Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 AGENTS.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -7,7 +7,7 @@

## Project Snapshot

T3 Code is a minimal web GUI for using coding agents like Codex and Claude.
k3code is a minimal web GUI for using coding agents like Codex and Claude.

This repository is a VERY EARLY WIP. Proposing sweeping changes that improve long-term maintainability is encouraged.

Expand All@@ -32,7 +32,7 @@ Long term maintainability is a core priority. If you add new functionality, firs

## Codex App Server (Important)

T3 Code is currently Codex-first. The server starts `codex app-server` (JSON-RPC over stdio) per provider session, then streams structured events to the browser through WebSocket push messages.
k3code is currently Codex-first. The server starts `codex app-server` (JSON-RPC over stdio) per provider session, then streams structured events to the browser through WebSocket push messages.

How we use it in this codebase:

Expand Down
2 changes: 1 addition & 1 deletion KEYBINDINGS.md
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
# Keybindings

T3 Code reads keybindings from:
k3code reads keybindings from:

- `~/.t3/keybindings.json`

Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
# T3 Code
# k3code

T3 Code is a minimal web GUI for coding agents (currently Codex and Claude, more coming soon).
k3code is a minimal web GUI for coding agents (currently Codex and Claude, more coming soon).

## Installation

> [!WARNING]
> T3 Code currently supports Codex, Claude, and OpenCode.
> k3code currently supports Codex, Claude, and OpenCode.
> Install and authenticate at least one provider before use:
>
> - Codex: install [Codex CLI](https://developers.openai.com/codex/cli) and run `codex login`
Expand Down
2 changes: 1 addition & 1 deletion REMOTE.md
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
# Remote Access

Use this when you want to connect to a T3 Code server from another device such as a phone, tablet, or separate desktop app.
Use this when you want to connect to a k3code server from another device such as a phone, tablet, or separate desktop app.

## Recommended Setup

Expand Down
2 changes: 1 addition & 1 deletion apps/desktop/package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -28,5 +28,5 @@
"typescript": "catalog:",
"vitest": "catalog:"
},
"productName": "T3 Code (Alpha)"
"productName": "k3code (Alpha)"
}
4 changes: 2 additions & 2 deletions apps/desktop/scripts/electron-launcher.mjs
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
// This file mostly exists because we want dev mode to say "T3 Code (Dev)" instead of "electron"
// This file mostly exists because we want dev mode to say "k3code (Dev)" instead of "electron"

import { spawnSync } from "node:child_process";
import {
Expand All@@ -17,7 +17,7 @@ import { dirname, join, resolve } from "node:path";
import { fileURLToPath } from "node:url";

const isDevelopment = Boolean(process.env.VITE_DEV_SERVER_URL);
const APP_DISPLAY_NAME = isDevelopment ? "T3 Code (Dev)" : "T3 Code (Alpha)";
const APP_DISPLAY_NAME = isDevelopment ? "k3code (Dev)" : "k3code (Alpha)";
const APP_BUNDLE_ID = isDevelopment ? "com.t3tools.t3code.dev" : "com.t3tools.t3code";
const LAUNCHER_VERSION = 2;

Expand Down
4 changes: 2 additions & 2 deletions apps/desktop/src/appBranding.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -39,9 +39,9 @@ describe("resolveDesktopAppBranding", () => {
appVersion: "0.0.17-nightly.20260414.1",
}),
).toEqual({
baseName: "T3 Code",
baseName: "k3code",
stageLabel: "Nightly",
displayName: "T3 Code (Nightly)",
displayName: "k3code (Nightly)",
});
});
});
2 changes: 1 addition & 1 deletion apps/desktop/src/appBranding.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,7 +2,7 @@ import type { DesktopAppBranding, DesktopAppStageLabel } from "@t3tools/contract

import { isNightlyDesktopVersion } from "./updateChannels.ts";

const APP_BASE_NAME = "T3 Code";
const APP_BASE_NAME = "k3code";

