Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
f055995
fix(chat): mark tool images beyond the preview limit (#23595)
only21mil Oct 22, 2026
b9aaff4
fix(web): provider updates no longer pop toasts on launch (#23233)
flamboh Oct 22, 2026
f460ddb
fix(server): probe the Windows startup environment asynchronously (#2…
UtkarshUsername Oct 22, 2026
5e8c5eb
fix(usage): count initial Codex requests with inherited totals (#23729)
PixPMusic Oct 22, 2026
4eae8ae
chore(mobile): bump app version to 2.1.0
t3-code[bot] Oct 22, 2026
e54e71d
fix(web): let toast content use the full accordion width (#23777)
Yash-Singh1 Oct 22, 2026
044f072
fix(web): sidebar follows the active thread after history navigation …
juliusmarminge Oct 22, 2026
fd1063b
fix(server): keep subagent transcript updates off shell stream (#23783)
Yash-Singh1 Oct 22, 2026
22840ab
fix(deps): pin all patched package versions (#23798)
juliusmarminge Oct 22, 2026
52c2b38
docs: document the GitCafe mirror and refresh the dev setup (#23808)
juliusmarminge Oct 22, 2026
d7f3b72
fix: no more em dashes in product copy (#23799)
t3dotgg Oct 22, 2026
ef92441
chore(release): prepare v0.1.2
t3-code[bot] Oct 22, 2026
2c8bdf6
chore(mobile): bump Clerk Expo SDKs to the new native client sync (#2…
wobsoriano Oct 22, 2026
ff31a2a
fix(mobile): capture folded and unfolded Duo store screenshots (#23849)
juliusmarminge Oct 22, 2026
cf3acd9
fix(server): preserve typed requirements as the RPC group grows (#23813)
juliusmarminge Oct 22, 2026
b3c0109
fix(server): wake PR watches when no checks report (#23863)
juliusmarminge Oct 22, 2026
11adcb0
fix(server): resume Codex parents after native children finish (#23840)
juliusmarminge Oct 22, 2026
f9c1d02
fix(gitcafe): authored lists, merge progress, and author reviews matc…
juliusmarminge Oct 22, 2026
52bb5c8
fix(forgejo): merges follow the repository's delete-branch setting (#…
juliusmarminge Oct 22, 2026
200dad3
fix(web): keep PR check counts in sync (#23548)
juliusmarminge Oct 22, 2026
c7e3993
fix(server): speed up shell snapshots on large databases (#23751)
Yash-Singh1 Oct 22, 2026
478fdfc
fix(server): keep managed Codex token renewal in the server (#21786)
juliusmarminge Oct 22, 2026
f5cf9a0
fix(server): renew active managed Codex turns through native auth (#2…
juliusmarminge Oct 22, 2026
e78297d
feat(web): telemetry export settings show where the running endpoint …
yordis Oct 22, 2026
23bd753
fix(ui): preserve tool icon detail in light mode (#23896)
juliusmarminge Oct 22, 2026
1c8e79e
fix(mcp): accept GitCafe pull request URLs in link/unlink/watch tools…
juliusmarminge Oct 23, 2026
5127302
feat(settings): add thread title instructions (#21882)
CadenEl Oct 23, 2026
18e2742
fix(mobile): undo toasts keep their action on one row (#23910)
saphid Oct 23, 2026
50e151c
docs(connect): correct the relay webhook endpoint key (#23526)
juliusmarminge Oct 23, 2026
05cd55d
fix(mobile): center Android composer text and pad wrapped drafts (#23…
PixPMusic Oct 23, 2026
09bb9f1
fix(server): wake PR watches when remaining CI checks finish (#23904)
juliusmarminge Oct 23, 2026
a8dba9c
fix(mobile): the empty composer row shows only the provider icon (#23…
flamboh Oct 23, 2026
6ed47b5
fix(server): route SQLite reads around writer contention (#23902)
Yash-Singh1 Oct 23, 2026
27e118c
Merge remote-tracking branch 'upstream/main' into yordis/chore-sync-u…
yordis Oct 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Dev container for T3 Code. Mirrors CI (ubuntu-24.04, Node 24, Rust stable)
// Dev container for T3 Code. Mirrors CI (ubuntu-24.04, Node 26, Rust stable)
// and the canonical setup in docs/operations/development.md: global `vp`, `vp i`.
// Contributor doc: docs/internals/devcontainer.md
{
Expand All @@ -8,7 +8,7 @@
// nodeGypDependencies (default true) brings python3/make/g++, which Linux
// needs for node-pty's node-gyp fallback (its prebuilds are mac/win only).
"ghcr.io/devcontainers/features/node:2": {
"version": "24"
"version": "26"
},
// native/resource-monitor (edition 2024, needs stable >= 1.85). The server
// degrades gracefully without the binary, but CI checks cargo fmt + test.
Expand Down
5 changes: 4 additions & 1 deletion .github/workflows/mobile-showcase-screenshots.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ env:

jobs:
ios:
name: iPhone 6.9, iPhone 6.5, and iPad 13
name: iPhone, iPhone Duo, and iPad 13
if: inputs.platform == 'all' || inputs.platform == 'ios'
runs-on: macos-26
# Capturing every palette multiplies the device matrix by six, and only the
Expand Down Expand Up @@ -87,6 +87,9 @@ jobs:
brew install cameroncooke/axe/axe
axe --version

- name: Install foldable simulator controls
run: npm install --global agent-device@0.21.25

- name: Capture iOS showcase
run: pnpm screenshots:mobile --platform ios --appearance "${{ inputs.appearance }}" --theme "${{ inputs.theme }}"

Expand Down
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ For authorized mobile verification, a missing or outdated native client is a bui

- Never make a PR unless the developer explicitly asks you to do so.
- PRs target this fork (`TrogonStack/t3code`), never `pingdotgg/t3code`, unless the developer asks for the change to go upstream.
- If `origin` is git.cafe, follow [GitCafe mirror](docs/operations/development.md#gitcafe-mirror-optional): use `cafe` for existing PRs, issues, comments and labels, but push and open PRs on GitHub, where CI runs.
- Conventional commit titles, plain language: `fix(web): new threads no longer spike CPU`.
- Body: the problem in a sentence or two, then how you fixed it.
- UI changes need before/after images. Motion or timing needs a short video.
Expand Down
2 changes: 1 addition & 1 deletion apps/desktop/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@t3tools/desktop",
"version": "0.1.1",
"version": "0.1.2",
"private": true,
"type": "module",
"main": "dist-electron/boot.cjs",
Expand Down
8 changes: 4 additions & 4 deletions apps/desktop/src/wsl/DesktopWslEnvironment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -463,14 +463,14 @@ cd ${shellQuote(linuxServerDir)} && node <<'NODE' >/dev/null 2>&1
// The sentinel must be a package the CLI bundle leaves external. It used to be
// "effect", back when the bundle externalized its runtime deps and the whole
// node_modules tree was unpacked. The bundle now inlines its JS dependencies,
// so "effect" no longer exists on disk and only the native packages do —
// resolving node-pty is what actually validates the unpacked tree.
// so "effect" no longer exists on disk and only the native packages do.
// Resolving node-pty is what actually validates the unpacked tree.
try { require.resolve("node-pty/package.json"); } catch (_e) { process.exit(3); }
const fs = require("node:fs");
const path = require("node:path");
const pkgDir = path.dirname(require.resolve("node-pty/package.json"));
// node-pty 1.x is N-API based, so a single Linux pty.node is ABI-stable across
// Node versions — require() succeeding IS the real compatibility test. Look in
// Node versions, so require() succeeding IS the real compatibility test. Look in
// the same places node-pty's own loader does.
const candidates = [
path.join(pkgDir, "build", "Release", "pty.node"),
Expand Down Expand Up @@ -699,7 +699,7 @@ const ensureNodePtyImpl = Effect.fn("DesktopWslEnvironment.ensureNodePtyImpl")(f
return {
ok: false,
reason:
'WSL server dependencies could not be loaded (for example "node-pty"). The native packages the server needs are not unpacked where the WSL distro\'s Node can read them — this is a packaging problem with this build. Please report it.',
'WSL server dependencies could not be loaded (for example "node-pty"). The native packages the server needs are not unpacked where the WSL distro\'s Node can read them. This is a packaging problem with this build. Please report it.',
fatal: true,
} as const;
}
Expand Down
2 changes: 1 addition & 1 deletion apps/marketing/src/layouts/Layout.astro
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ const canonicalUrl = new URL(Astro.url.pathname, Astro.site);
href={GITHUB_REPOSITORY_URL}
target="_blank"
rel="noopener noreferrer"
aria-label={`Star T3 Code on GitHub — ${MARKETING_STATS.githubStars} stars`}
aria-label={`Star T3 Code on GitHub, ${MARKETING_STATS.githubStars} stars`}
>
<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
<path d="M12 2.3l2.9 5.88 6.49.94-4.7 4.58 1.11 6.47L12 17.12l-5.8 3.05 1.11-6.47-4.7-4.58 6.49-.94L12 2.3z"/>
Expand Down
2 changes: 1 addition & 1 deletion apps/marketing/src/pages/download.astro
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const imageProps = {
} satisfies Partial<ComponentProps<typeof Image>>;
---

<Layout title="Download — T3 Code" description="Download T3 Code for macOS, Windows, or Linux.">
<Layout title="Download | T3 Code" description="Download T3 Code for macOS, Windows, or Linux.">
<div class="download-page" id="download-page" data-channel="stable">
<!-- The sky lives behind the header and fades to the page. It only shows on the nightly channel. -->
<header class="download-head">
Expand Down
2 changes: 1 addition & 1 deletion apps/marketing/src/pages/legal.astro
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const documents = [
---

<Layout
title="Legal — T3 Code"
title="Legal | T3 Code"
description="Privacy, terms, and security documents for T3 Code."
pageClass="legal-document-page"
>
Expand Down
2 changes: 1 addition & 1 deletion apps/marketing/src/pages/privacy-policy.astro
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const sections = [
---

<LegalPage
title="Privacy Policy — T3 Code"
title="Privacy Policy | T3 Code"
description="How T3 Tools, Inc. handles information when you use T3 Code, app.t3.codes, and t3.codes."
heading="T3 Code Privacy Policy"
lede="This Privacy Policy describes how T3 Tools, Inc. collects, uses, and shares personal information when you use the T3 Code desktop, mobile, and hosted web applications, visit the t3.codes marketing site, or use the optional T3 Connect service."
Expand Down
2 changes: 1 addition & 1 deletion apps/marketing/src/pages/security-policy.astro
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const sections = [
---

<LegalPage
title="Security Policy — T3 Code"
title="Security Policy | T3 Code"
description="How to report security issues in T3 Code and how T3 Tools approaches product security."
heading="T3 Code Security Policy"
lede="Security is a shared responsibility. This policy explains how to report a vulnerability, how we protect T3 Tools-operated services, and how you can secure the environments and providers you connect to T3 Code."
Expand Down
6 changes: 3 additions & 3 deletions apps/marketing/src/pages/terms-of-service.astro
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const sections = [
---

<LegalPage
title="Terms of Service — T3 Code"
title="Terms of Service | T3 Code"
description="The terms that govern your use of T3 Code, app.t3.codes, T3 Connect, and t3.codes."
heading="T3 Code Terms of Service"
lede="These Terms govern your use of T3 Code, including its desktop, mobile, and hosted applications, the optional T3 Connect service, and the t3.codes website."
Expand Down Expand Up @@ -197,8 +197,8 @@ const sections = [
immediately where needed to prevent harm or comply with law.
</p>
<p>
Provisions that by their nature should survive termination—including ownership, disclaimers,
limitations of liability, indemnification, and dispute terms—will survive.
Provisions that by their nature should survive termination (including ownership, disclaimers,
limitations of liability, indemnification, and dispute terms) will survive.
</p>
</section>

Expand Down
2 changes: 1 addition & 1 deletion apps/mobile/app.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ const config: ExpoConfig = {
slug: "t3-code",
platforms: ["ios", "android"],
scheme: variant.scheme,
version: repoEnv.T3CODE_MOBILE_VERSION ?? "2.0.0",
version: repoEnv.T3CODE_MOBILE_VERSION ?? "2.1.0",
runtimeVersion: {
// Development manifests resolve on every launch, so avoid fingerprint's
// expensive native-project calculation there. Preview and production stay
Expand Down
2 changes: 1 addition & 1 deletion apps/mobile/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
},
"dependencies": {
"@clerk/expo": "catalog:",
"@clerk/expo-native-components": "0.2.0",
"@clerk/expo-native-components": "0.4.0",
"@effect/atom-react": "catalog:",
"@expo-google-fonts/dm-sans": "^0.4.2",
"@expo/metro-runtime": "~58.0.14",
Expand Down
16 changes: 10 additions & 6 deletions apps/mobile/src/components/ui/Toast.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { MOBILE_SHAPE } from "../../lib/designTokens";
import { useEffect } from "react";
import { AccessibilityInfo, Platform, View } from "react-native";
import { AccessibilityInfo, Platform, View, useWindowDimensions } from "react-native";

import { AppText } from "./AppText";
import { Button } from "./Button";
Expand All @@ -20,6 +20,13 @@ export interface ToastProps {

/** The owning screen places and dismisses feedback; actions are never implicit. */
export function Toast(props: ToastProps) {
const { fontScale } = useWindowDimensions();
// A one-line message keeps its action on the same row. Descriptions and
// accessibility text sizes need the full width, so the action moves below.
const inlineAction = !props.description && fontScale < 1.5;
const action = props.action ? (
<Button label={props.action.label} onPress={props.action.onPress} />
) : null;
useEffect(() => {
if (Platform.OS === "ios") AccessibilityInfo.announceForAccessibility(props.message);
}, [props.message]);
Expand Down Expand Up @@ -47,15 +54,12 @@ export function Toast(props: ToastProps) {
</AppText>
) : null}
</View>
{inlineAction ? action : null}
{props.onDismiss ? (
<IconButton accessibilityLabel="Dismiss message" icon="xmark" onPress={props.onDismiss} />
) : null}
</View>
{props.action ? (
<View className="mt-2 self-end">
<Button label={props.action.label} onPress={props.action.onPress} />
</View>
) : null}
{action && !inlineAction ? <View className="mt-2 self-end">{action}</View> : null}
</GlassSurface>
);
}
67 changes: 27 additions & 40 deletions apps/mobile/src/features/showcase/ShowcaseCaptureCoordinator.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
import { useEffect, useRef, useState, useSyncExternalStore } from "react";
import { Keyboard, View } from "react-native";
import {
CommonActions,
type NavigationState,
type PartialState,
StackActions,
useNavigation,
} from "@react-navigation/native";
import { CommonActions, StackActions, useNavigation } from "@react-navigation/native";
import { AsyncResult } from "effect/reactivity";
import { requireOptionalNativeModule } from "expo";

import { useConnectionController } from "../connection/useConnectionController";
import { useAppearancePreferences } from "../settings/appearance/AppearancePreferencesProvider";
Expand Down Expand Up @@ -42,8 +37,6 @@ import { stageShowcaseAgentActivity } from "./stageShowcaseAgentActivity";
const SHOWCASE_ENABLED = process.env.EXPO_PUBLIC_SHOWCASE === "1";
const SHOWCASE_THREAD_ID = "remote-command-center";

type ShowcaseResetRoute = PartialState<NavigationState>["routes"][number];

function sceneFromPathname(pathname: string): ShowcaseScene | null {
const routePath = pathname.split(/[?#]/u, 1)[0] ?? pathname;
if (routePath === "/settings" || routePath.endsWith("/settings/environments")) {
Expand All @@ -63,6 +56,18 @@ export function ShowcaseCaptureCoordinator(props: { readonly pathname: string })

function EnabledShowcaseCaptureCoordinator(props: { readonly pathname: string }) {
const navigation = useNavigation();
useEffect(() => {
const menu = requireOptionalNativeModule<{
closeMenu(): void;
setToolsButtonVisible(visible: boolean): void;
}>("ExpoDevMenu");
// The dev menu can open after bundle loading and block orientation requests.
const timer = setInterval(() => {
menu?.closeMenu();
menu?.setToolsButtonVisible(false);
}, 1_000);
return () => clearInterval(timer);
}, []);
const { connectPairingUrl } = useConnectionController();
const {
isReady: appearancePreferencesReady,
Expand Down Expand Up @@ -237,40 +242,22 @@ function EnabledShowcaseCaptureCoordinator(props: { readonly pathname: string })
navigation.dispatch(CommonActions.reset({ index: 0, routes: [{ name: "Home" }] }));
return;
}
const routes: ShowcaseResetRoute[] = [{ name: "Home" }];
if (requestedScene === "environments") {
routes.push({
name: "SettingsSheet",
state: {
index: 0,
routes: [
{
name: "SettingsContent",
state: {
index: 1,
routes: [{ name: "Settings" }, { name: "SettingsEnvironments" }],
},
},
],
},
});
navigation.dispatch(
CommonActions.navigate("SettingsSheet", {
screen: "SettingsContent",
params: { screen: "SettingsEnvironments" },
}),
);
} else if (requestedScene === "terminal") {
navigation.dispatch(
CommonActions.navigate("ThreadTerminal", { ...params, terminalId: "term-1" }),
);
} else if (requestedScene === "review") {
navigation.dispatch(CommonActions.navigate("ThreadReview", params));
} else {
routes.push({ name: "Thread", params });
if (requestedScene === "terminal") {
routes.push({

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Showcase navigation leaves prior screens

Medium Severity

Scene changes now navigate onto SettingsSheet, ThreadTerminal, ThreadReview, or Thread instead of resetting the stack to that exact route. A settings sheet or earlier screen can stay presented when the capture path moves to another scene, so showcase shots can capture the wrong surface.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 27e118c. Configure here.

name: "ThreadTerminal",
params: { ...params, terminalId: "term-1" },
});
} else if (requestedScene === "review") {
routes.push({ name: "ThreadReview", params });
}
navigation.dispatch(CommonActions.navigate("Thread", params));
}
navigation.dispatch(
CommonActions.reset({
index: routes.length - 1,
routes,
}),
);
}, [hasFixture, navigation, requestedScene, scene, showcaseThread]);

useEffect(() => {
Expand Down
11 changes: 4 additions & 7 deletions apps/mobile/src/features/threads/ThreadComposer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,8 @@ export function useCompactComposerEditor(text: ScaledTextRole, value: string) {
const rowWidth = useSharedValue(0);
const editorX = useSharedValue(0);
const editorWidth = useSharedValue(0);
const inset = Platform.OS === "android" ? 0 : collapsedEditorInset(text);
const inset =
Platform.OS === "android" ? COLLAPSED_EDITOR_DEFAULT_INSET : collapsedEditorInset(text);
const minimum = Math.max(INLINE_EDITOR_HEIGHT, Math.ceil(text.lineHeight) + 2 * inset);
const height = Math.max(
minimum,
Expand Down Expand Up @@ -216,7 +217,7 @@ export function useCompactComposerEditor(text: ScaledTextRole, value: string) {
}
},
editorProps: {
singleLineCentered: false,
singleLineCentered: !isExpanded,
scrollEnabled: Platform.OS === "android" || contentHeight >= text.lineHeight * 4,
contentInsetVertical: inset,
onContentSizeChange: (size: { width: number; height: number }) => {
Expand Down Expand Up @@ -848,8 +849,6 @@ export const ThreadComposer = function ThreadComposer(props: ThreadComposerProps
</>
) : null;

// The row and the card's toolbar share this picker. It shrinks to the provider
// icon in the row once the draft has text, so the draft keeps the width.
const modelControl = (
<View className="min-w-0 shrink">
<ComposerModelControl
Expand All @@ -860,9 +859,7 @@ export const ThreadComposer = function ThreadComposer(props: ThreadComposerProps
reportedSelection={props.reportedModelSelection}
prompt={draftMessage}
surfaceColor={composerPanel}
iconOnly={
(draftMessage.length > 0 || stripAttachments.length > 0) && !compactEditor.isExpanded
}
iconOnly={!compactEditor.isExpanded}
onPress={openSettings}
/>
</View>
Expand Down
7 changes: 5 additions & 2 deletions apps/mobile/src/features/threads/thread-work-log.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1610,14 +1610,17 @@ function ToolActivityImage(props: {
<View
style={[
StyleSheet.absoluteFill,
props.themeAppearance === "light" ? { filter: [{ brightness: 0.6 }] } : undefined,
props.themeAppearance === "light" ? { filter: [{ brightness: 0.7 }] } : undefined,
]}
>
<Image
source={props.source}
cachePolicy="memory-disk"
contentFit="contain"
style={[StyleSheet.absoluteFill, { opacity: loaded ? 0.7 : 0 }]}
style={[
StyleSheet.absoluteFill,
{ opacity: loaded ? (props.themeAppearance === "dark" ? 0.7 : 1) : 0 },
]}
onLoad={() => setLoaded(true)}
onError={() => setFailed(true)}
/>
Expand Down
2 changes: 1 addition & 1 deletion apps/mobile/src/lib/threadActivityInspector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ export function buildThreadActivityInspector(
addBlock(blocks, "Query", item.pattern);
for (const result of item.results ?? []) {
fileLinks.push({
label: result.preview ? `${result.fileName} — ${result.preview}` : result.fileName,
label: result.preview ? `${result.fileName}: ${result.preview}` : result.fileName,
path: result.fileName,
...(result.line === undefined ? {} : { line: result.line }),
});
Expand Down
2 changes: 1 addition & 1 deletion apps/server/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "t3",
"version": "0.1.1",
"version": "0.1.2",
"license": "MIT",
"repository": {
"type": "git",
Expand Down
2 changes: 1 addition & 1 deletion apps/server/scripts/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ const buildCmd = Command.make(
yield* applyDevelopmentIconOverrides(repoRoot, serverDir);
yield* Effect.log("[cli] Bundled web app into dist/client");
} else {
yield* Effect.logWarning("[cli] Web dist not found — skipping client bundle.");
yield* Effect.logWarning("[cli] Web dist not found. Skipping client bundle.");
}
}),
).pipe(Command.withDescription("Build the server package (tsdown + bundle web client)."));
Expand Down
Loading
Loading