export function resolveDesktopAppStageLabel(input: {
readonly isDevelopment: boolean;
Expand Down
1 change: 1 addition & 0 deletions apps/desktop/src/clientPersistence.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -53,6 +53,7 @@ const clientSettings: ClientSettings = {
confirmThreadArchive: true,
confirmThreadDelete: false,
diffWordWrap: true,
hideWindowControls: false,
favorites: [],
providerModelPreferences: {},
sidebarProjectGroupingMode: "repository_path",
Expand Down
19 changes: 13 additions & 6 deletions apps/desktop/src/main.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -31,6 +31,7 @@ import type {
DesktopUpdateCheckResult,
DesktopUpdateState,
} from "@t3tools/contracts";
import { DEFAULT_CLIENT_SETTINGS } from "@t3tools/contracts/settings";
import { autoUpdater } from "electron-updater";

import type { ContextMenuItem } from "@t3tools/contracts";
Expand DownExpand Up@@ -122,7 +123,7 @@ const APP_USER_MODEL_ID = isDevelopment ? "com.t3tools.t3code.dev" : "com.t3tool
const LINUX_DESKTOP_ENTRY_NAME = isDevelopment ? "t3code-dev.desktop" : "t3code.desktop";
const LINUX_WM_CLASS = isDevelopment ? "t3code-dev" : "t3code";
const USER_DATA_DIR_NAME = isDevelopment ? "t3code-dev" : "t3code";
const LEGACY_USER_DATA_DIR_NAME = isDevelopment ? "T3 Code (Dev)" : "T3 Code (Alpha)";
const LEGACY_USER_DATA_DIR_NAME = isDevelopment ? "k3code (Dev)" : "k3code (Alpha)";
const COMMIT_HASH_PATTERN = /^[0-9a-f]{7,40}$/i;
const COMMIT_HASH_DISPLAY_LENGTH = 12;
const LOG_DIR = Path.join(STATE_DIR, "logs");
Expand DownExpand Up@@ -228,6 +229,7 @@ let restoreStdIoCapture: (() => void) | null = null;
let backendObservabilitySettings = readPersistedBackendObservabilitySettings();
let desktopSettings = readDesktopSettings(DESKTOP_SETTINGS_PATH, app.getVersion());
let desktopServerExposureMode: DesktopServerExposureMode = desktopSettings.serverExposureMode;
let clientSettings = readClientSettings(CLIENT_SETTINGS_PATH) ?? DEFAULT_CLIENT_SETTINGS;

let destructiveMenuIconCache: Electron.NativeImage | null | undefined;
const expectedBackendExitChildren = new WeakSet<ChildProcess.ChildProcess>();
Expand DownExpand Up@@ -796,7 +798,7 @@ function handleFatalStartupError(stage: string, error: unknown): void {
console.error(`[desktop] fatal startup error (${stage})`, error);
if (!isQuitting) {
isQuitting = true;
dialog.showErrorBox("T3 Code failed to start", `Stage: ${stage}\n${message}${detail}`);
dialog.showErrorBox("k3code failed to start", `Stage: ${stage}\n${message}${detail}`);
}
stopBackend();
restoreStdIoCapture?.();
Expand DownExpand Up@@ -901,7 +903,7 @@ async function checkForUpdatesFromMenu(): Promise<void> {
void dialog.showMessageBox({
type: "info",
title: "You're up to date!",
message: `T3 Code ${updateState.currentVersion} is currently the newest version available.`,
message: `k3code ${updateState.currentVersion} is currently the newest version available.`,
buttons: ["OK"],
});
} else if (updateState.status === "error") {
Expand DownExpand Up@@ -1031,7 +1033,7 @@ function resolveIconPath(ext: "ico" | "icns" | "png"): string | null {
*
* Electron derives the default userData path from `productName` in
* package.json, which currently produces directories with spaces and
* parentheses (e.g. `~/.config/T3 Code (Alpha)` on Linux). This is
* parentheses (e.g. `~/.config/k3code (Alpha)` on Linux). This is
* unfriendly for shell usage and violates Linux naming conventions.
*
* We override it to a clean lowercase name (`t3code`). If the legacy
Expand DownExpand Up@@ -1580,15 +1582,17 @@ function registerIpcHandlers(): void {
});

ipcMain.removeHandler(GET_CLIENT_SETTINGS_CHANNEL);
ipcMain.handle(GET_CLIENT_SETTINGS_CHANNEL, async () => readClientSettings(CLIENT_SETTINGS_PATH));
ipcMain.handle(GET_CLIENT_SETTINGS_CHANNEL, async () => clientSettings);

ipcMain.removeHandler(SET_CLIENT_SETTINGS_CHANNEL);
ipcMain.handle(SET_CLIENT_SETTINGS_CHANNEL, async (_event, rawSettings: unknown) => {
if (typeof rawSettings !== "object" || rawSettings === null) {
throw new Error("Invalid client settings payload.");
}

writeClientSettings(CLIENT_SETTINGS_PATH, rawSettings as ClientSettings);
clientSettings = rawSettings as ClientSettings;
writeClientSettings(CLIENT_SETTINGS_PATH, clientSettings);
syncAllWindowAppearance();
});

ipcMain.removeHandler(GET_SAVED_ENVIRONMENT_REGISTRY_CHANNEL);
Expand DownExpand Up@@ -1923,6 +1927,9 @@ function syncWindowAppearance(window: BrowserWindow): void {
if (typeof titleBarOverlay === "object") {
window.setTitleBarOverlay(titleBarOverlay);
}
if (process.platform === "darwin") {
window.setWindowButtonVisibility(!clientSettings.hideWindowControls);
}
}

function syncAllWindowAppearance(): void {
Expand Down
4 changes: 2 additions & 2 deletions apps/marketing/src/layouts/Layout.astro
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,8 +5,8 @@ interface Props {
}

const {
title = "T3 Code",
description = "T3 Code — The best way to code with AI.",
title = "k3code",
description = "k3code — The best way to code with AI.",
} = Astro.props;
---

Expand Down
4 changes: 2 additions & 2 deletions apps/marketing/src/pages/download.astro
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,8 +3,8 @@ import Layout from "../layouts/Layout.astro";
import { RELEASES_URL } from "../lib/releases";
---

<Layout title="Download — T3 Code" description="Download T3 Code for macOS, Windows, or Linux.">
<h1 class="heading">Download T3 Code</h1>
<Layout title="Download — k3code" description="Download k3code for macOS, Windows, or Linux.">
<h1 class="heading">Download k3code</h1>
<p class="subheading">
<span id="version-label">Loading latest release&hellip;</span>
<a id="changelog-link" class="changelog-link" href="#" target="_blank" rel="noopener noreferrer" style="display:none">View changelog<span aria-hidden="true"> &#8599;</span></a>
Expand Down
4 changes: 2 additions & 2 deletions apps/marketing/src/pages/index.astro
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,7 +3,7 @@ import Layout from "../layouts/Layout.astro";
---

<Layout>
<h1 class="tagline">T3 Code is the best way to code with AI.</h1>
<h1 class="tagline">k3code is the best way to code with AI.</h1>

<a
id="download-btn"
Expand All@@ -19,7 +19,7 @@ import Layout from "../layouts/Layout.astro";
<a href="/download" class="other-platforms">Other platforms</a>

<div class="screenshot-wrap">
<img src="/screenshot.jpeg" alt="T3 Code" class="screenshot" />
<img src="/screenshot.jpeg" alt="k3code" class="screenshot" />
</div>
</Layout>

Expand Down
1 change: 1 addition & 0 deletions apps/server/package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -29,6 +29,7 @@
"@effect/platform-bun": "catalog:",
"@effect/platform-node": "catalog:",
"@effect/sql-sqlite-bun": "catalog:",
"@mariozechner/pi-coding-agent": "0.62.0",
"@opencode-ai/sdk": "^1.3.15",
"@pierre/diffs": "^1.1.0-beta.16",
"effect": "catalog:",
Expand Down
6 changes: 3 additions & 3 deletions apps/server/src/cli.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -1110,13 +1110,13 @@ const runServerCommand = (
});

const startCommand = Command.make("start", { ...sharedServerCommandFlags }).pipe(
Command.withDescription("Run the T3 Code server."),
Command.withDescription("Run the k3code server."),
Command.withHandler((flags) => runServerCommand(flags)),
);

const serveCommand = Command.make("serve", { ...sharedServerCommandFlags }).pipe(
Command.withDescription(
"Run the T3 Code server without opening a browser and print headless pairing details.",
"Run the k3code server without opening a browser and print headless pairing details.",
),
Command.withHandler((flags) =>
runServerCommand(flags, {
Expand All@@ -1127,7 +1127,7 @@ const serveCommand = Command.make("serve", { ...sharedServerCommandFlags }).pipe
);

export const cli = Command.make("t3", { ...sharedServerCommandFlags }).pipe(
Command.withDescription("Run the T3 Code server."),
Command.withDescription("Run the k3code server."),
Command.withHandler((flags) => runServerCommand(flags)),
Command.withSubcommands([startCommand, serveCommand, authCommand, projectCommand]),
);
2 changes: 1 addition & 1 deletion apps/server/src/git/Layers/OpenCodeTextGeneration.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -298,7 +298,7 @@ export const makeOpenCodeTextGeneration = Effect.fn("makeOpenCodeTextGeneration"
: {}),
});
const session = await client.session.create({
title: `T3 Code ${input.operation}`,
title: `k3code ${input.operation}`,
permission: [{ permission: "*", pattern: "*", action: "deny" }],
});
if (!session.data) {
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 AGENTS.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -7,7 +7,7 @@

## Project Snapshot

T3 Code is a minimal web GUI for using coding agents like Codex and Claude.
k3code is a minimal web GUI for using coding agents like Codex and Claude.

This repository is a VERY EARLY WIP. Proposing sweeping changes that improve long-term maintainability is encouraged.

Expand All@@ -32,7 +32,7 @@ Long term maintainability is a core priority. If you add new functionality, firs

## Codex App Server (Important)

T3 Code is currently Codex-first. The server starts `codex app-server` (JSON-RPC over stdio) per provider session, then streams structured events to the browser through WebSocket push messages.
k3code is currently Codex-first. The server starts `codex app-server` (JSON-RPC over stdio) per provider session, then streams structured events to the browser through WebSocket push messages.

How we use it in this codebase:

Expand Down
2 changes: 1 addition & 1 deletion KEYBINDINGS.md
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
# Keybindings

T3 Code reads keybindings from:
k3code reads keybindings from:

- `~/.t3/keybindings.json`

Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
# T3 Code
# k3code

T3 Code is a minimal web GUI for coding agents (currently Codex and Claude, more coming soon).
k3code is a minimal web GUI for coding agents (currently Codex and Claude, more coming soon).

## Installation

> [!WARNING]
> T3 Code currently supports Codex, Claude, and OpenCode.
> k3code currently supports Codex, Claude, and OpenCode.
> Install and authenticate at least one provider before use:
>
> - Codex: install [Codex CLI](https://developers.openai.com/codex/cli) and run `codex login`
Expand Down
2 changes: 1 addition & 1 deletion REMOTE.md
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
# Remote Access

Use this when you want to connect to a T3 Code server from another device such as a phone, tablet, or separate desktop app.
Use this when you want to connect to a k3code server from another device such as a phone, tablet, or separate desktop app.

## Recommended Setup

Expand Down
2 changes: 1 addition & 1 deletion apps/desktop/package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -28,5 +28,5 @@
"typescript": "catalog:",
"vitest": "catalog:"
},
"productName": "T3 Code (Alpha)"
"productName": "k3code (Alpha)"
}
4 changes: 2 additions & 2 deletions apps/desktop/scripts/electron-launcher.mjs
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
// This file mostly exists because we want dev mode to say "T3 Code (Dev)" instead of "electron"
// This file mostly exists because we want dev mode to say "k3code (Dev)" instead of "electron"

import { spawnSync } from "node:child_process";
import {
Expand All@@ -17,7 +17,7 @@ import { dirname, join, resolve } from "node:path";
import { fileURLToPath } from "node:url";

const isDevelopment = Boolean(process.env.VITE_DEV_SERVER_URL);
const APP_DISPLAY_NAME = isDevelopment ? "T3 Code (Dev)" : "T3 Code (Alpha)";
const APP_DISPLAY_NAME = isDevelopment ? "k3code (Dev)" : "k3code (Alpha)";
const APP_BUNDLE_ID = isDevelopment ? "com.t3tools.t3code.dev" : "com.t3tools.t3code";
const LAUNCHER_VERSION = 2;

Expand Down
4 changes: 2 additions & 2 deletions apps/desktop/src/appBranding.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -39,9 +39,9 @@ describe("resolveDesktopAppBranding", () => {
appVersion: "0.0.17-nightly.20260414.1",
}),
).toEqual({
baseName: "T3 Code",
baseName: "k3code",
stageLabel: "Nightly",
displayName: "T3 Code (Nightly)",
displayName: "k3code (Nightly)",
});
});
});
2 changes: 1 addition & 1 deletion apps/desktop/src/appBranding.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,7 +2,7 @@ import type { DesktopAppBranding, DesktopAppStageLabel } from "@t3tools/contract

import { isNightlyDesktopVersion } from "./updateChannels.ts";

const APP_BASE_NAME = "T3 Code";
const APP_BASE_NAME = "k3code";

export function resolveDesktopAppStageLabel(input: {
readonly isDevelopment: boolean;
Expand Down
1 change: 1 addition & 0 deletions apps/desktop/src/clientPersistence.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -53,6 +53,7 @@ const clientSettings: ClientSettings = {
confirmThreadArchive: true,
confirmThreadDelete: false,
diffWordWrap: true,
hideWindowControls: false,
favorites: [],
providerModelPreferences: {},
sidebarProjectGroupingMode: "repository_path",
Expand Down
19 changes: 13 additions & 6 deletions apps/desktop/src/main.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -31,6 +31,7 @@ import type {
DesktopUpdateCheckResult,
DesktopUpdateState,
} from "@t3tools/contracts";
import { DEFAULT_CLIENT_SETTINGS } from "@t3tools/contracts/settings";
import { autoUpdater } from "electron-updater";

import type { ContextMenuItem } from "@t3tools/contracts";
Expand DownExpand Up@@ -122,7 +123,7 @@ const APP_USER_MODEL_ID = isDevelopment ? "com.t3tools.t3code.dev" : "com.t3tool
const LINUX_DESKTOP_ENTRY_NAME = isDevelopment ? "t3code-dev.desktop" : "t3code.desktop";
const LINUX_WM_CLASS = isDevelopment ? "t3code-dev" : "t3code";
const USER_DATA_DIR_NAME = isDevelopment ? "t3code-dev" : "t3code";
const LEGACY_USER_DATA_DIR_NAME = isDevelopment ? "T3 Code (Dev)" : "T3 Code (Alpha)";
const LEGACY_USER_DATA_DIR_NAME = isDevelopment ? "k3code (Dev)" : "k3code (Alpha)";
const COMMIT_HASH_PATTERN = /^[0-9a-f]{7,40}$/i;
const COMMIT_HASH_DISPLAY_LENGTH = 12;
const LOG_DIR = Path.join(STATE_DIR, "logs");
Expand DownExpand Up@@ -228,6 +229,7 @@ let restoreStdIoCapture: (() => void) | null = null;
let backendObservabilitySettings = readPersistedBackendObservabilitySettings();
let desktopSettings = readDesktopSettings(DESKTOP_SETTINGS_PATH, app.getVersion());
let desktopServerExposureMode: DesktopServerExposureMode = desktopSettings.serverExposureMode;
let clientSettings = readClientSettings(CLIENT_SETTINGS_PATH) ?? DEFAULT_CLIENT_SETTINGS;

let destructiveMenuIconCache: Electron.NativeImage | null | undefined;
const expectedBackendExitChildren = new WeakSet<ChildProcess.ChildProcess>();
Expand DownExpand Up@@ -796,7 +798,7 @@ function handleFatalStartupError(stage: string, error: unknown): void {
console.error(`[desktop] fatal startup error (${stage})`, error);
if (!isQuitting) {
isQuitting = true;
dialog.showErrorBox("T3 Code failed to start", `Stage: ${stage}\n${message}${detail}`);
dialog.showErrorBox("k3code failed to start", `Stage: ${stage}\n${message}${detail}`);
}
stopBackend();
restoreStdIoCapture?.();
Expand DownExpand Up@@ -901,7 +903,7 @@ async function checkForUpdatesFromMenu(): Promise<void> {
void dialog.showMessageBox({
type: "info",
title: "You're up to date!",
message: `T3 Code ${updateState.currentVersion} is currently the newest version available.`,
message: `k3code ${updateState.currentVersion} is currently the newest version available.`,
buttons: ["OK"],
});
} else if (updateState.status === "error") {
Expand DownExpand Up@@ -1031,7 +1033,7 @@ function resolveIconPath(ext: "ico" | "icns" | "png"): string | null {
*
* Electron derives the default userData path from `productName` in
* package.json, which currently produces directories with spaces and
* parentheses (e.g. `~/.config/T3 Code (Alpha)` on Linux). This is
* parentheses (e.g. `~/.config/k3code (Alpha)` on Linux). This is
* unfriendly for shell usage and violates Linux naming conventions.
*
* We override it to a clean lowercase name (`t3code`). If the legacy
Expand DownExpand Up@@ -1580,15 +1582,17 @@ function registerIpcHandlers(): void {
});

ipcMain.removeHandler(GET_CLIENT_SETTINGS_CHANNEL);
ipcMain.handle(GET_CLIENT_SETTINGS_CHANNEL, async () => readClientSettings(CLIENT_SETTINGS_PATH));
ipcMain.handle(GET_CLIENT_SETTINGS_CHANNEL, async () => clientSettings);

ipcMain.removeHandler(SET_CLIENT_SETTINGS_CHANNEL);
ipcMain.handle(SET_CLIENT_SETTINGS_CHANNEL, async (_event, rawSettings: unknown) => {
if (typeof rawSettings !== "object" || rawSettings === null) {
throw new Error("Invalid client settings payload.");
}

writeClientSettings(CLIENT_SETTINGS_PATH, rawSettings as ClientSettings);
clientSettings = rawSettings as ClientSettings;
writeClientSettings(CLIENT_SETTINGS_PATH, clientSettings);
syncAllWindowAppearance();
});

ipcMain.removeHandler(GET_SAVED_ENVIRONMENT_REGISTRY_CHANNEL);
Expand DownExpand Up@@ -1923,6 +1927,9 @@ function syncWindowAppearance(window: BrowserWindow): void {
if (typeof titleBarOverlay === "object") {
window.setTitleBarOverlay(titleBarOverlay);
}
if (process.platform === "darwin") {
window.setWindowButtonVisibility(!clientSettings.hideWindowControls);
}
}

function syncAllWindowAppearance(): void {
Expand Down
4 changes: 2 additions & 2 deletions apps/marketing/src/layouts/Layout.astro
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,8 +5,8 @@ interface Props {
}

const {
title = "T3 Code",
description = "T3 Code — The best way to code with AI.",
title = "k3code",
description = "k3code — The best way to code with AI.",
} = Astro.props;
---

Expand Down
4 changes: 2 additions & 2 deletions apps/marketing/src/pages/download.astro
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,8 +3,8 @@ import Layout from "../layouts/Layout.astro";
import { RELEASES_URL } from "../lib/releases";
---

<Layout title="Download — T3 Code" description="Download T3 Code for macOS, Windows, or Linux.">
<h1 class="heading">Download T3 Code</h1>
<Layout title="Download — k3code" description="Download k3code for macOS, Windows, or Linux.">
<h1 class="heading">Download k3code</h1>
<p class="subheading">
<span id="version-label">Loading latest release&hellip;</span>
<a id="changelog-link" class="changelog-link" href="#" target="_blank" rel="noopener noreferrer" style="display:none">View changelog<span aria-hidden="true"> &#8599;</span></a>
Expand Down
4 changes: 2 additions & 2 deletions apps/marketing/src/pages/index.astro
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,7 +3,7 @@ import Layout from "../layouts/Layout.astro";
---

<Layout>
<h1 class="tagline">T3 Code is the best way to code with AI.</h1>
<h1 class="tagline">k3code is the best way to code with AI.</h1>

<a
id="download-btn"
Expand All@@ -19,7 +19,7 @@ import Layout from "../layouts/Layout.astro";
<a href="/download" class="other-platforms">Other platforms</a>

<div class="screenshot-wrap">
<img src="/screenshot.jpeg" alt="T3 Code" class="screenshot" />
<img src="/screenshot.jpeg" alt="k3code" class="screenshot" />
</div>
</Layout>

Expand Down
1 change: 1 addition & 0 deletions apps/server/package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -29,6 +29,7 @@
"@effect/platform-bun": "catalog:",
"@effect/platform-node": "catalog:",
"@effect/sql-sqlite-bun": "catalog:",
"@mariozechner/pi-coding-agent": "0.62.0",
"@opencode-ai/sdk": "^1.3.15",
"@pierre/diffs": "^1.1.0-beta.16",
"effect": "catalog:",
Expand Down
6 changes: 3 additions & 3 deletions apps/server/src/cli.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -1110,13 +1110,13 @@ const runServerCommand = (
});

const startCommand = Command.make("start", { ...sharedServerCommandFlags }).pipe(
Command.withDescription("Run the T3 Code server."),
Command.withDescription("Run the k3code server."),
Command.withHandler((flags) => runServerCommand(flags)),
);

const serveCommand = Command.make("serve", { ...sharedServerCommandFlags }).pipe(
Command.withDescription(
"Run the T3 Code server without opening a browser and print headless pairing details.",
"Run the k3code server without opening a browser and print headless pairing details.",
),
Command.withHandler((flags) =>
runServerCommand(flags, {
Expand All@@ -1127,7 +1127,7 @@ const serveCommand = Command.make("serve", { ...sharedServerCommandFlags }).pipe
);

export const cli = Command.make("t3", { ...sharedServerCommandFlags }).pipe(
Command.withDescription("Run the T3 Code server."),
Command.withDescription("Run the k3code server."),
Command.withHandler((flags) => runServerCommand(flags)),
Command.withSubcommands([startCommand, serveCommand, authCommand, projectCommand]),
);
2 changes: 1 addition & 1 deletion apps/server/src/git/Layers/OpenCodeTextGeneration.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -298,7 +298,7 @@ export const makeOpenCodeTextGeneration = Effect.fn("makeOpenCodeTextGeneration"
: {}),
});
const session = await client.session.create({
title: `T3 Code ${input.operation}`,
title: `k3code ${input.operation}`,
permission: [{ permission: "*", pattern: "*", action: "deny" }],
});
if (!session.data) {
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 AGENTS.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -7,7 +7,7 @@

## Project Snapshot

T3 Code is a minimal web GUI for using coding agents like Codex and Claude.
k3code is a minimal web GUI for using coding agents like Codex and Claude.

This repository is a VERY EARLY WIP. Proposing sweeping changes that improve long-term maintainability is encouraged.

Expand All@@ -32,7 +32,7 @@ Long term maintainability is a core priority. If you add new functionality, firs

## Codex App Server (Important)

T3 Code is currently Codex-first. The server starts `codex app-server` (JSON-RPC over stdio) per provider session, then streams structured events to the browser through WebSocket push messages.
k3code is currently Codex-first. The server starts `codex app-server` (JSON-RPC over stdio) per provider session, then streams structured events to the browser through WebSocket push messages.

How we use it in this codebase:

Expand Down
2 changes: 1 addition & 1 deletion KEYBINDINGS.md
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
# Keybindings

T3 Code reads keybindings from:
k3code reads keybindings from:

- `~/.t3/keybindings.json`

Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
# T3 Code
# k3code

T3 Code is a minimal web GUI for coding agents (currently Codex and Claude, more coming soon).
k3code is a minimal web GUI for coding agents (currently Codex and Claude, more coming soon).

## Installation

> [!WARNING]
> T3 Code currently supports Codex, Claude, and OpenCode.
> k3code currently supports Codex, Claude, and OpenCode.
> Install and authenticate at least one provider before use:
>
> - Codex: install [Codex CLI](https://developers.openai.com/codex/cli) and run `codex login`
Expand Down
2 changes: 1 addition & 1 deletion REMOTE.md
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
# Remote Access

Use this when you want to connect to a T3 Code server from another device such as a phone, tablet, or separate desktop app.
Use this when you want to connect to a k3code server from another device such as a phone, tablet, or separate desktop app.

## Recommended Setup

Expand Down
2 changes: 1 addition & 1 deletion apps/desktop/package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -28,5 +28,5 @@
"typescript": "catalog:",
"vitest": "catalog:"
},
"productName": "T3 Code (Alpha)"
"productName": "k3code (Alpha)"
}
4 changes: 2 additions & 2 deletions apps/desktop/scripts/electron-launcher.mjs
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
// This file mostly exists because we want dev mode to say "T3 Code (Dev)" instead of "electron"
// This file mostly exists because we want dev mode to say "k3code (Dev)" instead of "electron"

import { spawnSync } from "node:child_process";
import {
Expand All@@ -17,7 +17,7 @@ import { dirname, join, resolve } from "node:path";
import { fileURLToPath } from "node:url";

const isDevelopment = Boolean(process.env.VITE_DEV_SERVER_URL);
const APP_DISPLAY_NAME = isDevelopment ? "T3 Code (Dev)" : "T3 Code (Alpha)";
const APP_DISPLAY_NAME = isDevelopment ? "k3code (Dev)" : "k3code (Alpha)";
const APP_BUNDLE_ID = isDevelopment ? "com.t3tools.t3code.dev" : "com.t3tools.t3code";
const LAUNCHER_VERSION = 2;

Expand Down
4 changes: 2 additions & 2 deletions apps/desktop/src/appBranding.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -39,9 +39,9 @@ describe("resolveDesktopAppBranding", () => {
appVersion: "0.0.17-nightly.20260414.1",
}),
).toEqual({
baseName: "T3 Code",
baseName: "k3code",
stageLabel: "Nightly",
displayName: "T3 Code (Nightly)",
displayName: "k3code (Nightly)",
});
});
});
2 changes: 1 addition & 1 deletion apps/desktop/src/appBranding.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,7 +2,7 @@ import type { DesktopAppBranding, DesktopAppStageLabel } from "@t3tools/contract

import { isNightlyDesktopVersion } from "./updateChannels.ts";

const APP_BASE_NAME = "T3 Code";
const APP_BASE_NAME = "k3code";

export function resolveDesktopAppStageLabel(input: {
readonly isDevelopment: boolean;
Expand Down
1 change: 1 addition & 0 deletions apps/desktop/src/clientPersistence.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -53,6 +53,7 @@ const clientSettings: ClientSettings = {
confirmThreadArchive: true,
confirmThreadDelete: false,
diffWordWrap: true,
hideWindowControls: false,
favorites: [],
providerModelPreferences: {},
sidebarProjectGroupingMode: "repository_path",
Expand Down
19 changes: 13 additions & 6 deletions apps/desktop/src/main.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -31,6 +31,7 @@ import type {
DesktopUpdateCheckResult,
DesktopUpdateState,
} from "@t3tools/contracts";
import { DEFAULT_CLIENT_SETTINGS } from "@t3tools/contracts/settings";
import { autoUpdater } from "electron-updater";

import type { ContextMenuItem } from "@t3tools/contracts";
Expand DownExpand Up@@ -122,7 +123,7 @@ const APP_USER_MODEL_ID = isDevelopment ? "com.t3tools.t3code.dev" : "com.t3tool
const LINUX_DESKTOP_ENTRY_NAME = isDevelopment ? "t3code-dev.desktop" : "t3code.desktop";
const LINUX_WM_CLASS = isDevelopment ? "t3code-dev" : "t3code";
const USER_DATA_DIR_NAME = isDevelopment ? "t3code-dev" : "t3code";
const LEGACY_USER_DATA_DIR_NAME = isDevelopment ? "T3 Code (Dev)" : "T3 Code (Alpha)";
const LEGACY_USER_DATA_DIR_NAME = isDevelopment ? "k3code (Dev)" : "k3code (Alpha)";
const COMMIT_HASH_PATTERN = /^[0-9a-f]{7,40}$/i;
const COMMIT_HASH_DISPLAY_LENGTH = 12;
const LOG_DIR = Path.join(STATE_DIR, "logs");
Expand DownExpand Up@@ -228,6 +229,7 @@ let restoreStdIoCapture: (() => void) | null = null;
let backendObservabilitySettings = readPersistedBackendObservabilitySettings();
let desktopSettings = readDesktopSettings(DESKTOP_SETTINGS_PATH, app.getVersion());
let desktopServerExposureMode: DesktopServerExposureMode = desktopSettings.serverExposureMode;
let clientSettings = readClientSettings(CLIENT_SETTINGS_PATH) ?? DEFAULT_CLIENT_SETTINGS;

let destructiveMenuIconCache: Electron.NativeImage | null | undefined;
const expectedBackendExitChildren = new WeakSet<ChildProcess.ChildProcess>();
Expand DownExpand Up@@ -796,7 +798,7 @@ function handleFatalStartupError(stage: string, error: unknown): void {
console.error(`[desktop] fatal startup error (${stage})`, error);
if (!isQuitting) {
isQuitting = true;
dialog.showErrorBox("T3 Code failed to start", `Stage: ${stage}\n${message}${detail}`);
dialog.showErrorBox("k3code failed to start", `Stage: ${stage}\n${message}${detail}`);
}
stopBackend();
restoreStdIoCapture?.();
Expand DownExpand Up@@ -901,7 +903,7 @@ async function checkForUpdatesFromMenu(): Promise<void> {
void dialog.showMessageBox({
type: "info",
title: "You're up to date!",
message: `T3 Code ${updateState.currentVersion} is currently the newest version available.`,
message: `k3code ${updateState.currentVersion} is currently the newest version available.`,
buttons: ["OK"],
});
} else if (updateState.status === "error") {
Expand DownExpand Up@@ -1031,7 +1033,7 @@ function resolveIconPath(ext: "ico" | "icns" | "png"): string | null {
*
* Electron derives the default userData path from `productName` in
* package.json, which currently produces directories with spaces and
* parentheses (e.g. `~/.config/T3 Code (Alpha)` on Linux). This is
* parentheses (e.g. `~/.config/k3code (Alpha)` on Linux). This is
* unfriendly for shell usage and violates Linux naming conventions.
*
* We override it to a clean lowercase name (`t3code`). If the legacy
Expand DownExpand Up@@ -1580,15 +1582,17 @@ function registerIpcHandlers(): void {
});

ipcMain.removeHandler(GET_CLIENT_SETTINGS_CHANNEL);
ipcMain.handle(GET_CLIENT_SETTINGS_CHANNEL, async () => readClientSettings(CLIENT_SETTINGS_PATH));
ipcMain.handle(GET_CLIENT_SETTINGS_CHANNEL, async () => clientSettings);

ipcMain.removeHandler(SET_CLIENT_SETTINGS_CHANNEL);
ipcMain.handle(SET_CLIENT_SETTINGS_CHANNEL, async (_event, rawSettings: unknown) => {
if (typeof rawSettings !== "object" || rawSettings === null) {
throw new Error("Invalid client settings payload.");
}

writeClientSettings(CLIENT_SETTINGS_PATH, rawSettings as ClientSettings);
clientSettings = rawSettings as ClientSettings;
writeClientSettings(CLIENT_SETTINGS_PATH, clientSettings);
syncAllWindowAppearance();
});

ipcMain.removeHandler(GET_SAVED_ENVIRONMENT_REGISTRY_CHANNEL);
Expand DownExpand Up@@ -1923,6 +1927,9 @@ function syncWindowAppearance(window: BrowserWindow): void {
if (typeof titleBarOverlay === "object") {
window.setTitleBarOverlay(titleBarOverlay);
}
if (process.platform === "darwin") {
window.setWindowButtonVisibility(!clientSettings.hideWindowControls);
}
}

function syncAllWindowAppearance(): void {
Expand Down
4 changes: 2 additions & 2 deletions apps/marketing/src/layouts/Layout.astro
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,8 +5,8 @@ interface Props {
}

const {
title = "T3 Code",
description = "T3 Code — The best way to code with AI.",
title = "k3code",
description = "k3code — The best way to code with AI.",
} = Astro.props;
---

Expand Down
4 changes: 2 additions & 2 deletions apps/marketing/src/pages/download.astro
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,8 +3,8 @@ import Layout from "../layouts/Layout.astro";
import { RELEASES_URL } from "../lib/releases";
---

<Layout title="Download — T3 Code" description="Download T3 Code for macOS, Windows, or Linux.">
<h1 class="heading">Download T3 Code</h1>
<Layout title="Download — k3code" description="Download k3code for macOS, Windows, or Linux.">
<h1 class="heading">Download k3code</h1>
<p class="subheading">
<span id="version-label">Loading latest release&hellip;</span>
<a id="changelog-link" class="changelog-link" href="#" target="_blank" rel="noopener noreferrer" style="display:none">View changelog<span aria-hidden="true"> &#8599;</span></a>
Expand Down
4 changes: 2 additions & 2 deletions apps/marketing/src/pages/index.astro
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,7 +3,7 @@ import Layout from "../layouts/Layout.astro";
---

<Layout>
<h1 class="tagline">T3 Code is the best way to code with AI.</h1>
<h1 class="tagline">k3code is the best way to code with AI.</h1>

<a
id="download-btn"
Expand All@@ -19,7 +19,7 @@ import Layout from "../layouts/Layout.astro";
<a href="/download" class="other-platforms">Other platforms</a>

<div class="screenshot-wrap">
<img src="/screenshot.jpeg" alt="T3 Code" class="screenshot" />
<img src="/screenshot.jpeg" alt="k3code" class="screenshot" />
</div>
</Layout>

Expand Down
1 change: 1 addition & 0 deletions apps/server/package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -29,6 +29,7 @@
"@effect/platform-bun": "catalog:",
"@effect/platform-node": "catalog:",
"@effect/sql-sqlite-bun": "catalog:",
"@mariozechner/pi-coding-agent": "0.62.0",
"@opencode-ai/sdk": "^1.3.15",
"@pierre/diffs": "^1.1.0-beta.16",
"effect": "catalog:",
Expand Down
6 changes: 3 additions & 3 deletions apps/server/src/cli.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -1110,13 +1110,13 @@ const runServerCommand = (
});

const startCommand = Command.make("start", { ...sharedServerCommandFlags }).pipe(
Command.withDescription("Run the T3 Code server."),
Command.withDescription("Run the k3code server."),
Command.withHandler((flags) => runServerCommand(flags)),
);

const serveCommand = Command.make("serve", { ...sharedServerCommandFlags }).pipe(
Command.withDescription(
"Run the T3 Code server without opening a browser and print headless pairing details.",
"Run the k3code server without opening a browser and print headless pairing details.",
),
Command.withHandler((flags) =>
runServerCommand(flags, {
Expand All@@ -1127,7 +1127,7 @@ const serveCommand = Command.make("serve", { ...sharedServerCommandFlags }).pipe
);

export const cli = Command.make("t3", { ...sharedServerCommandFlags }).pipe(
Command.withDescription("Run the T3 Code server."),
Command.withDescription("Run the k3code server."),
Command.withHandler((flags) => runServerCommand(flags)),
Command.withSubcommands([startCommand, serveCommand, authCommand, projectCommand]),
);
2 changes: 1 addition & 1 deletion apps/server/src/git/Layers/OpenCodeTextGeneration.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -298,7 +298,7 @@ export const makeOpenCodeTextGeneration = Effect.fn("makeOpenCodeTextGeneration"
: {}),
});
const session = await client.session.create({
title: `T3 Code ${input.operation}`,
title: `k3code ${input.operation}`,
permission: [{ permission: "*", pattern: "*", action: "deny" }],
});
if (!session.data) {
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 AGENTS.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -7,7 +7,7 @@

## Project Snapshot

T3 Code is a minimal web GUI for using coding agents like Codex and Claude.
k3code is a minimal web GUI for using coding agents like Codex and Claude.

This repository is a VERY EARLY WIP. Proposing sweeping changes that improve long-term maintainability is encouraged.

Expand All@@ -32,7 +32,7 @@ Long term maintainability is a core priority. If you add new functionality, firs

## Codex App Server (Important)

T3 Code is currently Codex-first. The server starts `codex app-server` (JSON-RPC over stdio) per provider session, then streams structured events to the browser through WebSocket push messages.
k3code is currently Codex-first. The server starts `codex app-server` (JSON-RPC over stdio) per provider session, then streams structured events to the browser through WebSocket push messages.

How we use it in this codebase:

Expand Down
2 changes: 1 addition & 1 deletion KEYBINDINGS.md
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
# Keybindings

T3 Code reads keybindings from:
k3code reads keybindings from:

- `~/.t3/keybindings.json`

Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
# T3 Code
# k3code

T3 Code is a minimal web GUI for coding agents (currently Codex and Claude, more coming soon).
k3code is a minimal web GUI for coding agents (currently Codex and Claude, more coming soon).

## Installation

> [!WARNING]
> T3 Code currently supports Codex, Claude, and OpenCode.
> k3code currently supports Codex, Claude, and OpenCode.
> Install and authenticate at least one provider before use:
>
> - Codex: install [Codex CLI](https://developers.openai.com/codex/cli) and run `codex login`
Expand Down
2 changes: 1 addition & 1 deletion REMOTE.md
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
# Remote Access

Use this when you want to connect to a T3 Code server from another device such as a phone, tablet, or separate desktop app.
Use this when you want to connect to a k3code server from another device such as a phone, tablet, or separate desktop app.

## Recommended Setup

Expand Down
2 changes: 1 addition & 1 deletion apps/desktop/package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -28,5 +28,5 @@
"typescript": "catalog:",
"vitest": "catalog:"
},
"productName": "T3 Code (Alpha)"
"productName": "k3code (Alpha)"
}
4 changes: 2 additions & 2 deletions apps/desktop/scripts/electron-launcher.mjs
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
// This file mostly exists because we want dev mode to say "T3 Code (Dev)" instead of "electron"
// This file mostly exists because we want dev mode to say "k3code (Dev)" instead of "electron"

import { spawnSync } from "node:child_process";
import {
Expand All@@ -17,7 +17,7 @@ import { dirname, join, resolve } from "node:path";
import { fileURLToPath } from "node:url";

const isDevelopment = Boolean(process.env.VITE_DEV_SERVER_URL);
const APP_DISPLAY_NAME = isDevelopment ? "T3 Code (Dev)" : "T3 Code (Alpha)";
const APP_DISPLAY_NAME = isDevelopment ? "k3code (Dev)" : "k3code (Alpha)";
const APP_BUNDLE_ID = isDevelopment ? "com.t3tools.t3code.dev" : "com.t3tools.t3code";
const LAUNCHER_VERSION = 2;

Expand Down
4 changes: 2 additions & 2 deletions apps/desktop/src/appBranding.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -39,9 +39,9 @@ describe("resolveDesktopAppBranding", () => {
appVersion: "0.0.17-nightly.20260414.1",
}),
).toEqual({
baseName: "T3 Code",
baseName: "k3code",
stageLabel: "Nightly",
displayName: "T3 Code (Nightly)",
displayName: "k3code (Nightly)",
});
});
});
2 changes: 1 addition & 1 deletion apps/desktop/src/appBranding.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,7 +2,7 @@ import type { DesktopAppBranding, DesktopAppStageLabel } from "@t3tools/contract

import { isNightlyDesktopVersion } from "./updateChannels.ts";

const APP_BASE_NAME = "T3 Code";
const APP_BASE_NAME = "k3code";

export function resolveDesktopAppStageLabel(input: {
readonly isDevelopment: boolean;
Expand Down
1 change: 1 addition & 0 deletions apps/desktop/src/clientPersistence.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -53,6 +53,7 @@ const clientSettings: ClientSettings = {
confirmThreadArchive: true,
confirmThreadDelete: false,
diffWordWrap: true,
hideWindowControls: false,
favorites: [],
providerModelPreferences: {},
sidebarProjectGroupingMode: "repository_path",
Expand Down
19 changes: 13 additions & 6 deletions apps/desktop/src/main.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -31,6 +31,7 @@ import type {
DesktopUpdateCheckResult,
DesktopUpdateState,
} from "@t3tools/contracts";
import { DEFAULT_CLIENT_SETTINGS } from "@t3tools/contracts/settings";
import { autoUpdater } from "electron-updater";

import type { ContextMenuItem } from "@t3tools/contracts";
Expand DownExpand Up@@ -122,7 +123,7 @@ const APP_USER_MODEL_ID = isDevelopment ? "com.t3tools.t3code.dev" : "com.t3tool
const LINUX_DESKTOP_ENTRY_NAME = isDevelopment ? "t3code-dev.desktop" : "t3code.desktop";
const LINUX_WM_CLASS = isDevelopment ? "t3code-dev" : "t3code";
const USER_DATA_DIR_NAME = isDevelopment ? "t3code-dev" : "t3code";
const LEGACY_USER_DATA_DIR_NAME = isDevelopment ? "T3 Code (Dev)" : "T3 Code (Alpha)";
const LEGACY_USER_DATA_DIR_NAME = isDevelopment ? "k3code (Dev)" : "k3code (Alpha)";
const COMMIT_HASH_PATTERN = /^[0-9a-f]{7,40}$/i;
const COMMIT_HASH_DISPLAY_LENGTH = 12;
const LOG_DIR = Path.join(STATE_DIR, "logs");
Expand DownExpand Up@@ -228,6 +229,7 @@ let restoreStdIoCapture: (() => void) | null = null;
let backendObservabilitySettings = readPersistedBackendObservabilitySettings();
let desktopSettings = readDesktopSettings(DESKTOP_SETTINGS_PATH, app.getVersion());
let desktopServerExposureMode: DesktopServerExposureMode = desktopSettings.serverExposureMode;
let clientSettings = readClientSettings(CLIENT_SETTINGS_PATH) ?? DEFAULT_CLIENT_SETTINGS;

let destructiveMenuIconCache: Electron.NativeImage | null | undefined;
const expectedBackendExitChildren = new WeakSet<ChildProcess.ChildProcess>();
Expand DownExpand Up@@ -796,7 +798,7 @@ function handleFatalStartupError(stage: string, error: unknown): void {
console.error(`[desktop] fatal startup error (${stage})`, error);
if (!isQuitting) {
isQuitting = true;
dialog.showErrorBox("T3 Code failed to start", `Stage: ${stage}\n${message}${detail}`);
dialog.showErrorBox("k3code failed to start", `Stage: ${stage}\n${message}${detail}`);
}
stopBackend();
restoreStdIoCapture?.();
Expand DownExpand Up@@ -901,7 +903,7 @@ async function checkForUpdatesFromMenu(): Promise<void> {
void dialog.showMessageBox({
type: "info",
title: "You're up to date!",
message: `T3 Code ${updateState.currentVersion} is currently the newest version available.`,
message: `k3code ${updateState.currentVersion} is currently the newest version available.`,
buttons: ["OK"],
});
} else if (updateState.status === "error") {
Expand DownExpand Up@@ -1031,7 +1033,7 @@ function resolveIconPath(ext: "ico" | "icns" | "png"): string | null {
*
* Electron derives the default userData path from `productName` in
* package.json, which currently produces directories with spaces and
* parentheses (e.g. `~/.config/T3 Code (Alpha)` on Linux). This is
* parentheses (e.g. `~/.config/k3code (Alpha)` on Linux). This is
* unfriendly for shell usage and violates Linux naming conventions.
*
* We override it to a clean lowercase name (`t3code`). If the legacy
Expand DownExpand Up@@ -1580,15 +1582,17 @@ function registerIpcHandlers(): void {
});

ipcMain.removeHandler(GET_CLIENT_SETTINGS_CHANNEL);
ipcMain.handle(GET_CLIENT_SETTINGS_CHANNEL, async () => readClientSettings(CLIENT_SETTINGS_PATH));
ipcMain.handle(GET_CLIENT_SETTINGS_CHANNEL, async () => clientSettings);

ipcMain.removeHandler(SET_CLIENT_SETTINGS_CHANNEL);
ipcMain.handle(SET_CLIENT_SETTINGS_CHANNEL, async (_event, rawSettings: unknown) => {
if (typeof rawSettings !== "object" || rawSettings === null) {
throw new Error("Invalid client settings payload.");
}

writeClientSettings(CLIENT_SETTINGS_PATH, rawSettings as ClientSettings);
clientSettings = rawSettings as ClientSettings;
writeClientSettings(CLIENT_SETTINGS_PATH, clientSettings);
syncAllWindowAppearance();
});

ipcMain.removeHandler(GET_SAVED_ENVIRONMENT_REGISTRY_CHANNEL);
Expand DownExpand Up@@ -1923,6 +1927,9 @@ function syncWindowAppearance(window: BrowserWindow): void {
if (typeof titleBarOverlay === "object") {
window.setTitleBarOverlay(titleBarOverlay);
}
if (process.platform === "darwin") {
window.setWindowButtonVisibility(!clientSettings.hideWindowControls);
}
}

function syncAllWindowAppearance(): void {
Expand Down
4 changes: 2 additions & 2 deletions apps/marketing/src/layouts/Layout.astro
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,8 +5,8 @@ interface Props {
}

const {
title = "T3 Code",
description = "T3 Code — The best way to code with AI.",
title = "k3code",
description = "k3code — The best way to code with AI.",
} = Astro.props;
---

Expand Down
4 changes: 2 additions & 2 deletions apps/marketing/src/pages/download.astro
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,8 +3,8 @@ import Layout from "../layouts/Layout.astro";
import { RELEASES_URL } from "../lib/releases";
---

<Layout title="Download — T3 Code" description="Download T3 Code for macOS, Windows, or Linux.">
<h1 class="heading">Download T3 Code</h1>
<Layout title="Download — k3code" description="Download k3code for macOS, Windows, or Linux.">
<h1 class="heading">Download k3code</h1>
<p class="subheading">
<span id="version-label">Loading latest release&hellip;</span>
<a id="changelog-link" class="changelog-link" href="#" target="_blank" rel="noopener noreferrer" style="display:none">View changelog<span aria-hidden="true"> &#8599;</span></a>
Expand Down
4 changes: 2 additions & 2 deletions apps/marketing/src/pages/index.astro
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,7 +3,7 @@ import Layout from "../layouts/Layout.astro";
---

<Layout>
<h1 class="tagline">T3 Code is the best way to code with AI.</h1>
<h1 class="tagline">k3code is the best way to code with AI.</h1>

<a
id="download-btn"
Expand All@@ -19,7 +19,7 @@ import Layout from "../layouts/Layout.astro";
<a href="/download" class="other-platforms">Other platforms</a>

<div class="screenshot-wrap">
<img src="/screenshot.jpeg" alt="T3 Code" class="screenshot" />
<img src="/screenshot.jpeg" alt="k3code" class="screenshot" />
</div>
</Layout>

Expand Down
1 change: 1 addition & 0 deletions apps/server/package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -29,6 +29,7 @@
"@effect/platform-bun": "catalog:",
"@effect/platform-node": "catalog:",
"@effect/sql-sqlite-bun": "catalog:",
"@mariozechner/pi-coding-agent": "0.62.0",
"@opencode-ai/sdk": "^1.3.15",
"@pierre/diffs": "^1.1.0-beta.16",
"effect": "catalog:",
Expand Down
6 changes: 3 additions & 3 deletions apps/server/src/cli.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -1110,13 +1110,13 @@ const runServerCommand = (
});

const startCommand = Command.make("start", { ...sharedServerCommandFlags }).pipe(
Command.withDescription("Run the T3 Code server."),
Command.withDescription("Run the k3code server."),
Command.withHandler((flags) => runServerCommand(flags)),
);

const serveCommand = Command.make("serve", { ...sharedServerCommandFlags }).pipe(
Command.withDescription(
"Run the T3 Code server without opening a browser and print headless pairing details.",
"Run the k3code server without opening a browser and print headless pairing details.",
),
Command.withHandler((flags) =>
runServerCommand(flags, {
Expand All@@ -1127,7 +1127,7 @@ const serveCommand = Command.make("serve", { ...sharedServerCommandFlags }).pipe
);

export const cli = Command.make("t3", { ...sharedServerCommandFlags }).pipe(
Command.withDescription("Run the T3 Code server."),
Command.withDescription("Run the k3code server."),
Command.withHandler((flags) => runServerCommand(flags)),
Command.withSubcommands([startCommand, serveCommand, authCommand, projectCommand]),
);
2 changes: 1 addition & 1 deletion apps/server/src/git/Layers/OpenCodeTextGeneration.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -298,7 +298,7 @@ export const makeOpenCodeTextGeneration = Effect.fn("makeOpenCodeTextGeneration"
: {}),
});
const session = await client.session.create({
title: `T3 Code ${input.operation}`,
title: `k3code ${input.operation}`,
permission: [{ permission: "*", pattern: "*", action: "deny" }],
});
if (!session.data) {
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 AGENTS.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -7,7 +7,7 @@

## Project Snapshot

T3 Code is a minimal web GUI for using coding agents like Codex and Claude.
k3code is a minimal web GUI for using coding agents like Codex and Claude.

This repository is a VERY EARLY WIP. Proposing sweeping changes that improve long-term maintainability is encouraged.

Expand All@@ -32,7 +32,7 @@ Long term maintainability is a core priority. If you add new functionality, firs

## Codex App Server (Important)

T3 Code is currently Codex-first. The server starts `codex app-server` (JSON-RPC over stdio) per provider session, then streams structured events to the browser through WebSocket push messages.
k3code is currently Codex-first. The server starts `codex app-server` (JSON-RPC over stdio) per provider session, then streams structured events to the browser through WebSocket push messages.

How we use it in this codebase:

Expand Down
2 changes: 1 addition & 1 deletion KEYBINDINGS.md
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
# Keybindings

T3 Code reads keybindings from:
k3code reads keybindings from:

- `~/.t3/keybindings.json`

Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
# T3 Code
# k3code

T3 Code is a minimal web GUI for coding agents (currently Codex and Claude, more coming soon).
k3code is a minimal web GUI for coding agents (currently Codex and Claude, more coming soon).

## Installation

> [!WARNING]
> T3 Code currently supports Codex, Claude, and OpenCode.
> k3code currently supports Codex, Claude, and OpenCode.
> Install and authenticate at least one provider before use:
>
> - Codex: install [Codex CLI](https://developers.openai.com/codex/cli) and run `codex login`
Expand Down
2 changes: 1 addition & 1 deletion REMOTE.md
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
# Remote Access

Use this when you want to connect to a T3 Code server from another device such as a phone, tablet, or separate desktop app.
Use this when you want to connect to a k3code server from another device such as a phone, tablet, or separate desktop app.

## Recommended Setup

Expand Down
2 changes: 1 addition & 1 deletion apps/desktop/package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -28,5 +28,5 @@
"typescript": "catalog:",
"vitest": "catalog:"
},
"productName": "T3 Code (Alpha)"
"productName": "k3code (Alpha)"
}
4 changes: 2 additions & 2 deletions apps/desktop/scripts/electron-launcher.mjs
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
// This file mostly exists because we want dev mode to say "T3 Code (Dev)" instead of "electron"
// This file mostly exists because we want dev mode to say "k3code (Dev)" instead of "electron"

import { spawnSync } from "node:child_process";
import {
Expand All@@ -17,7 +17,7 @@ import { dirname, join, resolve } from "node:path";
import { fileURLToPath } from "node:url";

const isDevelopment = Boolean(process.env.VITE_DEV_SERVER_URL);
const APP_DISPLAY_NAME = isDevelopment ? "T3 Code (Dev)" : "T3 Code (Alpha)";
const APP_DISPLAY_NAME = isDevelopment ? "k3code (Dev)" : "k3code (Alpha)";
const APP_BUNDLE_ID = isDevelopment ? "com.t3tools.t3code.dev" : "com.t3tools.t3code";
const LAUNCHER_VERSION = 2;

Expand Down
4 changes: 2 additions & 2 deletions apps/desktop/src/appBranding.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -39,9 +39,9 @@ describe("resolveDesktopAppBranding", () => {
appVersion: "0.0.17-nightly.20260414.1",
}),
).toEqual({
baseName: "T3 Code",
baseName: "k3code",
stageLabel: "Nightly",
displayName: "T3 Code (Nightly)",
displayName: "k3code (Nightly)",
});
});
});
2 changes: 1 addition & 1 deletion apps/desktop/src/appBranding.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,7 +2,7 @@ import type { DesktopAppBranding, DesktopAppStageLabel } from "@t3tools/contract

import { isNightlyDesktopVersion } from "./updateChannels.ts";

const APP_BASE_NAME = "T3 Code";
const APP_BASE_NAME = "k3code";

export function resolveDesktopAppStageLabel(input: {
readonly isDevelopment: boolean;
Expand Down
1 change: 1 addition & 0 deletions apps/desktop/src/clientPersistence.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -53,6 +53,7 @@ const clientSettings: ClientSettings = {
confirmThreadArchive: true,
confirmThreadDelete: false,
diffWordWrap: true,
hideWindowControls: false,
favorites: [],
providerModelPreferences: {},
sidebarProjectGroupingMode: "repository_path",
Expand Down
19 changes: 13 additions & 6 deletions apps/desktop/src/main.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -31,6 +31,7 @@ import type {
DesktopUpdateCheckResult,
DesktopUpdateState,
} from "@t3tools/contracts";
import { DEFAULT_CLIENT_SETTINGS } from "@t3tools/contracts/settings";
import { autoUpdater } from "electron-updater";

import type { ContextMenuItem } from "@t3tools/contracts";
Expand DownExpand Up@@ -122,7 +123,7 @@ const APP_USER_MODEL_ID = isDevelopment ? "com.t3tools.t3code.dev" : "com.t3tool
const LINUX_DESKTOP_ENTRY_NAME = isDevelopment ? "t3code-dev.desktop" : "t3code.desktop";
const LINUX_WM_CLASS = isDevelopment ? "t3code-dev" : "t3code";
const USER_DATA_DIR_NAME = isDevelopment ? "t3code-dev" : "t3code";
const LEGACY_USER_DATA_DIR_NAME = isDevelopment ? "T3 Code (Dev)" : "T3 Code (Alpha)";
const LEGACY_USER_DATA_DIR_NAME = isDevelopment ? "k3code (Dev)" : "k3code (Alpha)";
const COMMIT_HASH_PATTERN = /^[0-9a-f]{7,40}$/i;
const COMMIT_HASH_DISPLAY_LENGTH = 12;
const LOG_DIR = Path.join(STATE_DIR, "logs");
Expand DownExpand Up@@ -228,6 +229,7 @@ let restoreStdIoCapture: (() => void) | null = null;
let backendObservabilitySettings = readPersistedBackendObservabilitySettings();
let desktopSettings = readDesktopSettings(DESKTOP_SETTINGS_PATH, app.getVersion());
let desktopServerExposureMode: DesktopServerExposureMode = desktopSettings.serverExposureMode;
let clientSettings = readClientSettings(CLIENT_SETTINGS_PATH) ?? DEFAULT_CLIENT_SETTINGS;

let destructiveMenuIconCache: Electron.NativeImage | null | undefined;
const expectedBackendExitChildren = new WeakSet<ChildProcess.ChildProcess>();
Expand DownExpand Up@@ -796,7 +798,7 @@ function handleFatalStartupError(stage: string, error: unknown): void {
console.error(`[desktop] fatal startup error (${stage})`, error);
if (!isQuitting) {
isQuitting = true;
dialog.showErrorBox("T3 Code failed to start", `Stage: ${stage}\n${message}${detail}`);
dialog.showErrorBox("k3code failed to start", `Stage: ${stage}\n${message}${detail}`);
}
stopBackend();
restoreStdIoCapture?.();
Expand DownExpand Up@@ -901,7 +903,7 @@ async function checkForUpdatesFromMenu(): Promise<void> {
void dialog.showMessageBox({
type: "info",
title: "You're up to date!",
message: `T3 Code ${updateState.currentVersion} is currently the newest version available.`,
message: `k3code ${updateState.currentVersion} is currently the newest version available.`,
buttons: ["OK"],
});
} else if (updateState.status === "error") {
Expand DownExpand Up@@ -1031,7 +1033,7 @@ function resolveIconPath(ext: "ico" | "icns" | "png"): string | null {
*
* Electron derives the default userData path from `productName` in
* package.json, which currently produces directories with spaces and
* parentheses (e.g. `~/.config/T3 Code (Alpha)` on Linux). This is
* parentheses (e.g. `~/.config/k3code (Alpha)` on Linux). This is
* unfriendly for shell usage and violates Linux naming conventions.
*
* We override it to a clean lowercase name (`t3code`). If the legacy
Expand DownExpand Up@@ -1580,15 +1582,17 @@ function registerIpcHandlers(): void {
});

ipcMain.removeHandler(GET_CLIENT_SETTINGS_CHANNEL);
ipcMain.handle(GET_CLIENT_SETTINGS_CHANNEL, async () => readClientSettings(CLIENT_SETTINGS_PATH));
ipcMain.handle(GET_CLIENT_SETTINGS_CHANNEL, async () => clientSettings);

ipcMain.removeHandler(SET_CLIENT_SETTINGS_CHANNEL);
ipcMain.handle(SET_CLIENT_SETTINGS_CHANNEL, async (_event, rawSettings: unknown) => {
if (typeof rawSettings !== "object" || rawSettings === null) {
throw new Error("Invalid client settings payload.");
}

writeClientSettings(CLIENT_SETTINGS_PATH, rawSettings as ClientSettings);
clientSettings = rawSettings as ClientSettings;
writeClientSettings(CLIENT_SETTINGS_PATH, clientSettings);
syncAllWindowAppearance();
});

ipcMain.removeHandler(GET_SAVED_ENVIRONMENT_REGISTRY_CHANNEL);
Expand DownExpand Up@@ -1923,6 +1927,9 @@ function syncWindowAppearance(window: BrowserWindow): void {
if (typeof titleBarOverlay === "object") {
window.setTitleBarOverlay(titleBarOverlay);
}
if (process.platform === "darwin") {
window.setWindowButtonVisibility(!clientSettings.hideWindowControls);
}
}

function syncAllWindowAppearance(): void {
Expand Down
4 changes: 2 additions & 2 deletions apps/marketing/src/layouts/Layout.astro
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,8 +5,8 @@ interface Props {
}

const {
title = "T3 Code",
description = "T3 Code — The best way to code with AI.",
title = "k3code",
description = "k3code — The best way to code with AI.",
} = Astro.props;
---

Expand Down
4 changes: 2 additions & 2 deletions apps/marketing/src/pages/download.astro
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,8 +3,8 @@ import Layout from "../layouts/Layout.astro";
import { RELEASES_URL } from "../lib/releases";
---

<Layout title="Download — T3 Code" description="Download T3 Code for macOS, Windows, or Linux.">
<h1 class="heading">Download T3 Code</h1>
<Layout title="Download — k3code" description="Download k3code for macOS, Windows, or Linux.">
<h1 class="heading">Download k3code</h1>
<p class="subheading">
<span id="version-label">Loading latest release&hellip;</span>
<a id="changelog-link" class="changelog-link" href="#" target="_blank" rel="noopener noreferrer" style="display:none">View changelog<span aria-hidden="true"> &#8599;</span></a>
Expand Down
4 changes: 2 additions & 2 deletions apps/marketing/src/pages/index.astro
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,7 +3,7 @@ import Layout from "../layouts/Layout.astro";
---

<Layout>
<h1 class="tagline">T3 Code is the best way to code with AI.</h1>
<h1 class="tagline">k3code is the best way to code with AI.</h1>

<a
id="download-btn"
Expand All@@ -19,7 +19,7 @@ import Layout from "../layouts/Layout.astro";
<a href="/download" class="other-platforms">Other platforms</a>

<div class="screenshot-wrap">
<img src="/screenshot.jpeg" alt="T3 Code" class="screenshot" />
<img src="/screenshot.jpeg" alt="k3code" class="screenshot" />
</div>
</Layout>

Expand Down
1 change: 1 addition & 0 deletions apps/server/package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -29,6 +29,7 @@
"@effect/platform-bun": "catalog:",
"@effect/platform-node": "catalog:",
"@effect/sql-sqlite-bun": "catalog:",
"@mariozechner/pi-coding-agent": "0.62.0",
"@opencode-ai/sdk": "^1.3.15",
"@pierre/diffs": "^1.1.0-beta.16",
"effect": "catalog:",
Expand Down
6 changes: 3 additions & 3 deletions apps/server/src/cli.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -1110,13 +1110,13 @@ const runServerCommand = (
});

const startCommand = Command.make("start", { ...sharedServerCommandFlags }).pipe(
Command.withDescription("Run the T3 Code server."),
Command.withDescription("Run the k3code server."),
Command.withHandler((flags) => runServerCommand(flags)),
);

const serveCommand = Command.make("serve", { ...sharedServerCommandFlags }).pipe(
Command.withDescription(
"Run the T3 Code server without opening a browser and print headless pairing details.",
"Run the k3code server without opening a browser and print headless pairing details.",
),
Command.withHandler((flags) =>
runServerCommand(flags, {
Expand All@@ -1127,7 +1127,7 @@ const serveCommand = Command.make("serve", { ...sharedServerCommandFlags }).pipe
);

export const cli = Command.make("t3", { ...sharedServerCommandFlags }).pipe(
Command.withDescription("Run the T3 Code server."),
Command.withDescription("Run the k3code server."),
Command.withHandler((flags) => runServerCommand(flags)),
Command.withSubcommands([startCommand, serveCommand, authCommand, projectCommand]),
);
2 changes: 1 addition & 1 deletion apps/server/src/git/Layers/OpenCodeTextGeneration.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -298,7 +298,7 @@ export const makeOpenCodeTextGeneration = Effect.fn("makeOpenCodeTextGeneration"
: {}),
});
const session = await client.session.create({
title: `T3 Code ${input.operation}`,
title: `k3code ${input.operation}`,
permission: [{ permission: "*", pattern: "*", action: "deny" }],
});
if (!session.data) {
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 AGENTS.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -7,7 +7,7 @@

## Project Snapshot

T3 Code is a minimal web GUI for using coding agents like Codex and Claude.
k3code is a minimal web GUI for using coding agents like Codex and Claude.

This repository is a VERY EARLY WIP. Proposing sweeping changes that improve long-term maintainability is encouraged.

Expand All@@ -32,7 +32,7 @@ Long term maintainability is a core priority. If you add new functionality, firs

## Codex App Server (Important)

T3 Code is currently Codex-first. The server starts `codex app-server` (JSON-RPC over stdio) per provider session, then streams structured events to the browser through WebSocket push messages.
k3code is currently Codex-first. The server starts `codex app-server` (JSON-RPC over stdio) per provider session, then streams structured events to the browser through WebSocket push messages.

How we use it in this codebase:

Expand Down
2 changes: 1 addition & 1 deletion KEYBINDINGS.md
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
# Keybindings

T3 Code reads keybindings from:
k3code reads keybindings from:

- `~/.t3/keybindings.json`

Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
# T3 Code
# k3code

T3 Code is a minimal web GUI for coding agents (currently Codex and Claude, more coming soon).
k3code is a minimal web GUI for coding agents (currently Codex and Claude, more coming soon).

## Installation

> [!WARNING]
> T3 Code currently supports Codex, Claude, and OpenCode.
> k3code currently supports Codex, Claude, and OpenCode.
> Install and authenticate at least one provider before use:
>
> - Codex: install [Codex CLI](https://developers.openai.com/codex/cli) and run `codex login`
Expand Down
2 changes: 1 addition & 1 deletion REMOTE.md
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
# Remote Access

Use this when you want to connect to a T3 Code server from another device such as a phone, tablet, or separate desktop app.
Use this when you want to connect to a k3code server from another device such as a phone, tablet, or separate desktop app.

## Recommended Setup

Expand Down
2 changes: 1 addition & 1 deletion apps/desktop/package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -28,5 +28,5 @@
"typescript": "catalog:",
"vitest": "catalog:"
},
"productName": "T3 Code (Alpha)"
"productName": "k3code (Alpha)"
}
4 changes: 2 additions & 2 deletions apps/desktop/scripts/electron-launcher.mjs
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
// This file mostly exists because we want dev mode to say "T3 Code (Dev)" instead of "electron"
// This file mostly exists because we want dev mode to say "k3code (Dev)" instead of "electron"

import { spawnSync } from "node:child_process";
import {
Expand All@@ -17,7 +17,7 @@ import { dirname, join, resolve } from "node:path";
import { fileURLToPath } from "node:url";

const isDevelopment = Boolean(process.env.VITE_DEV_SERVER_URL);
const APP_DISPLAY_NAME = isDevelopment ? "T3 Code (Dev)" : "T3 Code (Alpha)";
const APP_DISPLAY_NAME = isDevelopment ? "k3code (Dev)" : "k3code (Alpha)";
const APP_BUNDLE_ID = isDevelopment ? "com.t3tools.t3code.dev" : "com.t3tools.t3code";
const LAUNCHER_VERSION = 2;

Expand Down
4 changes: 2 additions & 2 deletions apps/desktop/src/appBranding.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -39,9 +39,9 @@ describe("resolveDesktopAppBranding", () => {
appVersion: "0.0.17-nightly.20260414.1",
}),
).toEqual({
baseName: "T3 Code",
baseName: "k3code",
stageLabel: "Nightly",
displayName: "T3 Code (Nightly)",
displayName: "k3code (Nightly)",
});
});
});
2 changes: 1 addition & 1 deletion apps/desktop/src/appBranding.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,7 +2,7 @@ import type { DesktopAppBranding, DesktopAppStageLabel } from "@t3tools/contract

import { isNightlyDesktopVersion } from "./updateChannels.ts";

const APP_BASE_NAME = "T3 Code";
const APP_BASE_NAME = "k3code";

export function resolveDesktopAppStageLabel(input: {
readonly isDevelopment: boolean;
Expand Down
1 change: 1 addition & 0 deletions apps/desktop/src/clientPersistence.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -53,6 +53,7 @@ const clientSettings: ClientSettings = {
confirmThreadArchive: true,
confirmThreadDelete: false,
diffWordWrap: true,
hideWindowControls: false,
favorites: [],
providerModelPreferences: {},
sidebarProjectGroupingMode: "repository_path",
Expand Down
19 changes: 13 additions & 6 deletions apps/desktop/src/main.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -31,6 +31,7 @@ import type {
DesktopUpdateCheckResult,
DesktopUpdateState,
} from "@t3tools/contracts";
import { DEFAULT_CLIENT_SETTINGS } from "@t3tools/contracts/settings";
import { autoUpdater } from "electron-updater";

import type { ContextMenuItem } from "@t3tools/contracts";
Expand DownExpand Up@@ -122,7 +123,7 @@ const APP_USER_MODEL_ID = isDevelopment ? "com.t3tools.t3code.dev" : "com.t3tool
const LINUX_DESKTOP_ENTRY_NAME = isDevelopment ? "t3code-dev.desktop" : "t3code.desktop";
const LINUX_WM_CLASS = isDevelopment ? "t3code-dev" : "t3code";
const USER_DATA_DIR_NAME = isDevelopment ? "t3code-dev" : "t3code";
const LEGACY_USER_DATA_DIR_NAME = isDevelopment ? "T3 Code (Dev)" : "T3 Code (Alpha)";
const LEGACY_USER_DATA_DIR_NAME = isDevelopment ? "k3code (Dev)" : "k3code (Alpha)";
const COMMIT_HASH_PATTERN = /^[0-9a-f]{7,40}$/i;
const COMMIT_HASH_DISPLAY_LENGTH = 12;
const LOG_DIR = Path.join(STATE_DIR, "logs");
Expand DownExpand Up@@ -228,6 +229,7 @@ let restoreStdIoCapture: (() => void) | null = null;
let backendObservabilitySettings = readPersistedBackendObservabilitySettings();
let desktopSettings = readDesktopSettings(DESKTOP_SETTINGS_PATH, app.getVersion());
let desktopServerExposureMode: DesktopServerExposureMode = desktopSettings.serverExposureMode;
let clientSettings = readClientSettings(CLIENT_SETTINGS_PATH) ?? DEFAULT_CLIENT_SETTINGS;

let destructiveMenuIconCache: Electron.NativeImage | null | undefined;
const expectedBackendExitChildren = new WeakSet<ChildProcess.ChildProcess>();
Expand DownExpand Up@@ -796,7 +798,7 @@ function handleFatalStartupError(stage: string, error: unknown): void {
console.error(`[desktop] fatal startup error (${stage})`, error);
if (!isQuitting) {
isQuitting = true;
dialog.showErrorBox("T3 Code failed to start", `Stage: ${stage}\n${message}${detail}`);
dialog.showErrorBox("k3code failed to start", `Stage: ${stage}\n${message}${detail}`);
}
stopBackend();
restoreStdIoCapture?.();
Expand DownExpand Up@@ -901,7 +903,7 @@ async function checkForUpdatesFromMenu(): Promise<void> {
void dialog.showMessageBox({
type: "info",
title: "You're up to date!",
message: `T3 Code ${updateState.currentVersion} is currently the newest version available.`,
message: `k3code ${updateState.currentVersion} is currently the newest version available.`,
buttons: ["OK"],
});
} else if (updateState.status === "error") {
Expand DownExpand Up@@ -1031,7 +1033,7 @@ function resolveIconPath(ext: "ico" | "icns" | "png"): string | null {
*
* Electron derives the default userData path from `productName` in
* package.json, which currently produces directories with spaces and
* parentheses (e.g. `~/.config/T3 Code (Alpha)` on Linux). This is
* parentheses (e.g. `~/.config/k3code (Alpha)` on Linux). This is
* unfriendly for shell usage and violates Linux naming conventions.
*
* We override it to a clean lowercase name (`t3code`). If the legacy
Expand DownExpand Up@@ -1580,15 +1582,17 @@ function registerIpcHandlers(): void {
});

ipcMain.removeHandler(GET_CLIENT_SETTINGS_CHANNEL);
ipcMain.handle(GET_CLIENT_SETTINGS_CHANNEL, async () => readClientSettings(CLIENT_SETTINGS_PATH));
ipcMain.handle(GET_CLIENT_SETTINGS_CHANNEL, async () => clientSettings);

ipcMain.removeHandler(SET_CLIENT_SETTINGS_CHANNEL);
ipcMain.handle(SET_CLIENT_SETTINGS_CHANNEL, async (_event, rawSettings: unknown) => {
if (typeof rawSettings !== "object" || rawSettings === null) {
throw new Error("Invalid client settings payload.");
}

writeClientSettings(CLIENT_SETTINGS_PATH, rawSettings as ClientSettings);
clientSettings = rawSettings as ClientSettings;
writeClientSettings(CLIENT_SETTINGS_PATH, clientSettings);
syncAllWindowAppearance();
});

ipcMain.removeHandler(GET_SAVED_ENVIRONMENT_REGISTRY_CHANNEL);
Expand DownExpand Up@@ -1923,6 +1927,9 @@ function syncWindowAppearance(window: BrowserWindow): void {
if (typeof titleBarOverlay === "object") {
window.setTitleBarOverlay(titleBarOverlay);
}
if (process.platform === "darwin") {
window.setWindowButtonVisibility(!clientSettings.hideWindowControls);
}
}

function syncAllWindowAppearance(): void {
Expand Down
4 changes: 2 additions & 2 deletions apps/marketing/src/layouts/Layout.astro
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,8 +5,8 @@ interface Props {
}

const {
title = "T3 Code",
description = "T3 Code — The best way to code with AI.",
title = "k3code",
description = "k3code — The best way to code with AI.",
} = Astro.props;
---

Expand Down
4 changes: 2 additions & 2 deletions apps/marketing/src/pages/download.astro
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,8 +3,8 @@ import Layout from "../layouts/Layout.astro";
import { RELEASES_URL } from "../lib/releases";
---

<Layout title="Download — T3 Code" description="Download T3 Code for macOS, Windows, or Linux.">
<h1 class="heading">Download T3 Code</h1>
<Layout title="Download — k3code" description="Download k3code for macOS, Windows, or Linux.">
<h1 class="heading">Download k3code</h1>
<p class="subheading">
<span id="version-label">Loading latest release&hellip;</span>
<a id="changelog-link" class="changelog-link" href="#" target="_blank" rel="noopener noreferrer" style="display:none">View changelog<span aria-hidden="true"> &#8599;</span></a>
Expand Down
4 changes: 2 additions & 2 deletions apps/marketing/src/pages/index.astro
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,7 +3,7 @@ import Layout from "../layouts/Layout.astro";
---

<Layout>
<h1 class="tagline">T3 Code is the best way to code with AI.</h1>
<h1 class="tagline">k3code is the best way to code with AI.</h1>

<a
id="download-btn"
Expand All@@ -19,7 +19,7 @@ import Layout from "../layouts/Layout.astro";
<a href="/download" class="other-platforms">Other platforms</a>

<div class="screenshot-wrap">
<img src="/screenshot.jpeg" alt="T3 Code" class="screenshot" />
<img src="/screenshot.jpeg" alt="k3code" class="screenshot" />
</div>
</Layout>

Expand Down
1 change: 1 addition & 0 deletions apps/server/package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -29,6 +29,7 @@
"@effect/platform-bun": "catalog:",
"@effect/platform-node": "catalog:",
"@effect/sql-sqlite-bun": "catalog:",
"@mariozechner/pi-coding-agent": "0.62.0",
"@opencode-ai/sdk": "^1.3.15",
"@pierre/diffs": "^1.1.0-beta.16",
"effect": "catalog:",
Expand Down
6 changes: 3 additions & 3 deletions apps/server/src/cli.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -1110,13 +1110,13 @@ const runServerCommand = (
});

const startCommand = Command.make("start", { ...sharedServerCommandFlags }).pipe(
Command.withDescription("Run the T3 Code server."),
Command.withDescription("Run the k3code server."),
Command.withHandler((flags) => runServerCommand(flags)),
);

const serveCommand = Command.make("serve", { ...sharedServerCommandFlags }).pipe(
Command.withDescription(
"Run the T3 Code server without opening a browser and print headless pairing details.",
"Run the k3code server without opening a browser and print headless pairing details.",
),
Command.withHandler((flags) =>
runServerCommand(flags, {
Expand All@@ -1127,7 +1127,7 @@ const serveCommand = Command.make("serve", { ...sharedServerCommandFlags }).pipe
);

export const cli = Command.make("t3", { ...sharedServerCommandFlags }).pipe(
Command.withDescription("Run the T3 Code server."),
Command.withDescription("Run the k3code server."),
Command.withHandler((flags) => runServerCommand(flags)),
Command.withSubcommands([startCommand, serveCommand, authCommand, projectCommand]),
);
2 changes: 1 addition & 1 deletion apps/server/src/git/Layers/OpenCodeTextGeneration.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -298,7 +298,7 @@ export const makeOpenCodeTextGeneration = Effect.fn("makeOpenCodeTextGeneration"
: {}),
});
const session = await client.session.create({
title: `T3 Code ${input.operation}`,
title: `k3code ${input.operation}`,
permission: [{ permission: "*", pattern: "*", action: "deny" }],
});
if (!session.data) {
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 AGENTS.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -7,7 +7,7 @@

## Project Snapshot

T3 Code is a minimal web GUI for using coding agents like Codex and Claude.
k3code is a minimal web GUI for using coding agents like Codex and Claude.

This repository is a VERY EARLY WIP. Proposing sweeping changes that improve long-term maintainability is encouraged.

Expand All@@ -32,7 +32,7 @@ Long term maintainability is a core priority. If you add new functionality, firs

## Codex App Server (Important)

T3 Code is currently Codex-first. The server starts `codex app-server` (JSON-RPC over stdio) per provider session, then streams structured events to the browser through WebSocket push messages.
k3code is currently Codex-first. The server starts `codex app-server` (JSON-RPC over stdio) per provider session, then streams structured events to the browser through WebSocket push messages.

How we use it in this codebase:

Expand Down
2 changes: 1 addition & 1 deletion KEYBINDINGS.md
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
# Keybindings

T3 Code reads keybindings from:
k3code reads keybindings from:

- `~/.t3/keybindings.json`

Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
# T3 Code
# k3code

T3 Code is a minimal web GUI for coding agents (currently Codex and Claude, more coming soon).
k3code is a minimal web GUI for coding agents (currently Codex and Claude, more coming soon).

## Installation

> [!WARNING]
> T3 Code currently supports Codex, Claude, and OpenCode.
> k3code currently supports Codex, Claude, and OpenCode.
> Install and authenticate at least one provider before use:
>
> - Codex: install [Codex CLI](https://developers.openai.com/codex/cli) and run `codex login`
Expand Down
2 changes: 1 addition & 1 deletion REMOTE.md
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
# Remote Access

Use this when you want to connect to a T3 Code server from another device such as a phone, tablet, or separate desktop app.
Use this when you want to connect to a k3code server from another device such as a phone, tablet, or separate desktop app.

## Recommended Setup

Expand Down
2 changes: 1 addition & 1 deletion apps/desktop/package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -28,5 +28,5 @@
"typescript": "catalog:",
"vitest": "catalog:"
},
"productName": "T3 Code (Alpha)"
"productName": "k3code (Alpha)"
}
4 changes: 2 additions & 2 deletions apps/desktop/scripts/electron-launcher.mjs
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
// This file mostly exists because we want dev mode to say "T3 Code (Dev)" instead of "electron"
// This file mostly exists because we want dev mode to say "k3code (Dev)" instead of "electron"

import { spawnSync } from "node:child_process";
import {
Expand All@@ -17,7 +17,7 @@ import { dirname, join, resolve } from "node:path";
import { fileURLToPath } from "node:url";

const isDevelopment = Boolean(process.env.VITE_DEV_SERVER_URL);
const APP_DISPLAY_NAME = isDevelopment ? "T3 Code (Dev)" : "T3 Code (Alpha)";
const APP_DISPLAY_NAME = isDevelopment ? "k3code (Dev)" : "k3code (Alpha)";
const APP_BUNDLE_ID = isDevelopment ? "com.t3tools.t3code.dev" : "com.t3tools.t3code";
const LAUNCHER_VERSION = 2;

Expand Down
4 changes: 2 additions & 2 deletions apps/desktop/src/appBranding.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -39,9 +39,9 @@ describe("resolveDesktopAppBranding", () => {
appVersion: "0.0.17-nightly.20260414.1",
}),
).toEqual({
baseName: "T3 Code",
baseName: "k3code",
stageLabel: "Nightly",
displayName: "T3 Code (Nightly)",
displayName: "k3code (Nightly)",
});
});
});
2 changes: 1 addition & 1 deletion apps/desktop/src/appBranding.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,7 +2,7 @@ import type { DesktopAppBranding, DesktopAppStageLabel } from "@t3tools/contract

import { isNightlyDesktopVersion } from "./updateChannels.ts";

const APP_BASE_NAME = "T3 Code";
const APP_BASE_NAME = "k3code";

export function resolveDesktopAppStageLabel(input: {
readonly isDevelopment: boolean;
Expand Down
1 change: 1 addition & 0 deletions apps/desktop/src/clientPersistence.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -53,6 +53,7 @@ const clientSettings: ClientSettings = {
confirmThreadArchive: true,
confirmThreadDelete: false,
diffWordWrap: true,
hideWindowControls: false,
favorites: [],
providerModelPreferences: {},
sidebarProjectGroupingMode: "repository_path",
Expand Down
19 changes: 13 additions & 6 deletions apps/desktop/src/main.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -31,6 +31,7 @@ import type {
DesktopUpdateCheckResult,
DesktopUpdateState,
} from "@t3tools/contracts";
import { DEFAULT_CLIENT_SETTINGS } from "@t3tools/contracts/settings";
import { autoUpdater } from "electron-updater";

import type { ContextMenuItem } from "@t3tools/contracts";
Expand DownExpand Up@@ -122,7 +123,7 @@ const APP_USER_MODEL_ID = isDevelopment ? "com.t3tools.t3code.dev" : "com.t3tool
const LINUX_DESKTOP_ENTRY_NAME = isDevelopment ? "t3code-dev.desktop" : "t3code.desktop";
const LINUX_WM_CLASS = isDevelopment ? "t3code-dev" : "t3code";
const USER_DATA_DIR_NAME = isDevelopment ? "t3code-dev" : "t3code";
const LEGACY_USER_DATA_DIR_NAME = isDevelopment ? "T3 Code (Dev)" : "T3 Code (Alpha)";
const LEGACY_USER_DATA_DIR_NAME = isDevelopment ? "k3code (Dev)" : "k3code (Alpha)";
const COMMIT_HASH_PATTERN = /^[0-9a-f]{7,40}$/i;
const COMMIT_HASH_DISPLAY_LENGTH = 12;
const LOG_DIR = Path.join(STATE_DIR, "logs");
Expand DownExpand Up@@ -228,6 +229,7 @@ let restoreStdIoCapture: (() => void) | null = null;
let backendObservabilitySettings = readPersistedBackendObservabilitySettings();
let desktopSettings = readDesktopSettings(DESKTOP_SETTINGS_PATH, app.getVersion());
let desktopServerExposureMode: DesktopServerExposureMode = desktopSettings.serverExposureMode;
let clientSettings = readClientSettings(CLIENT_SETTINGS_PATH) ?? DEFAULT_CLIENT_SETTINGS;

let destructiveMenuIconCache: Electron.NativeImage | null | undefined;
const expectedBackendExitChildren = new WeakSet<ChildProcess.ChildProcess>();
Expand DownExpand Up@@ -796,7 +798,7 @@ function handleFatalStartupError(stage: string, error: unknown): void {
console.error(`[desktop] fatal startup error (${stage})`, error);
if (!isQuitting) {
isQuitting = true;
dialog.showErrorBox("T3 Code failed to start", `Stage: ${stage}\n${message}${detail}`);
dialog.showErrorBox("k3code failed to start", `Stage: ${stage}\n${message}${detail}`);
}
stopBackend();
restoreStdIoCapture?.();
Expand DownExpand Up@@ -901,7 +903,7 @@ async function checkForUpdatesFromMenu(): Promise<void> {
void dialog.showMessageBox({
type: "info",
title: "You're up to date!",
message: `T3 Code ${updateState.currentVersion} is currently the newest version available.`,
message: `k3code ${updateState.currentVersion} is currently the newest version available.`,
buttons: ["OK"],
});
} else if (updateState.status === "error") {
Expand DownExpand Up@@ -1031,7 +1033,7 @@ function resolveIconPath(ext: "ico" | "icns" | "png"): string | null {
*
* Electron derives the default userData path from `productName` in
* package.json, which currently produces directories with spaces and
* parentheses (e.g. `~/.config/T3 Code (Alpha)` on Linux). This is
* parentheses (e.g. `~/.config/k3code (Alpha)` on Linux). This is
* unfriendly for shell usage and violates Linux naming conventions.
*
* We override it to a clean lowercase name (`t3code`). If the legacy
Expand DownExpand Up@@ -1580,15 +1582,17 @@ function registerIpcHandlers(): void {
});

ipcMain.removeHandler(GET_CLIENT_SETTINGS_CHANNEL);
ipcMain.handle(GET_CLIENT_SETTINGS_CHANNEL, async () => readClientSettings(CLIENT_SETTINGS_PATH));
ipcMain.handle(GET_CLIENT_SETTINGS_CHANNEL, async () => clientSettings);

ipcMain.removeHandler(SET_CLIENT_SETTINGS_CHANNEL);
ipcMain.handle(SET_CLIENT_SETTINGS_CHANNEL, async (_event, rawSettings: unknown) => {
if (typeof rawSettings !== "object" || rawSettings === null) {
throw new Error("Invalid client settings payload.");
}

writeClientSettings(CLIENT_SETTINGS_PATH, rawSettings as ClientSettings);
clientSettings = rawSettings as ClientSettings;
writeClientSettings(CLIENT_SETTINGS_PATH, clientSettings);
syncAllWindowAppearance();
});

ipcMain.removeHandler(GET_SAVED_ENVIRONMENT_REGISTRY_CHANNEL);
Expand DownExpand Up@@ -1923,6 +1927,9 @@ function syncWindowAppearance(window: BrowserWindow): void {
if (typeof titleBarOverlay === "object") {
window.setTitleBarOverlay(titleBarOverlay);
}
if (process.platform === "darwin") {
window.setWindowButtonVisibility(!clientSettings.hideWindowControls);
}
}

function syncAllWindowAppearance(): void {
Expand Down
4 changes: 2 additions & 2 deletions apps/marketing/src/layouts/Layout.astro
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,8 +5,8 @@ interface Props {
}

const {
title = "T3 Code",
description = "T3 Code — The best way to code with AI.",
title = "k3code",
description = "k3code — The best way to code with AI.",
} = Astro.props;
---

Expand Down
4 changes: 2 additions & 2 deletions apps/marketing/src/pages/download.astro
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,8 +3,8 @@ import Layout from "../layouts/Layout.astro";
import { RELEASES_URL } from "../lib/releases";
---

<Layout title="Download — T3 Code" description="Download T3 Code for macOS, Windows, or Linux.">
<h1 class="heading">Download T3 Code</h1>
<Layout title="Download — k3code" description="Download k3code for macOS, Windows, or Linux.">
<h1 class="heading">Download k3code</h1>
<p class="subheading">
<span id="version-label">Loading latest release&hellip;</span>
<a id="changelog-link" class="changelog-link" href="#" target="_blank" rel="noopener noreferrer" style="display:none">View changelog<span aria-hidden="true"> &#8599;</span></a>
Expand Down
4 changes: 2 additions & 2 deletions apps/marketing/src/pages/index.astro
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,7 +3,7 @@ import Layout from "../layouts/Layout.astro";
---

<Layout>
<h1 class="tagline">T3 Code is the best way to code with AI.</h1>
<h1 class="tagline">k3code is the best way to code with AI.</h1>

<a
id="download-btn"
Expand All@@ -19,7 +19,7 @@ import Layout from "../layouts/Layout.astro";
<a href="/download" class="other-platforms">Other platforms</a>

<div class="screenshot-wrap">
<img src="/screenshot.jpeg" alt="T3 Code" class="screenshot" />
<img src="/screenshot.jpeg" alt="k3code" class="screenshot" />
</div>
</Layout>

Expand Down
1 change: 1 addition & 0 deletions apps/server/package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -29,6 +29,7 @@
"@effect/platform-bun": "catalog:",
"@effect/platform-node": "catalog:",
"@effect/sql-sqlite-bun": "catalog:",
"@mariozechner/pi-coding-agent": "0.62.0",
"@opencode-ai/sdk": "^1.3.15",
"@pierre/diffs": "^1.1.0-beta.16",
"effect": "catalog:",
Expand Down
6 changes: 3 additions & 3 deletions apps/server/src/cli.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -1110,13 +1110,13 @@ const runServerCommand = (
});

const startCommand = Command.make("start", { ...sharedServerCommandFlags }).pipe(
Command.withDescription("Run the T3 Code server."),
Command.withDescription("Run the k3code server."),
Command.withHandler((flags) => runServerCommand(flags)),
);

const serveCommand = Command.make("serve", { ...sharedServerCommandFlags }).pipe(
Command.withDescription(
"Run the T3 Code server without opening a browser and print headless pairing details.",
"Run the k3code server without opening a browser and print headless pairing details.",
),
Command.withHandler((flags) =>
runServerCommand(flags, {
Expand All@@ -1127,7 +1127,7 @@ const serveCommand = Command.make("serve", { ...sharedServerCommandFlags }).pipe
);

export const cli = Command.make("t3", { ...sharedServerCommandFlags }).pipe(
Command.withDescription("Run the T3 Code server."),
Command.withDescription("Run the k3code server."),
Command.withHandler((flags) => runServerCommand(flags)),
Command.withSubcommands([startCommand, serveCommand, authCommand, projectCommand]),
);
2 changes: 1 addition & 1 deletion apps/server/src/git/Layers/OpenCodeTextGeneration.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -298,7 +298,7 @@ export const makeOpenCodeTextGeneration = Effect.fn("makeOpenCodeTextGeneration"
: {}),
});
const session = await client.session.create({
title: `T3 Code ${input.operation}`,
title: `k3code ${input.operation}`,
permission: [{ permission: "*", pattern: "*", action: "deny" }],
});
if (!session.data) {
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 AGENTS.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -7,7 +7,7 @@

## Project Snapshot

T3 Code is a minimal web GUI for using coding agents like Codex and Claude.
k3code is a minimal web GUI for using coding agents like Codex and Claude.

This repository is a VERY EARLY WIP. Proposing sweeping changes that improve long-term maintainability is encouraged.

Expand All@@ -32,7 +32,7 @@ Long term maintainability is a core priority. If you add new functionality, firs

## Codex App Server (Important)

T3 Code is currently Codex-first. The server starts `codex app-server` (JSON-RPC over stdio) per provider session, then streams structured events to the browser through WebSocket push messages.
k3code is currently Codex-first. The server starts `codex app-server` (JSON-RPC over stdio) per provider session, then streams structured events to the browser through WebSocket push messages.

How we use it in this codebase:

Expand Down
2 changes: 1 addition & 1 deletion KEYBINDINGS.md
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
# Keybindings

T3 Code reads keybindings from:
k3code reads keybindings from:

- `~/.t3/keybindings.json`

Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
# T3 Code
# k3code

T3 Code is a minimal web GUI for coding agents (currently Codex and Claude, more coming soon).
k3code is a minimal web GUI for coding agents (currently Codex and Claude, more coming soon).

## Installation

> [!WARNING]
> T3 Code currently supports Codex, Claude, and OpenCode.
> k3code currently supports Codex, Claude, and OpenCode.
> Install and authenticate at least one provider before use:
>
> - Codex: install [Codex CLI](https://developers.openai.com/codex/cli) and run `codex login`
Expand Down
2 changes: 1 addition & 1 deletion REMOTE.md
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
# Remote Access

Use this when you want to connect to a T3 Code server from another device such as a phone, tablet, or separate desktop app.
Use this when you want to connect to a k3code server from another device such as a phone, tablet, or separate desktop app.

## Recommended Setup

Expand Down
2 changes: 1 addition & 1 deletion apps/desktop/package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -28,5 +28,5 @@
"typescript": "catalog:",
"vitest": "catalog:"
},
"productName": "T3 Code (Alpha)"
"productName": "k3code (Alpha)"
}
4 changes: 2 additions & 2 deletions apps/desktop/scripts/electron-launcher.mjs
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
// This file mostly exists because we want dev mode to say "T3 Code (Dev)" instead of "electron"
// This file mostly exists because we want dev mode to say "k3code (Dev)" instead of "electron"

import { spawnSync } from "node:child_process";
import {
Expand All@@ -17,7 +17,7 @@ import { dirname, join, resolve } from "node:path";
import { fileURLToPath } from "node:url";

const isDevelopment = Boolean(process.env.VITE_DEV_SERVER_URL);
const APP_DISPLAY_NAME = isDevelopment ? "T3 Code (Dev)" : "T3 Code (Alpha)";
const APP_DISPLAY_NAME = isDevelopment ? "k3code (Dev)" : "k3code (Alpha)";
const APP_BUNDLE_ID = isDevelopment ? "com.t3tools.t3code.dev" : "com.t3tools.t3code";
const LAUNCHER_VERSION = 2;

Expand Down
4 changes: 2 additions & 2 deletions apps/desktop/src/appBranding.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -39,9 +39,9 @@ describe("resolveDesktopAppBranding", () => {
appVersion: "0.0.17-nightly.20260414.1",
}),
).toEqual({
baseName: "T3 Code",
baseName: "k3code",
stageLabel: "Nightly",
displayName: "T3 Code (Nightly)",
displayName: "k3code (Nightly)",
});
});
});
2 changes: 1 addition & 1 deletion apps/desktop/src/appBranding.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,7 +2,7 @@ import type { DesktopAppBranding, DesktopAppStageLabel } from "@t3tools/contract

import { isNightlyDesktopVersion } from "./updateChannels.ts";

const APP_BASE_NAME = "T3 Code";
const APP_BASE_NAME = "k3code";

export function resolveDesktopAppStageLabel(input: {
readonly isDevelopment: boolean;
Expand Down
1 change: 1 addition & 0 deletions apps/desktop/src/clientPersistence.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -53,6 +53,7 @@ const clientSettings: ClientSettings = {
confirmThreadArchive: true,
confirmThreadDelete: false,
diffWordWrap: true,
hideWindowControls: false,
favorites: [],
providerModelPreferences: {},
sidebarProjectGroupingMode: "repository_path",
Expand Down
19 changes: 13 additions & 6 deletions apps/desktop/src/main.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -31,6 +31,7 @@ import type {
DesktopUpdateCheckResult,
DesktopUpdateState,
} from "@t3tools/contracts";
import { DEFAULT_CLIENT_SETTINGS } from "@t3tools/contracts/settings";
import { autoUpdater } from "electron-updater";

import type { ContextMenuItem } from "@t3tools/contracts";
Expand DownExpand Up@@ -122,7 +123,7 @@ const APP_USER_MODEL_ID = isDevelopment ? "com.t3tools.t3code.dev" : "com.t3tool
const LINUX_DESKTOP_ENTRY_NAME = isDevelopment ? "t3code-dev.desktop" : "t3code.desktop";
const LINUX_WM_CLASS = isDevelopment ? "t3code-dev" : "t3code";
const USER_DATA_DIR_NAME = isDevelopment ? "t3code-dev" : "t3code";
const LEGACY_USER_DATA_DIR_NAME = isDevelopment ? "T3 Code (Dev)" : "T3 Code (Alpha)";
const LEGACY_USER_DATA_DIR_NAME = isDevelopment ? "k3code (Dev)" : "k3code (Alpha)";
const COMMIT_HASH_PATTERN = /^[0-9a-f]{7,40}$/i;
const COMMIT_HASH_DISPLAY_LENGTH = 12;
const LOG_DIR = Path.join(STATE_DIR, "logs");
Expand DownExpand Up@@ -228,6 +229,7 @@ let restoreStdIoCapture: (() => void) | null = null;
let backendObservabilitySettings = readPersistedBackendObservabilitySettings();
let desktopSettings = readDesktopSettings(DESKTOP_SETTINGS_PATH, app.getVersion());
let desktopServerExposureMode: DesktopServerExposureMode = desktopSettings.serverExposureMode;
let clientSettings = readClientSettings(CLIENT_SETTINGS_PATH) ?? DEFAULT_CLIENT_SETTINGS;

let destructiveMenuIconCache: Electron.NativeImage | null | undefined;
const expectedBackendExitChildren = new WeakSet<ChildProcess.ChildProcess>();
Expand DownExpand Up@@ -796,7 +798,7 @@ function handleFatalStartupError(stage: string, error: unknown): void {
console.error(`[desktop] fatal startup error (${stage})`, error);
if (!isQuitting) {
isQuitting = true;
dialog.showErrorBox("T3 Code failed to start", `Stage: ${stage}\n${message}${detail}`);
dialog.showErrorBox("k3code failed to start", `Stage: ${stage}\n${message}${detail}`);
}
stopBackend();
restoreStdIoCapture?.();
Expand DownExpand Up@@ -901,7 +903,7 @@ async function checkForUpdatesFromMenu(): Promise<void> {
void dialog.showMessageBox({
type: "info",
title: "You're up to date!",
message: `T3 Code ${updateState.currentVersion} is currently the newest version available.`,
message: `k3code ${updateState.currentVersion} is currently the newest version available.`,
buttons: ["OK"],
});
} else if (updateState.status === "error") {
Expand DownExpand Up@@ -1031,7 +1033,7 @@ function resolveIconPath(ext: "ico" | "icns" | "png"): string | null {
*
* Electron derives the default userData path from `productName` in
* package.json, which currently produces directories with spaces and
* parentheses (e.g. `~/.config/T3 Code (Alpha)` on Linux). This is
* parentheses (e.g. `~/.config/k3code (Alpha)` on Linux). This is
* unfriendly for shell usage and violates Linux naming conventions.
*
* We override it to a clean lowercase name (`t3code`). If the legacy
Expand DownExpand Up@@ -1580,15 +1582,17 @@ function registerIpcHandlers(): void {
});

ipcMain.removeHandler(GET_CLIENT_SETTINGS_CHANNEL);
ipcMain.handle(GET_CLIENT_SETTINGS_CHANNEL, async () => readClientSettings(CLIENT_SETTINGS_PATH));
ipcMain.handle(GET_CLIENT_SETTINGS_CHANNEL, async () => clientSettings);

ipcMain.removeHandler(SET_CLIENT_SETTINGS_CHANNEL);
ipcMain.handle(SET_CLIENT_SETTINGS_CHANNEL, async (_event, rawSettings: unknown) => {
if (typeof rawSettings !== "object" || rawSettings === null) {
throw new Error("Invalid client settings payload.");
}

writeClientSettings(CLIENT_SETTINGS_PATH, rawSettings as ClientSettings);
clientSettings = rawSettings as ClientSettings;
writeClientSettings(CLIENT_SETTINGS_PATH, clientSettings);
syncAllWindowAppearance();
});

ipcMain.removeHandler(GET_SAVED_ENVIRONMENT_REGISTRY_CHANNEL);
Expand DownExpand Up@@ -1923,6 +1927,9 @@ function syncWindowAppearance(window: BrowserWindow): void {
if (typeof titleBarOverlay === "object") {
window.setTitleBarOverlay(titleBarOverlay);
}
if (process.platform === "darwin") {
window.setWindowButtonVisibility(!clientSettings.hideWindowControls);
}
}

function syncAllWindowAppearance(): void {
Expand Down
4 changes: 2 additions & 2 deletions apps/marketing/src/layouts/Layout.astro
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,8 +5,8 @@ interface Props {
}

const {
title = "T3 Code",
description = "T3 Code — The best way to code with AI.",
title = "k3code",
description = "k3code — The best way to code with AI.",
} = Astro.props;
---

Expand Down
4 changes: 2 additions & 2 deletions apps/marketing/src/pages/download.astro
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,8 +3,8 @@ import Layout from "../layouts/Layout.astro";
import { RELEASES_URL } from "../lib/releases";
---

<Layout title="Download — T3 Code" description="Download T3 Code for macOS, Windows, or Linux.">
<h1 class="heading">Download T3 Code</h1>
<Layout title="Download — k3code" description="Download k3code for macOS, Windows, or Linux.">
<h1 class="heading">Download k3code</h1>
<p class="subheading">
<span id="version-label">Loading latest release&hellip;</span>
<a id="changelog-link" class="changelog-link" href="#" target="_blank" rel="noopener noreferrer" style="display:none">View changelog<span aria-hidden="true"> &#8599;</span></a>
Expand Down
4 changes: 2 additions & 2 deletions apps/marketing/src/pages/index.astro
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,7 +3,7 @@ import Layout from "../layouts/Layout.astro";
---

<Layout>
<h1 class="tagline">T3 Code is the best way to code with AI.</h1>
<h1 class="tagline">k3code is the best way to code with AI.</h1>

<a
id="download-btn"
Expand All@@ -19,7 +19,7 @@ import Layout from "../layouts/Layout.astro";
<a href="/download" class="other-platforms">Other platforms</a>

<div class="screenshot-wrap">
<img src="/screenshot.jpeg" alt="T3 Code" class="screenshot" />
<img src="/screenshot.jpeg" alt="k3code" class="screenshot" />
</div>
</Layout>

Expand Down
1 change: 1 addition & 0 deletions apps/server/package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -29,6 +29,7 @@
"@effect/platform-bun": "catalog:",
"@effect/platform-node": "catalog:",
"@effect/sql-sqlite-bun": "catalog:",
"@mariozechner/pi-coding-agent": "0.62.0",
"@opencode-ai/sdk": "^1.3.15",
"@pierre/diffs": "^1.1.0-beta.16",
"effect": "catalog:",
Expand Down
6 changes: 3 additions & 3 deletions apps/server/src/cli.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -1110,13 +1110,13 @@ const runServerCommand = (
});

const startCommand = Command.make("start", { ...sharedServerCommandFlags }).pipe(
Command.withDescription("Run the T3 Code server."),
Command.withDescription("Run the k3code server."),
Command.withHandler((flags) => runServerCommand(flags)),
);

const serveCommand = Command.make("serve", { ...sharedServerCommandFlags }).pipe(
Command.withDescription(
"Run the T3 Code server without opening a browser and print headless pairing details.",
"Run the k3code server without opening a browser and print headless pairing details.",
),
Command.withHandler((flags) =>
runServerCommand(flags, {
Expand All@@ -1127,7 +1127,7 @@ const serveCommand = Command.make("serve", { ...sharedServerCommandFlags }).pipe
);

export const cli = Command.make("t3", { ...sharedServerCommandFlags }).pipe(
Command.withDescription("Run the T3 Code server."),
Command.withDescription("Run the k3code server."),
Command.withHandler((flags) => runServerCommand(flags)),
Command.withSubcommands([startCommand, serveCommand, authCommand, projectCommand]),
);
2 changes: 1 addition & 1 deletion apps/server/src/git/Layers/OpenCodeTextGeneration.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -298,7 +298,7 @@ export const makeOpenCodeTextGeneration = Effect.fn("makeOpenCodeTextGeneration"
: {}),
});
const session = await client.session.create({
title: `T3 Code ${input.operation}`,
title: `k3code ${input.operation}`,
permission: [{ permission: "*", pattern: "*", action: "deny" }],
});
if (!session.data) {
Expand Down
Loading