aicodeman 1.16.3 → 1.16.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. package/README.md +9 -9
  2. package/dist/claude-credentials.d.ts +50 -0
  3. package/dist/claude-credentials.d.ts.map +1 -0
  4. package/dist/claude-credentials.js +102 -0
  5. package/dist/claude-credentials.js.map +1 -0
  6. package/dist/config/voice.d.ts +43 -0
  7. package/dist/config/voice.d.ts.map +1 -0
  8. package/dist/config/voice.js +48 -0
  9. package/dist/config/voice.js.map +1 -0
  10. package/dist/web/ports/config-port.d.ts +2 -0
  11. package/dist/web/ports/config-port.d.ts.map +1 -1
  12. package/dist/web/public/admin-ui.js.gz +0 -0
  13. package/dist/web/public/api-client.c9b1cddc.js.gz +0 -0
  14. package/dist/web/public/app.f9c6aadd.js.gz +0 -0
  15. package/dist/web/public/approvals-ui.js.gz +0 -0
  16. package/dist/web/public/constants.53dc0fa1.js.gz +0 -0
  17. package/dist/web/public/cron-ui.js.gz +0 -0
  18. package/dist/web/public/entrance-animations.js.gz +0 -0
  19. package/dist/web/public/home-sessions.js +15 -4
  20. package/dist/web/public/home-sessions.js.br +0 -0
  21. package/dist/web/public/home-sessions.js.gz +0 -0
  22. package/dist/web/public/i18n.89097ff5.js +1 -0
  23. package/dist/web/public/i18n.89097ff5.js.br +0 -0
  24. package/dist/web/public/i18n.89097ff5.js.gz +0 -0
  25. package/dist/web/public/image-input.ee16ad88.js.gz +0 -0
  26. package/dist/web/public/index.html +657 -402
  27. package/dist/web/public/index.html.br +0 -0
  28. package/dist/web/public/index.html.gz +0 -0
  29. package/dist/web/public/input-cjk.63794d0b.js.gz +0 -0
  30. package/dist/web/public/keyboard-accessory.0f524637.js.gz +0 -0
  31. package/dist/web/public/mobile-handlers.32fdd57f.js.gz +0 -0
  32. package/dist/web/public/mobile-overview.js.gz +0 -0
  33. package/dist/web/public/mobile.85bab868.css +1 -0
  34. package/dist/web/public/mobile.85bab868.css.br +0 -0
  35. package/dist/web/public/mobile.85bab868.css.gz +0 -0
  36. package/dist/web/public/notification-manager.5d229063.js.gz +0 -0
  37. package/dist/web/public/orchestrator-panel.js.gz +0 -0
  38. package/dist/web/public/panels-ui.54b0d004.js.gz +0 -0
  39. package/dist/web/public/ralph-panel.6de2d0f8.js.gz +0 -0
  40. package/dist/web/public/ralph-wizard.13a1831e.js.gz +0 -0
  41. package/dist/web/public/readmymind-ui.js +20 -4
  42. package/dist/web/public/readmymind-ui.js.br +0 -0
  43. package/dist/web/public/readmymind-ui.js.gz +0 -0
  44. package/dist/web/public/respawn-ui.ff0dae4c.js.gz +0 -0
  45. package/dist/web/public/sanitize-html.bc7078d6.js.gz +0 -0
  46. package/dist/web/public/{session-ui.f4fed187.js → session-ui.46a0993c.js} +5 -5
  47. package/dist/web/public/session-ui.46a0993c.js.br +0 -0
  48. package/dist/web/public/session-ui.46a0993c.js.gz +0 -0
  49. package/dist/web/public/settings-ui.63be4178.js +67 -0
  50. package/dist/web/public/settings-ui.63be4178.js.br +0 -0
  51. package/dist/web/public/settings-ui.63be4178.js.gz +0 -0
  52. package/dist/web/public/styles.2759a2fd.css +1 -0
  53. package/dist/web/public/styles.2759a2fd.css.br +0 -0
  54. package/dist/web/public/styles.2759a2fd.css.gz +0 -0
  55. package/dist/web/public/subagent-windows.4cc8b005.js.gz +0 -0
  56. package/dist/web/public/sw.js.gz +0 -0
  57. package/dist/web/public/terminal-ui.a910e1ab.js +4 -0
  58. package/dist/web/public/terminal-ui.a910e1ab.js.br +0 -0
  59. package/dist/web/public/terminal-ui.a910e1ab.js.gz +0 -0
  60. package/dist/web/public/ultracode-panel.js.gz +0 -0
  61. package/dist/web/public/ultracode-windows.js.gz +0 -0
  62. package/dist/web/public/upload.html.gz +0 -0
  63. package/dist/web/public/vendor/dompurify.min.js.gz +0 -0
  64. package/dist/web/public/vendor/marked.min.js.gz +0 -0
  65. package/dist/web/public/vendor/xterm-addon-fit.min.js.gz +0 -0
  66. package/dist/web/public/vendor/xterm-addon-serialize.min.js.gz +0 -0
  67. package/dist/web/public/vendor/xterm-addon-unicode11.min.js.gz +0 -0
  68. package/dist/web/public/vendor/xterm-addon-webgl.min.js.gz +0 -0
  69. package/dist/web/public/vendor/xterm-predictive-echo.6cec0fba.js.gz +0 -0
  70. package/dist/web/public/vendor/xterm-zerolag-input.137ad9f0.js.gz +0 -0
  71. package/dist/web/public/vendor/xterm.css.gz +0 -0
  72. package/dist/web/public/vendor/xterm.min.js.gz +0 -0
  73. package/dist/web/public/{voice-input.e5461859.js → voice-input.4ec670b0.js} +421 -13
  74. package/dist/web/public/voice-input.4ec670b0.js.br +0 -0
  75. package/dist/web/public/voice-input.4ec670b0.js.gz +0 -0
  76. package/dist/web/public/voice-pcm-worklet.js +57 -0
  77. package/dist/web/public/voice-pcm-worklet.js.br +0 -0
  78. package/dist/web/public/voice-pcm-worklet.js.gz +0 -0
  79. package/dist/web/public/webview-tabs.js.gz +0 -0
  80. package/dist/web/routes/index.d.ts +1 -0
  81. package/dist/web/routes/index.d.ts.map +1 -1
  82. package/dist/web/routes/index.js +1 -0
  83. package/dist/web/routes/index.js.map +1 -1
  84. package/dist/web/routes/voice-routes.d.ts +45 -0
  85. package/dist/web/routes/voice-routes.d.ts.map +1 -0
  86. package/dist/web/routes/voice-routes.js +172 -0
  87. package/dist/web/routes/voice-routes.js.map +1 -0
  88. package/dist/web/schemas.d.ts +2 -0
  89. package/dist/web/schemas.d.ts.map +1 -1
  90. package/dist/web/schemas.js +12 -0
  91. package/dist/web/schemas.js.map +1 -1
  92. package/dist/web/server.d.ts +1 -0
  93. package/dist/web/server.d.ts.map +1 -1
  94. package/dist/web/server.js +11 -1
  95. package/dist/web/server.js.map +1 -1
  96. package/dist/web/voice-stream.d.ts +96 -0
  97. package/dist/web/voice-stream.d.ts.map +1 -0
  98. package/dist/web/voice-stream.js +268 -0
  99. package/dist/web/voice-stream.js.map +1 -0
  100. package/package.json +1 -1
  101. package/dist/web/public/i18n.1a8b3412.js +0 -1
  102. package/dist/web/public/i18n.1a8b3412.js.br +0 -0
  103. package/dist/web/public/i18n.1a8b3412.js.gz +0 -0
  104. package/dist/web/public/mobile.52b30b35.css +0 -1
  105. package/dist/web/public/mobile.52b30b35.css.br +0 -0
  106. package/dist/web/public/mobile.52b30b35.css.gz +0 -0
  107. package/dist/web/public/session-ui.f4fed187.js.br +0 -0
  108. package/dist/web/public/session-ui.f4fed187.js.gz +0 -0
  109. package/dist/web/public/settings-ui.c674f367.js +0 -67
  110. package/dist/web/public/settings-ui.c674f367.js.br +0 -0
  111. package/dist/web/public/settings-ui.c674f367.js.gz +0 -0
  112. package/dist/web/public/styles.2eb23e0f.css +0 -1
  113. package/dist/web/public/styles.2eb23e0f.css.br +0 -0
  114. package/dist/web/public/styles.2eb23e0f.css.gz +0 -0
  115. package/dist/web/public/terminal-ui.61c7829d.js +0 -4
  116. package/dist/web/public/terminal-ui.61c7829d.js.br +0 -0
  117. package/dist/web/public/terminal-ui.61c7829d.js.gz +0 -0
  118. package/dist/web/public/voice-input.e5461859.js.br +0 -0
  119. package/dist/web/public/voice-input.e5461859.js.gz +0 -0
package/README.md CHANGED
@@ -254,7 +254,7 @@ Click **+ New Session** (or **Quick Start**). A session is one AI CLI running in
254
254
  | ---------------------------- | ------------------------------------------------------------------------------------------------------------------- |
255
255
  | **Working directory / case** | The folder the agent operates in. A "case" is just a named working dir Codeman remembers. **Add Case** creates one from scratch, links an existing folder, or clones a GitHub repo straight into one (**Clone Repo**). |
256
256
  | **CLI / run mode** | `Claude` (default), `OpenCode`, `Codex`, `Antigravity`, `Gemini`, or `Terminal` (plain shell). |
257
- | **Model** | Per-session model (App Settings → Claude Model). A soft default — `/model` still works in-session. |
257
+ | **Model** | Per-session model (App Settings → Models → New Claude sessions). A soft default — `/model` still works in-session. |
258
258
  | **Effort / Ultracode** | Reasoning effort (`low`–`max`) or `ultracode` for dynamic multi-agent workflows. Switchable anytime with `/effort`. |
259
259
 
260
260
  Hit start — Codeman spawns the CLI via a real PTY and streams it to your browser over SSE.
@@ -278,7 +278,7 @@ Hit start — Codeman spawns the CLI via a real PTY and streams it to your brows
278
278
  | ---------------- | --------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------- |
279
279
  | **Respawn** | Long unattended runs — auto-restarts the CLI on idle/limit, with adaptive timing. Presets: `solo-work`, `overnight-autonomous`, … | Respawn tab |
280
280
  | **Orchestrator** | Turn one goal into a phased plan and drive it to completion across agents. | Orchestrator panel |
281
- | **Cron** | Saved, named jobs on a schedule (`once`/`interval`/`daily`/`weekly`) that spawn a session and send a prompt when due. | ⏰ Cron button _(opt-in: App Settings → DisplayHeader Displays)_ |
281
+ | **Cron** | Saved, named jobs on a schedule (`once`/`interval`/`daily`/`weekly`) that spawn a session and send a prompt when due. | ⏰ Cron button _(opt-in: App Settings → Header & Panels Scheduling)_ |
282
282
  | **Auto-resume** | Automatically continue after a subscription rate-limit resets. | Respawn tab (top) |
283
283
 
284
284
  ### 6. Reach it from anywhere
@@ -291,7 +291,7 @@ Hit start — Codeman spawns the CLI via a real PTY and streams it to your brows
291
291
 
292
292
  - **App Settings** — model, effort, permission startup mode, theme/skin, notifications, display toggles, per-CLI options, a synced custom display name, and per-device English/Simplified Chinese UI language.
293
293
  - **Run it in the background** — `codeman web -d` detaches from your shell (`--status`, `--stop`); `codeman service install` makes it a systemd user unit / macOS LaunchAgent that survives reboots. Both verify the server actually answers before reporting success, and both refuse to start a second server on one data dir. See [Keep it running in the background](#quick-start---installation).
294
- - **Self-update** — git-clone installs update in place from **Settings → Updates**.
294
+ - **Self-update** — git-clone installs update in place from **App Settings → System → Updates**.
295
295
  - **Deploy your own changes** — see [Development](#development).
296
296
 
297
297
  > ⚠️ **Safety:** if you're working _inside_ a Codeman-managed session (`echo $CODEMAN_MUX` → `1`), never run `tmux kill-session` / `pkill claude` directly — use the web UI or `./scripts/tmux-manager.sh`.
@@ -427,7 +427,7 @@ PTY Output → 16ms Server Batch → DEC 2026 Wrap → SSE → Client rAF → xt
427
427
  ## More Features
428
428
 
429
429
  - **Background daemon & service install** — `codeman web -d` runs the server detached with a pidfile, `~/.codeman/web.log`, and verified startup (it polls the server until it answers, so a port clash never reads as success); `codeman service install` writes a systemd user unit (Linux) or LaunchAgent (macOS) with your shell's PATH baked in, so an nvm or Homebrew `node`, `tmux` and `claude` are actually found. Secrets are never written into unit files
430
- - **Self-update** — git-clone installs under systemd/launchd update in place from **App Settings → Updates**: it detects the latest release, auto-stashes a dirty tree, and streams build progress across the service restart (npm installs report as non-updatable)
430
+ - **Self-update** — git-clone installs under systemd/launchd update in place from **App Settings → System → Updates**: it detects the latest release, auto-stashes a dirty tree, and streams build progress across the service restart (npm installs report as non-updatable)
431
431
  - **Clone a GitHub repo as a case** — paste a repository URL into **Add Case → Clone Repo** and Codeman clones it into `~/codeman-cases/<name>` and registers it as a normal case, ready to run an agent in. It preflights the URL while you type (tells you whether it can be cloned anonymously and offers the repo's real branches and tags for the optional branch/tag field), fills the case name in from the URL, and lets you pick which CLI the Run button should use. Public repositories over `https://`; Codeman never collects or stores credentials
432
432
  - **Multi-CLI** — run **Claude Code**, **OpenCode**, **Codex**, **Antigravity**, or **Gemini** per session; env-var prefixes auto-gate (`CLAUDE_CODE_*` vs `OPENCODE_*` vs `CODEX_*` vs `ANTIGRAVITY_*` vs `GEMINI_*`/`GOOGLE_*`). See [`docs/opencode-integration.md`](docs/opencode-integration.md)
433
433
  - **Docker sessions** — run a case inside an isolated, hardened container. One checkbox on **Create New** spins up a container with sensible defaults and starts the agent inside it; multiple sessions share one per-case container; export a container + its workspace to a portable `.tar.gz` to move it to another machine. See [`docs/docker-cases.md`](docs/docker-cases.md)
@@ -435,9 +435,9 @@ PTY Output → 16ms Server Batch → DEC 2026 Wrap → SSE → Client rAF → xt
435
435
  - **Effort & Ultracode** — set a per-session default effort (`low`–`max`) or enable **ultracode** (dynamic multi-agent workflows). Soft defaults only — switchable anytime with `/effort` in-session. Extended-thinking budget is configurable too
436
436
  - **Voice input** — dictate prompts with Deepgram Nova-3 (Web Speech API fallback): toggle recording, auto-silence stop, live level meter (`Ctrl+Shift+V`)
437
437
  - **Image input** — paste or drag-and-drop images straight into a session
438
- - **Gesture control** _(opt-in)_ — a MediaPipe hand-tracking overlay to grab/drag session windows and pinch buttons, hands-free. Enable with `CODEMAN_GESTURE=1` + App Settings → Display
438
+ - **Gesture control** _(opt-in)_ — a MediaPipe hand-tracking overlay to grab/drag session windows and pinch buttons, hands-free. Enable with `CODEMAN_GESTURE=1` + App Settings → Terminal & Input
439
439
  - **Multi-monitor span** _(macOS)_ — one click opens a browser window maximized across all displays, so floating agent/gesture panels can cross the physical seam
440
- - **File Viewer button** _(opt-in)_ — a header button that toggles the built-in file browser panel with one tap; enable under App Settings → Display → Header Displays
440
+ - **File Viewer button** _(opt-in)_ — a header button that toggles the built-in file browser panel with one tap; enable under App Settings → Header & Panels → Header buttons
441
441
  - **CJK / IME input** — full composition support for Chinese / Japanese / Korean
442
442
  - **OS notifications & hostname-aware titles** — desktop alerts and tab titles are prefixed `codeman:<host>` so multi-host setups stay unambiguous
443
443
 
@@ -521,7 +521,7 @@ The script auto-installs a systemd user service on first run. The tunnel URL is
521
521
  systemctl --user enable codeman-tunnel
522
522
  loginctl enable-linger $USER
523
523
 
524
- # Or via the Codeman web UI: Settings → TunnelToggle On
524
+ # Or via the Codeman web UI: App Settings → SystemRemote access → Cloudflare Tunnel
525
525
  ```
526
526
 
527
527
  </details>
@@ -623,7 +623,7 @@ By default Codeman launches sessions with `--dangerously-skip-permissions`, so t
623
623
  - **Loopback by default** — the server binary binds `127.0.0.1`, reachable only from the same machine, so the no-password default is safe out of the box (the guided installer asks about network access and configures the binding + password for you). Binding a non-loopback host without `CODEMAN_PASSWORD` _starts but prints a loud warning_ with three concrete fixes (set a password, loopback + an authenticated tunnel, or explicitly acknowledge with `--allow-unauthenticated-network`)
624
624
  - **Optional auth, real sessions** — HTTP Basic via `CODEMAN_USERNAME` (default `admin`) / `CODEMAN_PASSWORD`. Success issues an opaque 256-bit `codeman_session` cookie (`randomBytes(32)`) — validated server-side, not client-signed, so it can't be forged offline (24h TTL, auto-extend, device-context audit log)
625
625
  - **Per-IP rate limiting** — 10 failed attempts → `429` with `Retry-After` (15-min decay). A valid cookie or correct password recovers _immediately_ even while an attacker hammers the same IP — important because all tunnel traffic shares one loopback IP. QR auth has its own separate limiter
626
- - **Configurable permission mode** - `--dangerously-skip-permissions` is only the default. **App Settings → Claude CLI → Startup Mode** can switch new sessions to Anthropic's classifier-guarded `auto` mode (low-prompt, needs Claude Code 2.1.207+), `normal` prompting, or an explicit allowed-tools list. In multi-user mode, non-granted users are forced to `auto`, and shell sessions / skip-permissions require an explicit per-user grant
626
+ - **Configurable permission mode** - `--dangerously-skip-permissions` is only the default. **App Settings → Agents & CLIs Claude → Startup Mode** can switch new sessions to Anthropic's classifier-guarded `auto` mode (low-prompt, needs Claude Code 2.1.207+), `normal` prompting, or an explicit allowed-tools list. In multi-user mode, non-granted users are forced to `auto`, and shell sessions / skip-permissions require an explicit per-user grant
627
627
 
628
628
  ### Always-on browser hardening (v0.9.5)
629
629
 
@@ -696,7 +696,7 @@ For AI agents and automation that control Codeman without a browser: an agent th
696
696
  >
697
697
  > - `npx skills add Ark0N/Codeman --skill codeman -g`: global, works for any skills-aware agent
698
698
  > - `codeman skill install` (global) or `codeman skill install --case <name>`: for npm installs that never cloned the repo; `codeman skill uninstall` reverses it
699
- > - **App Settings → Agent Skill** (`agentSkillEnabled`, default off): Codeman then injects the skill into each case on Claude session create; a user-authored `skills/codeman` in the case is never overwritten
699
+ > - **App Settings → Agents & CLIs → Claude → Agent Skill** (`agentSkillEnabled`, default off): Codeman then injects the skill into each case on Claude session create; a user-authored `skills/codeman` in the case is never overwritten
700
700
  >
701
701
  > A global install (`codeman skill install`, or `npx skills add`) is picked up by **every new Claude Code session on the machine**, inside Codeman or not. The skill self-gates: outside a Codeman session (`CODEMAN_MUX` unset) it refuses to act, so a global install costs an idle session nothing.
702
702
  >
@@ -0,0 +1,50 @@
1
+ /**
2
+ * @fileoverview Read-only access to the Claude Code OAuth credentials.
3
+ *
4
+ * Claude Code stores its subscription OAuth tokens in
5
+ * `$CLAUDE_CONFIG_DIR/.credentials.json` (default `~/.claude/.credentials.json`,
6
+ * mode 0600) on Linux/Windows, and in the login keychain on macOS. Codeman reads
7
+ * the access token to authenticate the voice-dictation relay
8
+ * (`src/web/voice-stream.ts`) against the same speech-to-text service the CLI's
9
+ * own `/voice` mode uses.
10
+ *
11
+ * ⚠️ READ-ONLY, deliberately. Codeman never writes this file and never performs
12
+ * an OAuth refresh: a refresh ROTATES the refresh token, so racing Claude Code's
13
+ * own refresh could invalidate the user's CLI login. An expired access token is
14
+ * reported as `expired` and the caller tells the user to run a Claude session
15
+ * (which refreshes it) instead.
16
+ *
17
+ * ⚠️ The token is a bearer secret: it is never logged, never persisted, never
18
+ * included in any API response, and never sent to the browser.
19
+ */
20
+ /** Result of inspecting the credential store. The token is present only on 'ok'. */
21
+ export type ClaudeCredentialStatus = 'ok' | 'expired' | 'missing' | 'malformed';
22
+ export interface ClaudeOAuthCredentials {
23
+ status: ClaudeCredentialStatus;
24
+ /** Bearer token. Present only when status is 'ok'. Never log or serialize this. */
25
+ accessToken?: string;
26
+ /** Epoch ms the access token expires at, when the store reports one. */
27
+ expiresAt?: number;
28
+ /** e.g. 'max', 'pro'. Display-only, safe to surface. */
29
+ subscriptionType?: string;
30
+ }
31
+ /**
32
+ * Parse a `.credentials.json` payload. Pure: no IO, no clock read (pass `now`),
33
+ * so the expiry and shape handling are unit-testable.
34
+ *
35
+ * Returns 'malformed' for anything that is not the expected `claudeAiOauth`
36
+ * shape rather than throwing — a hand-edited or half-written file must degrade
37
+ * to "voice unavailable", never to a 500.
38
+ */
39
+ export declare function parseClaudeCredentials(raw: string, now: number): ClaudeOAuthCredentials;
40
+ /** Path of the credentials file, honoring CLAUDE_CONFIG_DIR like the CLI does. */
41
+ export declare function claudeCredentialsPath(env?: NodeJS.ProcessEnv): string;
42
+ /**
43
+ * Locate and parse the Claude Code OAuth credentials.
44
+ *
45
+ * File first (present on every platform once the CLI has run there), keychain
46
+ * second on macOS. Never caches: Claude Code rewrites the store roughly every
47
+ * 8 hours, and a cached token would go stale inside a long-lived server.
48
+ */
49
+ export declare function readClaudeOAuthCredentials(now?: number): Promise<ClaudeOAuthCredentials>;
50
+ //# sourceMappingURL=claude-credentials.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-credentials.d.ts","sourceRoot":"","sources":["../src/claude-credentials.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAOH,oFAAoF;AACpF,MAAM,MAAM,sBAAsB,GAAG,IAAI,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,CAAC;AAEhF,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,sBAAsB,CAAC;IAC/B,mFAAmF;IACnF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wEAAwE;IACxE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wDAAwD;IACxD,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAWD;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,sBAAsB,CAyBvF;AAED,kFAAkF;AAClF,wBAAgB,qBAAqB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAGlF;AAcD;;;;;;GAMG;AACH,wBAAsB,0BAA0B,CAAC,GAAG,GAAE,MAAmB,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAkB1G"}
@@ -0,0 +1,102 @@
1
+ /**
2
+ * @fileoverview Read-only access to the Claude Code OAuth credentials.
3
+ *
4
+ * Claude Code stores its subscription OAuth tokens in
5
+ * `$CLAUDE_CONFIG_DIR/.credentials.json` (default `~/.claude/.credentials.json`,
6
+ * mode 0600) on Linux/Windows, and in the login keychain on macOS. Codeman reads
7
+ * the access token to authenticate the voice-dictation relay
8
+ * (`src/web/voice-stream.ts`) against the same speech-to-text service the CLI's
9
+ * own `/voice` mode uses.
10
+ *
11
+ * ⚠️ READ-ONLY, deliberately. Codeman never writes this file and never performs
12
+ * an OAuth refresh: a refresh ROTATES the refresh token, so racing Claude Code's
13
+ * own refresh could invalidate the user's CLI login. An expired access token is
14
+ * reported as `expired` and the caller tells the user to run a Claude session
15
+ * (which refreshes it) instead.
16
+ *
17
+ * ⚠️ The token is a bearer secret: it is never logged, never persisted, never
18
+ * included in any API response, and never sent to the browser.
19
+ */
20
+ import { readFile } from 'fs/promises';
21
+ import { execFile } from 'child_process';
22
+ import { homedir, userInfo } from 'os';
23
+ import { join } from 'path';
24
+ /** Skew applied to the stored expiry so a token that dies mid-stream is refused up front. */
25
+ const EXPIRY_SKEW_MS = 60_000;
26
+ /** macOS keychain service holding the same JSON blob as `.credentials.json`. */
27
+ const KEYCHAIN_SERVICE = 'Claude Code-credentials';
28
+ /** Keychain lookups shell out; keep them short so a locked keychain cannot hang a request. */
29
+ const KEYCHAIN_TIMEOUT_MS = 3000;
30
+ /**
31
+ * Parse a `.credentials.json` payload. Pure: no IO, no clock read (pass `now`),
32
+ * so the expiry and shape handling are unit-testable.
33
+ *
34
+ * Returns 'malformed' for anything that is not the expected `claudeAiOauth`
35
+ * shape rather than throwing — a hand-edited or half-written file must degrade
36
+ * to "voice unavailable", never to a 500.
37
+ */
38
+ export function parseClaudeCredentials(raw, now) {
39
+ let parsed;
40
+ try {
41
+ parsed = JSON.parse(raw);
42
+ }
43
+ catch {
44
+ return { status: 'malformed' };
45
+ }
46
+ if (!parsed || typeof parsed !== 'object')
47
+ return { status: 'malformed' };
48
+ const oauth = parsed.claudeAiOauth;
49
+ if (!oauth || typeof oauth !== 'object')
50
+ return { status: 'malformed' };
51
+ const record = oauth;
52
+ const accessToken = typeof record.accessToken === 'string' ? record.accessToken.trim() : '';
53
+ if (!accessToken)
54
+ return { status: 'malformed' };
55
+ const expiresAt = typeof record.expiresAt === 'number' ? record.expiresAt : undefined;
56
+ const subscriptionType = typeof record.subscriptionType === 'string' ? record.subscriptionType : undefined;
57
+ // An expired token is a real state (the CLI refreshes on its next run), not a
58
+ // malformed store: report it separately so the UI can say something useful.
59
+ if (expiresAt !== undefined && expiresAt - EXPIRY_SKEW_MS <= now) {
60
+ return { status: 'expired', expiresAt, subscriptionType };
61
+ }
62
+ return { status: 'ok', accessToken, expiresAt, subscriptionType };
63
+ }
64
+ /** Path of the credentials file, honoring CLAUDE_CONFIG_DIR like the CLI does. */
65
+ export function claudeCredentialsPath(env = process.env) {
66
+ const configDir = typeof env.CLAUDE_CONFIG_DIR === 'string' && env.CLAUDE_CONFIG_DIR.trim();
67
+ return join(configDir || join(homedir(), '.claude'), '.credentials.json');
68
+ }
69
+ /** Read the macOS keychain entry. Resolves to null on any failure (locked, absent, non-mac). */
70
+ function readKeychainCredentials() {
71
+ return new Promise((resolve) => {
72
+ execFile('security', ['find-generic-password', '-a', userInfo().username, '-w', '-s', KEYCHAIN_SERVICE], { encoding: 'utf-8', timeout: KEYCHAIN_TIMEOUT_MS }, (err, stdout) => resolve(err ? null : stdout.trim() || null));
73
+ });
74
+ }
75
+ /**
76
+ * Locate and parse the Claude Code OAuth credentials.
77
+ *
78
+ * File first (present on every platform once the CLI has run there), keychain
79
+ * second on macOS. Never caches: Claude Code rewrites the store roughly every
80
+ * 8 hours, and a cached token would go stale inside a long-lived server.
81
+ */
82
+ export async function readClaudeOAuthCredentials(now = Date.now()) {
83
+ let fileResult = null;
84
+ try {
85
+ fileResult = parseClaudeCredentials(await readFile(claudeCredentialsPath(), 'utf-8'), now);
86
+ }
87
+ catch {
88
+ fileResult = null;
89
+ }
90
+ if (fileResult && fileResult.status !== 'malformed')
91
+ return fileResult;
92
+ if (process.platform === 'darwin') {
93
+ const raw = await readKeychainCredentials();
94
+ if (raw) {
95
+ const keychainResult = parseClaudeCredentials(raw, now);
96
+ if (keychainResult.status !== 'malformed')
97
+ return keychainResult;
98
+ }
99
+ }
100
+ return fileResult ?? { status: 'missing' };
101
+ }
102
+ //# sourceMappingURL=claude-credentials.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-credentials.js","sourceRoot":"","sources":["../src/claude-credentials.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,IAAI,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAe5B,6FAA6F;AAC7F,MAAM,cAAc,GAAG,MAAM,CAAC;AAE9B,gFAAgF;AAChF,MAAM,gBAAgB,GAAG,yBAAyB,CAAC;AAEnD,8FAA8F;AAC9F,MAAM,mBAAmB,GAAG,IAAI,CAAC;AAEjC;;;;;;;GAOG;AACH,MAAM,UAAU,sBAAsB,CAAC,GAAW,EAAE,GAAW;IAC7D,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;IACjC,CAAC;IACD,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ;QAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;IAE1E,MAAM,KAAK,GAAI,MAAsC,CAAC,aAAa,CAAC;IACpE,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;IAExE,MAAM,MAAM,GAAG,KAAgC,CAAC;IAChD,MAAM,WAAW,GAAG,OAAO,MAAM,CAAC,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAC5F,IAAI,CAAC,WAAW;QAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;IAEjD,MAAM,SAAS,GAAG,OAAO,MAAM,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;IACtF,MAAM,gBAAgB,GAAG,OAAO,MAAM,CAAC,gBAAgB,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC,SAAS,CAAC;IAE3G,8EAA8E;IAC9E,4EAA4E;IAC5E,IAAI,SAAS,KAAK,SAAS,IAAI,SAAS,GAAG,cAAc,IAAI,GAAG,EAAE,CAAC;QACjE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,gBAAgB,EAAE,CAAC;IAC5D,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,SAAS,EAAE,gBAAgB,EAAE,CAAC;AACpE,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,qBAAqB,CAAC,MAAyB,OAAO,CAAC,GAAG;IACxE,MAAM,SAAS,GAAG,OAAO,GAAG,CAAC,iBAAiB,KAAK,QAAQ,IAAI,GAAG,CAAC,iBAAiB,CAAC,IAAI,EAAE,CAAC;IAC5F,OAAO,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,CAAC,EAAE,mBAAmB,CAAC,CAAC;AAC5E,CAAC;AAED,gGAAgG;AAChG,SAAS,uBAAuB;IAC9B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,QAAQ,CACN,UAAU,EACV,CAAC,uBAAuB,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,gBAAgB,CAAC,EAClF,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,mBAAmB,EAAE,EACnD,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC,CAC7D,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAAC,MAAc,IAAI,CAAC,GAAG,EAAE;IACvE,IAAI,UAAU,GAAkC,IAAI,CAAC;IACrD,IAAI,CAAC;QACH,UAAU,GAAG,sBAAsB,CAAC,MAAM,QAAQ,CAAC,qBAAqB,EAAE,EAAE,OAAO,CAAC,EAAE,GAAG,CAAC,CAAC;IAC7F,CAAC;IAAC,MAAM,CAAC;QACP,UAAU,GAAG,IAAI,CAAC;IACpB,CAAC;IACD,IAAI,UAAU,IAAI,UAAU,CAAC,MAAM,KAAK,WAAW;QAAE,OAAO,UAAU,CAAC;IAEvE,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAClC,MAAM,GAAG,GAAG,MAAM,uBAAuB,EAAE,CAAC;QAC5C,IAAI,GAAG,EAAE,CAAC;YACR,MAAM,cAAc,GAAG,sBAAsB,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YACxD,IAAI,cAAc,CAAC,MAAM,KAAK,WAAW;gBAAE,OAAO,cAAc,CAAC;QACnE,CAAC;IACH,CAAC;IAED,OAAO,UAAU,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;AAC7C,CAAC"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * @fileoverview Bounds and endpoint config for Claude voice dictation.
3
+ *
4
+ * Backs the browser → Codeman → Anthropic dictation relay (`src/web/voice-stream.ts`,
5
+ * `src/web/routes/voice-routes.ts`; design in `docs/claude-voice-plan.md`).
6
+ *
7
+ * Why everything here is bounded: an open microphone is an open pipe. Each live
8
+ * stream holds a browser socket, an upstream socket and a keepalive timer, and
9
+ * every second of audio is billed against the server owner's Claude subscription.
10
+ * A tab left recording (phone in a pocket, forgotten laptop) must cost a bounded
11
+ * amount, so streams die on their own at `MAX_STREAM_MS` and the server refuses
12
+ * more than `MAX_CONCURRENT_STREAMS` at once.
13
+ *
14
+ * The audio frame cap is a memory guard on a socket that carries attacker-shaped
15
+ * binary data: PCM16 at 16 kHz mono is 32 KB/s, so a 256 ms frame is ~8 KB and
16
+ * anything near 64 KB is either a broken client or an attempt to make the relay
17
+ * buffer for someone else.
18
+ */
19
+ /** Upstream speech-to-text service (the one Claude Code's own `/voice` mode uses). */
20
+ export declare const VOICE_STREAM_HOST = "wss://api.anthropic.com";
21
+ /** Path of the streaming speech-to-text endpoint. */
22
+ export declare const VOICE_STREAM_PATH = "/api/ws/speech_to_text/voice_stream";
23
+ /**
24
+ * Base override, for tests (point the relay at a local mock) and for users on an
25
+ * Anthropic-compatible gateway. Must be a ws:// or wss:// origin.
26
+ */
27
+ export declare function voiceStreamBase(env?: NodeJS.ProcessEnv): string;
28
+ /** Upstream drops an idle socket; the CLI pings at 8s and so do we. */
29
+ export declare const KEEPALIVE_INTERVAL_MS = 8000;
30
+ /** Hard ceiling on one dictation. Long enough for any real utterance, short enough to bound a forgotten mic. */
31
+ export declare const MAX_STREAM_MS: number;
32
+ /** Concurrent relays server-wide. Dictation is a human-paced, one-at-a-time act. */
33
+ export declare const MAX_CONCURRENT_STREAMS = 4;
34
+ /** Largest single audio frame accepted from the browser (~2s of PCM16 @16 kHz mono). */
35
+ export declare const MAX_AUDIO_FRAME_BYTES: number;
36
+ /** How long to wait for the final transcript after the client asks to finalize. */
37
+ export declare const FINALIZE_TIMEOUT_MS = 3000;
38
+ /** Upstream caps the keyterms header; mirrors the CLI's own limit. */
39
+ export declare const MAX_KEYTERMS_HEADER_CHARS = 1024;
40
+ /** Audio format the endpoint is opened with. The browser worklet must match exactly. */
41
+ export declare const AUDIO_SAMPLE_RATE = 16000;
42
+ export declare const AUDIO_CHANNELS = 1;
43
+ //# sourceMappingURL=voice.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"voice.d.ts","sourceRoot":"","sources":["../../src/config/voice.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,sFAAsF;AACtF,eAAO,MAAM,iBAAiB,4BAA4B,CAAC;AAE3D,qDAAqD;AACrD,eAAO,MAAM,iBAAiB,wCAAwC,CAAC;AAEvE;;;GAGG;AACH,wBAAgB,eAAe,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAI5E;AAED,uEAAuE;AACvE,eAAO,MAAM,qBAAqB,OAAO,CAAC;AAE1C,gHAAgH;AAChH,eAAO,MAAM,aAAa,QAAa,CAAC;AAExC,oFAAoF;AACpF,eAAO,MAAM,sBAAsB,IAAI,CAAC;AAExC,wFAAwF;AACxF,eAAO,MAAM,qBAAqB,QAAY,CAAC;AAE/C,mFAAmF;AACnF,eAAO,MAAM,mBAAmB,OAAO,CAAC;AAExC,sEAAsE;AACtE,eAAO,MAAM,yBAAyB,OAAO,CAAC;AAE9C,wFAAwF;AACxF,eAAO,MAAM,iBAAiB,QAAQ,CAAC;AACvC,eAAO,MAAM,cAAc,IAAI,CAAC"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * @fileoverview Bounds and endpoint config for Claude voice dictation.
3
+ *
4
+ * Backs the browser → Codeman → Anthropic dictation relay (`src/web/voice-stream.ts`,
5
+ * `src/web/routes/voice-routes.ts`; design in `docs/claude-voice-plan.md`).
6
+ *
7
+ * Why everything here is bounded: an open microphone is an open pipe. Each live
8
+ * stream holds a browser socket, an upstream socket and a keepalive timer, and
9
+ * every second of audio is billed against the server owner's Claude subscription.
10
+ * A tab left recording (phone in a pocket, forgotten laptop) must cost a bounded
11
+ * amount, so streams die on their own at `MAX_STREAM_MS` and the server refuses
12
+ * more than `MAX_CONCURRENT_STREAMS` at once.
13
+ *
14
+ * The audio frame cap is a memory guard on a socket that carries attacker-shaped
15
+ * binary data: PCM16 at 16 kHz mono is 32 KB/s, so a 256 ms frame is ~8 KB and
16
+ * anything near 64 KB is either a broken client or an attempt to make the relay
17
+ * buffer for someone else.
18
+ */
19
+ /** Upstream speech-to-text service (the one Claude Code's own `/voice` mode uses). */
20
+ export const VOICE_STREAM_HOST = 'wss://api.anthropic.com';
21
+ /** Path of the streaming speech-to-text endpoint. */
22
+ export const VOICE_STREAM_PATH = '/api/ws/speech_to_text/voice_stream';
23
+ /**
24
+ * Base override, for tests (point the relay at a local mock) and for users on an
25
+ * Anthropic-compatible gateway. Must be a ws:// or wss:// origin.
26
+ */
27
+ export function voiceStreamBase(env = process.env) {
28
+ const override = typeof env.CODEMAN_VOICE_STREAM_BASE === 'string' ? env.CODEMAN_VOICE_STREAM_BASE.trim() : '';
29
+ if (override && /^wss?:\/\//.test(override))
30
+ return override.replace(/\/+$/, '');
31
+ return VOICE_STREAM_HOST;
32
+ }
33
+ /** Upstream drops an idle socket; the CLI pings at 8s and so do we. */
34
+ export const KEEPALIVE_INTERVAL_MS = 8000;
35
+ /** Hard ceiling on one dictation. Long enough for any real utterance, short enough to bound a forgotten mic. */
36
+ export const MAX_STREAM_MS = 5 * 60_000;
37
+ /** Concurrent relays server-wide. Dictation is a human-paced, one-at-a-time act. */
38
+ export const MAX_CONCURRENT_STREAMS = 4;
39
+ /** Largest single audio frame accepted from the browser (~2s of PCM16 @16 kHz mono). */
40
+ export const MAX_AUDIO_FRAME_BYTES = 64 * 1024;
41
+ /** How long to wait for the final transcript after the client asks to finalize. */
42
+ export const FINALIZE_TIMEOUT_MS = 3000;
43
+ /** Upstream caps the keyterms header; mirrors the CLI's own limit. */
44
+ export const MAX_KEYTERMS_HEADER_CHARS = 1024;
45
+ /** Audio format the endpoint is opened with. The browser worklet must match exactly. */
46
+ export const AUDIO_SAMPLE_RATE = 16000;
47
+ export const AUDIO_CHANNELS = 1;
48
+ //# sourceMappingURL=voice.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"voice.js","sourceRoot":"","sources":["../../src/config/voice.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,sFAAsF;AACtF,MAAM,CAAC,MAAM,iBAAiB,GAAG,yBAAyB,CAAC;AAE3D,qDAAqD;AACrD,MAAM,CAAC,MAAM,iBAAiB,GAAG,qCAAqC,CAAC;AAEvE;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,MAAyB,OAAO,CAAC,GAAG;IAClE,MAAM,QAAQ,GAAG,OAAO,GAAG,CAAC,yBAAyB,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,yBAAyB,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAC/G,IAAI,QAAQ,IAAI,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC;QAAE,OAAO,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACjF,OAAO,iBAAiB,CAAC;AAC3B,CAAC;AAED,uEAAuE;AACvE,MAAM,CAAC,MAAM,qBAAqB,GAAG,IAAI,CAAC;AAE1C,gHAAgH;AAChH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,GAAG,MAAM,CAAC;AAExC,oFAAoF;AACpF,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC;AAExC,wFAAwF;AACxF,MAAM,CAAC,MAAM,qBAAqB,GAAG,EAAE,GAAG,IAAI,CAAC;AAE/C,mFAAmF;AACnF,MAAM,CAAC,MAAM,mBAAmB,GAAG,IAAI,CAAC;AAExC,sEAAsE;AACtE,MAAM,CAAC,MAAM,yBAAyB,GAAG,IAAI,CAAC;AAE9C,wFAAwF;AACxF,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,CAAC;AACvC,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC"}
@@ -23,6 +23,8 @@ export interface ConfigPort {
23
23
  getTerminalHistoryConfig(): Promise<TerminalHistoryConfig>;
24
24
  /** Synced `agentSkillEnabled` app setting (default OFF); gates per-case agent-skill injection. */
25
25
  getAgentSkillEnabled(): Promise<boolean>;
26
+ /** Synced `claudeVoiceEnabled` app setting (default OFF); gates the Claude voice dictation relay. */
27
+ getClaudeVoiceEnabled(): Promise<boolean>;
26
28
  getDefaultClaudeMdPath(): Promise<string | undefined>;
27
29
  getLightState(identity?: {
28
30
  username: string;
@@ -1 +1 @@
1
- {"version":3,"file":"config-port.d.ts","sourceRoot":"","sources":["../../../src/web/ports/config-port.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC7D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AAE9E,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,mBAAmB,IAAI,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAAC;IACvD,cAAc,IAAI,OAAO,CAAC;QAAE,YAAY,CAAC,EAAE,MAAM,CAAC;QAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,GAAG,IAAI,CAAC,CAAC;IACzG,mBAAmB,IAAI,OAAO,CAAC;QAAE,UAAU,CAAC,EAAE,UAAU,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACnF,wBAAwB,IAAI,OAAO,CAAC,qBAAqB,CAAC,CAAC;IAC3D,kGAAkG;IAClG,oBAAoB,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IACzC,sBAAsB,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IACtD,aAAa,CAAC,QAAQ,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC;IAChF,qBAAqB,IAAI,OAAO,EAAE,CAAC;IACnC,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IACxE,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/C;;;;OAIG;IACH,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IACpD,iGAAiG;IACjG,kBAAkB,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;CACvC"}
1
+ {"version":3,"file":"config-port.d.ts","sourceRoot":"","sources":["../../../src/web/ports/config-port.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC7D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AAE9E,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,mBAAmB,IAAI,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAAC;IACvD,cAAc,IAAI,OAAO,CAAC;QAAE,YAAY,CAAC,EAAE,MAAM,CAAC;QAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,GAAG,IAAI,CAAC,CAAC;IACzG,mBAAmB,IAAI,OAAO,CAAC;QAAE,UAAU,CAAC,EAAE,UAAU,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACnF,wBAAwB,IAAI,OAAO,CAAC,qBAAqB,CAAC,CAAC;IAC3D,kGAAkG;IAClG,oBAAoB,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IACzC,qGAAqG;IACrG,qBAAqB,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1C,sBAAsB,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IACtD,aAAa,CAAC,QAAQ,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC;IAChF,qBAAqB,IAAI,OAAO,EAAE,CAAC;IACnC,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IACxE,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/C;;;;OAIG;IACH,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IACpD,iGAAiG;IACjG,kBAAkB,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;CACvC"}
Binary file
Binary file
Binary file
Binary file
@@ -393,10 +393,14 @@ Object.assign(CodemanApp.prototype, {
393
393
  // that collide with state strings on other surfaces.
394
394
  pill.setAttribute('data-i18n-skip', '');
395
395
  pill.textContent = row.pill;
396
- item.appendChild(pill);
397
396
 
398
- // Wraps onto its own line (the row is flex-wrap) so it gets the full width.
399
- item.appendChild(this._buildHomeSessionsMeta(row));
397
+ // The stamps line wraps onto its own full-width line (the row is flex-wrap)
398
+ // and the pill rides along at its right end, rather than sitting beside the
399
+ // name: that hands the whole width of the rail to the session name, which is
400
+ // what stops it ellipsizing.
401
+ const meta = this._buildHomeSessionsMeta(row);
402
+ meta.appendChild(pill);
403
+ item.appendChild(meta);
400
404
 
401
405
  return item;
402
406
  },
@@ -439,7 +443,14 @@ Object.assign(CodemanApp.prototype, {
439
443
  pill.className = 'home-sessions-pill home-sessions-pill--web';
440
444
  pill.setAttribute('data-i18n-skip', '');
441
445
  pill.textContent = 'web';
442
- item.appendChild(pill);
446
+
447
+ // Same bottom line as a session row (minus the stamps, a dashboard has
448
+ // none), so the pill sits in the same place on every row in the rail.
449
+ const foot = document.createElement('span');
450
+ foot.className = 'home-sessions-row-meta';
451
+ foot.setAttribute('data-i18n-skip', '');
452
+ foot.appendChild(pill);
453
+ item.appendChild(foot);
443
454
 
444
455
  return item;
445
456
  },
Binary file
Binary file
@@ -0,0 +1 @@
1
+ "use strict";(function(a){"use strict";const c="Codeman",O=new Set(["en","zh-CN"]),y=["title","aria-label","placeholder"],x=["[data-i18n-skip]",".xterm",".terminal-container",".terminal-output",".response-content",".response-viewer-content",".file-preview-content",".session-tab-name",".session-name",".case-name",".notif-item-message","pre","code","script","style","textarea"].join(","),D=[".history-item-title",".history-item-subtitle",".history-detail-prompt",".history-detail-path",".folder-history-subtitle"].join(","),m=Object.freeze({"Skip to terminal":"\u8DF3\u8F6C\u5230\u7EC8\u7AEF","Go to main page":"\u8FD4\u56DE\u4E3B\u9875","Session tabs":"\u4F1A\u8BDD\u6807\u7B7E\u9875","Admin Panel":"\u7BA1\u7406\u9762\u677F","Open admin panel":"\u6253\u5F00\u7BA1\u7406\u9762\u677F","Re-dock to dashboard (close window)":"\u91CD\u65B0\u505C\u9760\u5230\u4E3B\u754C\u9762\uFF08\u5173\u95ED\u7A97\u53E3\uFF09","Tunnel status":"\u96A7\u9053\u72B6\u6001","Decrease font size":"\u51CF\u5C0F\u5B57\u4F53","Increase font size":"\u589E\u5927\u5B57\u4F53","Current font size":"\u5F53\u524D\u5B57\u4F53\u5927\u5C0F","System resource usage":"\u7CFB\u7EDF\u8D44\u6E90\u4F7F\u7528\u60C5\u51B5","Redraw terminal":"\u91CD\u7ED8\u7EC8\u7AEF","Redraw terminal to fit current screen (Ctrl+Shift+R)":"\u91CD\u7ED8\u7EC8\u7AEF\u4EE5\u9002\u5E94\u5F53\u524D\u5C4F\u5E55\uFF08Ctrl+Shift+R\uFF09","View last response":"\u67E5\u770B\u6700\u8FD1\u4E00\u6B21\u56DE\u590D","Away Digest":"\u79BB\u5F00\u671F\u95F4\u6458\u8981","Open away digest":"\u6253\u5F00\u79BB\u5F00\u671F\u95F4\u6458\u8981","Session Manager":"\u4F1A\u8BDD\u7BA1\u7406\u5668","Session actions":"\u4F1A\u8BDD\u64CD\u4F5C","Open session manager":"\u6253\u5F00\u4F1A\u8BDD\u7BA1\u7406\u5668",Attachments:"\u9644\u4EF6","Open attachment history":"\u6253\u5F00\u9644\u4EF6\u5386\u53F2","File Viewer":"\u6587\u4EF6\u67E5\u770B\u5668","Open file viewer":"\u6253\u5F00\u6587\u4EF6\u67E5\u770B\u5668","Open Codeman across all displays":"\u5728\u6240\u6709\u663E\u793A\u5668\u4E0A\u6253\u5F00 {name}","Ultracode / Workflow agents":"Ultracode / Workflow \u667A\u80FD\u4F53","Open ultracode workflow agents":"\u6253\u5F00 Ultracode \u5DE5\u4F5C\u6D41\u667A\u80FD\u4F53",Notifications:"\u901A\u77E5","Toggle notifications":"\u5207\u6362\u901A\u77E5\u9762\u677F","Session Lifecycle Log":"\u4F1A\u8BDD\u751F\u547D\u5468\u671F\u65E5\u5FD7","Open session lifecycle log":"\u6253\u5F00\u4F1A\u8BDD\u751F\u547D\u5468\u671F\u65E5\u5FD7","App Settings":"\u5E94\u7528\u8BBE\u7F6E","Open app settings":"\u6253\u5F00\u5E94\u7528\u8BBE\u7F6E","Total tokens across all sessions":"\u6240\u6709\u4F1A\u8BDD\u7684 Token \u603B\u6570","Token usage across active sessions":"\u6D3B\u52A8\u4F1A\u8BDD\u7684 Token \u4F7F\u7528\u91CF","Instance count":"\u5B9E\u4F8B\u6570\u91CF","No response yet":"\u6682\u65E0\u56DE\u590D","No response yet \u2014 send a message in this session first.":"\u6682\u65E0\u56DE\u590D\uFF0C\u8BF7\u5148\u5728\u6B64\u4F1A\u8BDD\u4E2D\u53D1\u9001\u4E00\u6761\u6D88\u606F\u3002","Last Response":"\u6700\u8FD1\u4E00\u6B21\u56DE\u590D",More:"\u66F4\u591A","Codeman version":"{name}\u7248\u672C",Stop:"\u505C\u6B62",Watching:"\u76D1\u89C6\u4E2D",Orchestrator:"\u7F16\u6392\u5668",Close:"\u5173\u95ED","Close window":"\u5173\u95ED\u7A97\u53E3","Session unavailable":"\u4F1A\u8BDD\u4E0D\u53EF\u7528","This session has ended or is no longer available.":"\u6B64\u4F1A\u8BDD\u5DF2\u7ED3\u675F\u6216\u4E0D\u518D\u53EF\u7528\u3002","Manage AI Coding tools in persistent tmux sessions.":"\u5728\u6301\u4E45\u5316 tmux \u4F1A\u8BDD\u4E2D\u7BA1\u7406 AI \u7F16\u7A0B\u5DE5\u5177\u3002","Select case":"\u9009\u62E9\u6848\u4F8B","Select Case":"\u9009\u62E9\u6848\u4F8B","All cases":"\u5168\u90E8\u6848\u4F8B","No directory":"\u672A\u9009\u62E9\u76EE\u5F55",Run:"\u8FD0\u884C","Run Claude Code":"\u8FD0\u884C Claude Code","Run OpenCode":"\u8FD0\u884C OpenCode","Run Gemini":"\u8FD0\u884C Gemini","Run Antigravity":"\u8FD0\u884C Antigravity","Run Shell":"\u8FD0\u884C Shell","Select AI backend":"\u9009\u62E9 AI \u540E\u7AEF","Create New Case":"\u65B0\u5EFA\u6848\u4F8B","Create new case":"\u65B0\u5EFA\u6848\u4F8B","Link Existing":"\u5173\u8054\u73B0\u6709\u76EE\u5F55","Add Case":"\u6DFB\u52A0\u6848\u4F8B","Open sessions":"\u6253\u5F00\u4F1A\u8BDD","Recent Sessions":"\u6700\u8FD1\u4F1A\u8BDD","Search sessions by name, prompt, or path\u2026":"\u6309\u540D\u79F0\u3001\u63D0\u793A\u8BCD\u6216\u8DEF\u5F84\u641C\u7D22\u4F1A\u8BDD\u2026","Search open sessions or start a new one":"\u641C\u7D22\u5DF2\u6253\u5F00\u4F1A\u8BDD\u6216\u542F\u52A8\u65B0\u4F1A\u8BDD","Find Open Session":"\u67E5\u627E\u5DF2\u6253\u5F00\u4F1A\u8BDD","No background agents":"\u6CA1\u6709\u540E\u53F0\u667A\u80FD\u4F53","No background agents detected":"\u672A\u68C0\u6D4B\u5230\u540E\u53F0\u667A\u80FD\u4F53","No notifications":"\u6CA1\u6709\u901A\u77E5","No mux sessions":"\u6CA1\u6709 mux \u4F1A\u8BDD","No lifecycle entries found":"\u672A\u627E\u5230\u751F\u547D\u5468\u671F\u8BB0\u5F55","No ultracode runs detected":"\u672A\u68C0\u6D4B\u5230 Ultracode \u8FD0\u884C",Display:"\u663E\u793A","Claude CLI":"Claude CLI","Codex CLI":"Codex CLI",Models:"\u6A21\u578B",Shortcuts:"\u5FEB\u6377\u952E",Voice:"\u8BED\u97F3",Save:"\u4FDD\u5B58",Cancel:"\u53D6\u6D88",Apply:"\u5E94\u7528",Create:"\u521B\u5EFA",Add:"\u6DFB\u52A0",Delete:"\u5220\u9664",Remove:"\u79FB\u9664",Edit:"\u7F16\u8F91",Refresh:"\u5237\u65B0",Back:"\u8FD4\u56DE",Next:"\u4E0B\u4E00\u6B65",Previous:"\u4E0A\u4E00\u6B65",Clear:"\u6E05\u9664","Clear all":"\u5168\u90E8\u6E05\u9664","Clear All":"\u5168\u90E8\u6E05\u9664",Search:"\u641C\u7D22",Filter:"\u7B5B\u9009",Enable:"\u542F\u7528",Enabled:"\u5DF2\u542F\u7528",Disabled:"\u5DF2\u7981\u7528",Active:"\u6D3B\u52A8","Not active":"\u672A\u6D3B\u52A8",On:"\u5F00",Off:"\u5173",Yes:"\u662F",No:"\u5426",Optional:"\u53EF\u9009",Default:"\u9ED8\u8BA4",Custom:"\u81EA\u5B9A\u4E49",Name:"\u540D\u79F0",Description:"\u63CF\u8FF0",Status:"\u72B6\u6001",Reason:"\u539F\u56E0",Time:"\u65F6\u95F4",Event:"\u4E8B\u4EF6",Events:"\u4E8B\u4EF6",Session:"\u4F1A\u8BDD",Sessions:"\u4F1A\u8BDD",Files:"\u6587\u4EF6",History:"\u5386\u53F2",Summary:"\u6458\u8981",Details:"\u8BE6\u60C5",Options:"\u9009\u9879",Settings:"\u8BBE\u7F6E",Help:"\u5E2E\u52A9",Loading:"\u6B63\u5728\u52A0\u8F7D",Error:"\u9519\u8BEF",Errors:"\u9519\u8BEF",Warning:"\u8B66\u544A",Warnings:"\u8B66\u544A",Info:"\u4FE1\u606F",Complete:"\u5B8C\u6210",Completed:"\u5DF2\u5B8C\u6210",Stopped:"\u5DF2\u505C\u6B62",Running:"\u8FD0\u884C\u4E2D",Idle:"\u7A7A\u95F2",Working:"\u5DE5\u4F5C\u4E2D",Today:"\u4ECA\u5929",Home:"\u4E3B\u9875",Local:"\u672C\u5730",Remote:"\u8FDC\u7A0B",Docker:"Docker",Terminal:"\u7EC8\u7AEF",Prompt:"\u63D0\u793A\u8BCD",Source:"\u6765\u6E90",Type:"\u7C7B\u578B",Language:"\u8BED\u8A00","Branding & Language":"\u54C1\u724C\u4E0E\u8BED\u8A00","Display Name":"\u663E\u793A\u540D\u79F0","Interface Language":"\u754C\u9762\u8BED\u8A00","Name shown in the browser UI and window title. Supports Unicode, including Chinese.":"\u663E\u793A\u5728\u6D4F\u89C8\u5668\u754C\u9762\u548C\u7A97\u53E3\u6807\u9898\u4E2D\u7684\u540D\u79F0\u3002\u652F\u6301 Unicode\uFF0C\u5305\u62EC\u4E2D\u6587\u3002","Language for this device. Dynamic status messages and dialogs use the same language.":"\u6B64\u8BBE\u5907\u4F7F\u7528\u7684\u754C\u9762\u8BED\u8A00\u3002\u52A8\u6001\u72B6\u6001\u6D88\u606F\u4E0E\u5BF9\u8BDD\u6846\u4E5F\u4F1A\u4F7F\u7528\u540C\u4E00\u8BED\u8A00\u3002",English:"English",Appearance:"\u5916\u89C2",Skin:"\u76AE\u80A4","Visual theme for this device (not synced)":"\u6B64\u8BBE\u5907\u7684\u89C6\u89C9\u4E3B\u9898\uFF08\u4E0D\u540C\u6B65\uFF09","Daylight Blue":"\u65E5\u5149\u84DD","Daylight Green":"\u65E5\u5149\u7EFF","OG Codeman":"\u7ECF\u5178 {name}",Performance:"\u6027\u80FD","WebGL Renderer":"WebGL \u6E32\u67D3\u5668","Header Displays":"\u9876\u90E8\u680F\u663E\u793A","Font Controls":"\u5B57\u4F53\u63A7\u5236","System Stats":"\u7CFB\u7EDF\u72B6\u6001","Lifecycle Log":"\u751F\u547D\u5468\u671F\u65E5\u5FD7","Response Viewer":"\u56DE\u590D\u67E5\u770B\u5668","Attachments Button":"\u9644\u4EF6\u6309\u94AE","Multi-monitor Button":"\u591A\u663E\u793A\u5668\u6309\u94AE","Session Manager Button":"\u4F1A\u8BDD\u7BA1\u7406\u5668\u6309\u94AE","Away Digest Button":"\u79BB\u5F00\u671F\u95F4\u6458\u8981\u6309\u94AE","Cron Button":"\u5B9A\u65F6\u4EFB\u52A1\u6309\u94AE","Redraw Terminal Button":"\u91CD\u7ED8\u7EC8\u7AEF\u6309\u94AE","Tab Bar":"\u6807\u7B7E\u680F","Tall Tabs (Name + Folder)":"\u53CC\u884C\u6807\u7B7E\uFF08\u540D\u79F0 + \u6587\u4EF6\u5939\uFF09","Pop-out Button on Tabs":"\u6807\u7B7E\u9875\u5F39\u51FA\u7A97\u53E3\u6309\u94AE",Panels:"\u9762\u677F",Monitor:"\u76D1\u89C6\u5668","Project Insights":"\u9879\u76EE\u6D1E\u5BDF","File Browser":"\u6587\u4EF6\u6D4F\u89C8\u5668",Subagents:"\u5B50\u667A\u80FD\u4F53","Ultracode Agents":"Ultracode \u667A\u80FD\u4F53","Ultracode Floating Windows":"Ultracode \u6D6E\u52A8\u7A97\u53E3","Approvals Inbox":"\u5BA1\u6279\u6536\u4EF6\u7BB1",Approvals:"\u5BA1\u6279","Prompts waiting on you, across all sessions":"\u6240\u6709\u4F1A\u8BDD\u4E2D\u7B49\u5F85\u60A8\u5904\u7406\u7684\u63D0\u793A","No pending approvals":"\u6CA1\u6709\u5F85\u5904\u7406\u7684\u5BA1\u6279","Approvals waiting on you":"\u7B49\u5F85\u60A8\u5BA1\u6279\u7684\u8BF7\u6C42","Open approvals inbox":"\u6253\u5F00\u5BA1\u6279\u6536\u4EF6\u7BB1","Close approvals inbox":"\u5173\u95ED\u5BA1\u6279\u6536\u4EF6\u7BB1",Approve:"\u6279\u51C6","Deny (Esc)":"\u62D2\u7EDD (Esc)",Deny:"\u62D2\u7EDD","Open session":"\u6253\u5F00\u4F1A\u8BDD",Dismiss:"\u5FFD\u7565",Send:"\u53D1\u9001",Permission:"\u6743\u9650",Question:"\u95EE\u9898",Idle:"\u7A7A\u95F2","Read My Mind":"\u8BFB\u5FC3\u672F","Read My Mind: predict your next prompt":"\u8BFB\u5FC3\u672F\uFF1A\u9884\u6D4B\u60A8\u7684\u4E0B\u4E00\u6761\u63D0\u793A","Predict my next prompt":"\u9884\u6D4B\u6211\u7684\u4E0B\u4E00\u6761\u63D0\u793A","Reading your mind\u2026":"\u6B63\u5728\u8BFB\u53D6\u60A8\u7684\u60F3\u6CD5\u2026","No suggestion this time. Add a steer note and Rethink to try again.":"\u8FD9\u6B21\u6CA1\u6709\u5EFA\u8BAE\u3002\u53EF\u6DFB\u52A0\u5F15\u5BFC\u5907\u6CE8\u540E\u70B9\u51FB\u300C\u91CD\u60F3\u300D\u518D\u8BD5\u4E00\u6B21\u3002",Rethink:"\u91CD\u60F3",Insert:"\u63D2\u5165","Put the text on the session's composer without submitting it":"\u5C06\u6587\u672C\u653E\u5165\u4F1A\u8BDD\u8F93\u5165\u6846\u4F46\u4E0D\u63D0\u4EA4","Predicted prompt, editable":"\u9884\u6D4B\u7684\u63D0\u793A\uFF0C\u53EF\u7F16\u8F91","Use this suggestion instead":"\u6539\u7528\u6B64\u5EFA\u8BAE","Steer the rethink, e.g. 'no, I meant the mobile bug'":'\u5F15\u5BFC\u91CD\u60F3\uFF0C\u4F8B\u5982\uFF1A"\u4E0D\uFF0C\u6211\u662F\u6307\u79FB\u52A8\u7AEF\u7684\u95EE\u9898"',"Steer note for Rethink":"\u91CD\u60F3\u7684\u5F15\u5BFC\u5907\u6CE8","Select a session first":"\u8BF7\u5148\u9009\u62E9\u4E00\u4E2A\u4F1A\u8BDD","Read My Mind works on Claude sessions only":"\u8BFB\u5FC3\u672F\u4EC5\u9002\u7528\u4E8E Claude \u4F1A\u8BDD","Prompt sent":"\u63D0\u793A\u5DF2\u53D1\u9001","Inserted, press Enter in the terminal to send":"\u5DF2\u63D2\u5165\uFF0C\u5728\u7EC8\u7AEF\u4E2D\u6309 Enter \u53D1\u9001","Could not reach the session":"\u65E0\u6CD5\u8FDE\u63A5\u5230\u4F1A\u8BDD","Subagent Options":"\u5B50\u667A\u80FD\u4F53\u9009\u9879","Enable Tracking":"\u542F\u7528\u8DDF\u8E2A","Active Tab Only":"\u4EC5\u6D3B\u52A8\u6807\u7B7E\u9875","Image Watcher":"\u56FE\u50CF\u76D1\u89C6\u5668","Enable Globally":"\u5168\u5C40\u542F\u7528","Remote Access":"\u8FDC\u7A0B\u8BBF\u95EE","Cloudflare Tunnel":"Cloudflare \u96A7\u9053","Tunnel URL":"\u96A7\u9053\u5730\u5740","Upload URL":"\u4E0A\u4F20\u5730\u5740",Updates:"\u66F4\u65B0","Current Version":"\u5F53\u524D\u7248\u672C","Check for Updates":"\u68C0\u67E5\u66F4\u65B0","Check now":"\u7ACB\u5373\u68C0\u67E5","Update available":"\u6709\u53EF\u7528\u66F4\u65B0","Update now":"\u7ACB\u5373\u66F4\u65B0","Show CPU and memory usage in header":"\u5728\u9876\u90E8\u680F\u663E\u793A CPU \u4E0E\u5185\u5B58\u4F7F\u7528\u60C5\u51B5","Show session lifecycle log button in header":"\u5728\u9876\u90E8\u680F\u663E\u793A\u4F1A\u8BDD\u751F\u547D\u5468\u671F\u65E5\u5FD7\u6309\u94AE","Show the response viewer (eye) button in header":"\u5728\u9876\u90E8\u680F\u663E\u793A\u56DE\u590D\u67E5\u770B\u5668\uFF08\u773C\u775B\uFF09\u6309\u94AE","Show the file viewer button in header (opens the file browser panel for the active session)":"\u5728\u9876\u90E8\u680F\u663E\u793A\u6587\u4EF6\u67E5\u770B\u5668\u6309\u94AE\uFF08\u6253\u5F00\u5F53\u524D\u4F1A\u8BDD\u7684\u6587\u4EF6\u6D4F\u89C8\u5668\u9762\u677F\uFF09","Show the attachments button in header (opens the attachment history drawer)":"\u5728\u9876\u90E8\u680F\u663E\u793A\u9644\u4EF6\u6309\u94AE\uFF08\u6253\u5F00\u9644\u4EF6\u5386\u53F2\u62BD\u5C49\uFF09","Show the multi-monitor button in the header (opens Codeman spanned across all displays)":"\u5728\u9876\u90E8\u680F\u663E\u793A\u591A\u663E\u793A\u5668\u6309\u94AE\uFF08\u8DE8\u6240\u6709\u663E\u793A\u5668\u6253\u5F00 {name}\uFF09","Show the session manager button in the header (opens the session manager \u2014 sessions also stay reachable via the Ctrl+K palette)":"\u5728\u9876\u90E8\u680F\u663E\u793A\u4F1A\u8BDD\u7BA1\u7406\u5668\u6309\u94AE\uFF08\u4E5F\u53EF\u901A\u8FC7 Ctrl+K \u9762\u677F\u8BBF\u95EE\u4F1A\u8BDD\uFF09","Show the away digest button in the header (opens the 'what happened while you were away' summary)":"\u5728\u9876\u90E8\u680F\u663E\u793A\u79BB\u5F00\u671F\u95F4\u6458\u8981\u6309\u94AE","Show the Cron button in the footer toolbar (opens the cron jobs manager)":"\u5728\u5E95\u90E8\u5DE5\u5177\u680F\u663E\u793A\u5B9A\u65F6\u4EFB\u52A1\u6309\u94AE","Show a terminal redraw button in the header \u2014 refit the terminal to the current screen size (useful when switching between devices)":"\u5728\u9876\u90E8\u680F\u663E\u793A\u7EC8\u7AEF\u91CD\u7ED8\u6309\u94AE\uFF0C\u4EE5\u91CD\u65B0\u9002\u914D\u5F53\u524D\u5C4F\u5E55\u5927\u5C0F","Show folder path below tab name and allow tab bar to wrap into multiple rows":"\u5728\u6807\u7B7E\u540D\u79F0\u4E0B\u663E\u793A\u6587\u4EF6\u5939\u8DEF\u5F84\uFF0C\u5E76\u5141\u8BB8\u6807\u7B7E\u680F\u6362\u884C","Show Monitor panel at bottom right":"\u5728\u53F3\u4E0B\u89D2\u663E\u793A\u76D1\u89C6\u5668\u9762\u677F","Show active tools and file viewers in a floating panel":"\u5728\u6D6E\u52A8\u9762\u677F\u4E2D\u663E\u793A\u6D3B\u52A8\u5DE5\u5177\u4E0E\u6587\u4EF6\u67E5\u770B\u5668","Show file browser panel on the right side":"\u5728\u53F3\u4FA7\u663E\u793A\u6587\u4EF6\u6D4F\u89C8\u5668\u9762\u677F","Show the Subagents panel (independent from Monitor)":"\u663E\u793A\u5B50\u667A\u80FD\u4F53\u9762\u677F\uFF08\u72EC\u7ACB\u4E8E\u76D1\u89C6\u5668\uFF09","Monitor Claude Code background agents in real-time":"\u5B9E\u65F6\u76D1\u89C6 Claude Code \u540E\u53F0\u667A\u80FD\u4F53","Only show subagent windows when their parent tab is selected":"\u4EC5\u5728\u9009\u4E2D\u7236\u6807\u7B7E\u9875\u65F6\u663E\u793A\u5B50\u667A\u80FD\u4F53\u7A97\u53E3","Automatically detect and popup new images in session directories":"\u81EA\u52A8\u68C0\u6D4B\u5E76\u5F39\u51FA\u4F1A\u8BDD\u76EE\u5F55\u4E2D\u7684\u65B0\u56FE\u50CF","Expose Codeman via Cloudflare Tunnel for remote access":"\u901A\u8FC7 Cloudflare \u96A7\u9053\u8FDC\u7A0B\u8BBF\u95EE {name}","Codeman version currently running":"\u5F53\u524D\u8FD0\u884C\u7684{name}\u7248\u672C","Check GitHub for a newer Codeman release":"\u68C0\u67E5 GitHub \u4E0A\u662F\u5426\u6709\u65B0\u7248 {name}",Input:"\u8F93\u5165","Local Echo":"\u672C\u5730\u56DE\u663E","CJK Input":"\u4E2D\u65E5\u97E9\u8F93\u5165","Extended Keyboard Bar":"\u6269\u5C55\u952E\u76D8\u680F","Gesture Control (beta)":"\u624B\u52BF\u63A7\u5236\uFF08\u6D4B\u8BD5\u7248\uFF09","Wheel Scrolls Local History":"\u6EDA\u8F6E\u6EDA\u52A8\u672C\u5730\u5386\u53F2","Instant typing feedback with local echo":"\u901A\u8FC7\u672C\u5730\u56DE\u663E\u5373\u65F6\u663E\u793A\u8F93\u5165","Dedicated IME input field for CJK languages":"\u4E3A\u4E2D\u65E5\u97E9\u8BED\u8A00\u63D0\u4F9B\u4E13\u7528\u8F93\u5165\u6CD5\u6587\u672C\u6846","Extra keys: Tab, Esc, arrows, Ctrl+O":"\u9644\u52A0\u6309\u952E\uFF1ATab\u3001Esc\u3001\u65B9\u5411\u952E\u3001Ctrl+O","Startup Mode":"\u542F\u52A8\u6A21\u5F0F","Skip Permissions (default)":"\u8DF3\u8FC7\u6743\u9650\u786E\u8BA4\uFF08\u9ED8\u8BA4\uFF09","Auto (classifier-guarded, low prompts)":"\u81EA\u52A8\uFF08\u5206\u7C7B\u5668\u4FDD\u62A4\uFF0C\u8F83\u5C11\u63D0\u793A\uFF09","Normal (with prompts)":"\u666E\u901A\uFF08\u663E\u793A\u63D0\u793A\uFF09","Allowed Tools Only":"\u4EC5\u5141\u8BB8\u6307\u5B9A\u5DE5\u5177","Allowed Tools":"\u5141\u8BB8\u7684\u5DE5\u5177","Comma-separated list of tools to allow":"\u4EE5\u9017\u53F7\u5206\u9694\u5141\u8BB8\u4F7F\u7528\u7684\u5DE5\u5177","Enable Ralph / Todo Tracker":"\u542F\u7528 Ralph / \u5F85\u529E\u8DDF\u8E2A\u5668","Claude Permissions":"Claude \u6743\u9650","Agent Teams":"\u667A\u80FD\u4F53\u56E2\u961F","Claude Model":"Claude \u6A21\u578B","1M Opus Context":"Opus 100 \u4E07\u4E0A\u4E0B\u6587","Remote auto-reconnect":"\u8FDC\u7A0B\u81EA\u52A8\u91CD\u8FDE","Thinking Effort":"\u601D\u8003\u5F3A\u5EA6",Low:"\u4F4E",Medium:"\u4E2D",High:"\u9AD8",Max:"\u6700\u9AD8","Nice Priority":"Nice \u4F18\u5148\u7EA7","Enable Nice Priority Reduction":"\u542F\u7528 Nice \u4F18\u5148\u7EA7\u8C03\u6574","Nice Value":"Nice \u503C","Bypass Approvals and Sandbox":"\u7ED5\u8FC7\u5BA1\u6279\u4E0E\u6C99\u7BB1","Default Model":"\u9ED8\u8BA4\u6A21\u578B","Show Optimizer Recommendations":"\u663E\u793A\u4F18\u5316\u5668\u5EFA\u8BAE","Agent Type Overrides":"\u6309\u667A\u80FD\u4F53\u7C7B\u578B\u8986\u76D6","Use Default":"\u4F7F\u7528\u9ED8\u8BA4\u503C","Enable Notifications":"\u542F\u7528\u901A\u77E5","Master toggle for all notification layers":"\u6240\u6709\u901A\u77E5\u5C42\u7684\u603B\u5F00\u5173","Browser Notifications":"\u6D4F\u89C8\u5668\u901A\u77E5","Audio Alerts":"\u58F0\u97F3\u63D0\u9192","Push Notifications":"\u63A8\u9001\u901A\u77E5","Notification Levels":"\u901A\u77E5\u7EA7\u522B",Critical:"\u4E25\u91CD","Per-Event Settings":"\u6309\u4E8B\u4EF6\u8BBE\u7F6E","Permission prompts":"\u6743\u9650\u63D0\u793A","Questions from Claude":"Claude \u63D0\u95EE","Session idle":"\u4F1A\u8BDD\u7A7A\u95F2","Response complete":"\u56DE\u590D\u5B8C\u6210","Respawn cycles":"\u91CD\u751F\u5FAA\u73AF","Task complete":"\u4EFB\u52A1\u5B8C\u6210","Subagent activity":"\u5B50\u667A\u80FD\u4F53\u6D3B\u52A8",Browser:"\u6D4F\u89C8\u5668",Audio:"\u58F0\u97F3",Push:"\u63A8\u9001","Voice Input":"\u8BED\u97F3\u8F93\u5165",Provider:"\u670D\u52A1\u5546","Active Provider":"\u5F53\u524D\u670D\u52A1\u5546","API Key":"API \u5BC6\u94A5","Domain Keywords":"\u9886\u57DF\u5173\u952E\u8BCD","Input Mode":"\u8F93\u5165\u6A21\u5F0F","Direct to input":"\u76F4\u63A5\u8F93\u5165","Compose dialog":"\u7F16\u8F91\u5BF9\u8BDD\u6846","Keyboard Shortcuts":"\u952E\u76D8\u5FEB\u6377\u952E","Customize keyboard shortcuts. Click the binding to capture a new key combination.":"\u81EA\u5B9A\u4E49\u952E\u76D8\u5FEB\u6377\u952E\u3002\u70B9\u51FB\u6309\u952E\u7EC4\u5408\u5373\u53EF\u5F55\u5165\u65B0\u7684\u7EC4\u5408\u3002","Show Shortcuts":"\u663E\u793A\u5FEB\u6377\u952E","Full shortcut reference":"\u5B8C\u6574\u5FEB\u6377\u952E\u53C2\u8003","Needs you":"\u9700\u8981\u4F60","Current sessions":"\u5F53\u524D\u4F1A\u8BDD","Past sessions":"\u5386\u53F2\u4F1A\u8BDD","Show all past sessions":"\u663E\u793A\u5168\u90E8\u5386\u53F2\u4F1A\u8BDD","Show fewer":"\u6536\u8D77","Choose what to run":"\u9009\u62E9\u8FD0\u884C\u65B9\u5F0F","Web / URL":"\u7F51\u9875 / \u94FE\u63A5","Add URL\u2026":"\u6DFB\u52A0\u94FE\u63A5\u2026","Nothing running. Hit Run to start something.":"\u5F53\u524D\u6CA1\u6709\u8FD0\u884C\u4E2D\u7684\u4F1A\u8BDD\u3002\u70B9\u51FB\u201C\u8FD0\u884C\u201D\u5F00\u59CB\u3002","No past conversations yet":"\u5C1A\u65E0\u5386\u53F2\u5BF9\u8BDD","Loading\u2026":"\u52A0\u8F7D\u4E2D\u2026","Overview Home Screen":"\u6982\u89C8\u4E3B\u9875","On phones, the C logo opens a session overview (needs you / spaces / idle) instead of the welcome screen":"\u5728\u624B\u673A\u4E0A\uFF0C\u70B9\u51FB C \u56FE\u6807\u6253\u5F00\u4F1A\u8BDD\u6982\u89C8\uFF08\u9700\u8981\u4F60 / \u7A7A\u95F4 / \u7A7A\u95F2\uFF09\uFF0C\u800C\u4E0D\u662F\u6B22\u8FCE\u9875",Phone:"\u624B\u673A","Open tabs":"\u6253\u5F00\u7684\u6807\u7B7E","Session Options":"\u4F1A\u8BDD\u9009\u9879","Session Name":"\u4F1A\u8BDD\u540D\u79F0","Session Color":"\u4F1A\u8BDD\u989C\u8272","Working Directory":"\u5DE5\u4F5C\u76EE\u5F55","Set working directory":"\u8BBE\u7F6E\u5DE5\u4F5C\u76EE\u5F55","Resume Conversation":"\u7EE7\u7EED\u5BF9\u8BDD","Close Session":"\u5173\u95ED\u4F1A\u8BDD","Choose how to close":"\u9009\u62E9\u5173\u95ED\u65B9\u5F0F","Tmux session keeps running in background":"Tmux \u4F1A\u8BDD\u7EE7\u7EED\u5728\u540E\u53F0\u8FD0\u884C","Terminate the session completely":"\u5F7B\u5E95\u7EC8\u6B62\u4F1A\u8BDD","Cancel close session":"\u53D6\u6D88\u5173\u95ED\u4F1A\u8BDD","Case Name":"\u6848\u4F8B\u540D\u79F0","Folder Path":"\u6587\u4EF6\u5939\u8DEF\u5F84","Default Working Directory":"\u9ED8\u8BA4\u5DE5\u4F5C\u76EE\u5F55","Default directory for new sessions.":"\u65B0\u4F1A\u8BDD\u7684\u9ED8\u8BA4\u76EE\u5F55\u3002","Default CLAUDE.md Template":"\u9ED8\u8BA4 CLAUDE.md \u6A21\u677F","Used when creating new cases. Leave empty for built-in template.":"\u521B\u5EFA\u65B0\u6848\u4F8B\u65F6\u4F7F\u7528\uFF1B\u7559\u7A7A\u5219\u4F7F\u7528\u5185\u7F6E\u6A21\u677F\u3002","Remote Path":"\u8FDC\u7A0B\u8DEF\u5F84","SSH Host/IP":"SSH \u4E3B\u673A/IP","SSH Username":"SSH \u7528\u6237\u540D","SSH Port":"SSH \u7AEF\u53E3","Identity File":"\u8EAB\u4EFD\u6587\u4EF6","Jump Host":"\u8DF3\u677F\u4E3B\u673A","Advanced SSH":"\u9AD8\u7EA7 SSH","Discover existing sessions":"\u53D1\u73B0\u73B0\u6709\u4F1A\u8BDD","Workspace Path":"\u5DE5\u4F5C\u533A\u8DEF\u5F84","Container settings (optional, sensible defaults)":"\u5BB9\u5668\u8BBE\u7F6E\uFF08\u53EF\u9009\uFF0C\u9ED8\u8BA4\u503C\u5408\u7406\uFF09",Template:"\u6A21\u677F",Network:"\u7F51\u7EDC",CPUs:"CPU \u6570",Memory:"\u5185\u5B58",GPUs:"GPU","Cron Jobs":"\u5B9A\u65F6\u4EFB\u52A1","+ New Job":"+ \u65B0\u5EFA\u4EFB\u52A1","New Cron Job":"\u65B0\u5EFA\u5B9A\u65F6\u4EFB\u52A1",Schedule:"\u8BA1\u5212","Schedule Type":"\u8BA1\u5212\u7C7B\u578B",Once:"\u4E00\u6B21",Interval:"\u95F4\u9694",Daily:"\u6BCF\u5929",Weekly:"\u6BCF\u5468","Run At":"\u8FD0\u884C\u65F6\u95F4","Every (minutes)":"\u6BCF\u9694\uFF08\u5206\u949F\uFF09",Weekdays:"\u5DE5\u4F5C\u65E5","Times use the server's local timezone.":"\u65F6\u95F4\u4F7F\u7528\u670D\u52A1\u5668\u672C\u5730\u65F6\u533A\u3002","All Events":"\u5168\u90E8\u4E8B\u4EF6",Created:"\u5DF2\u521B\u5EFA",Started:"\u5DF2\u542F\u52A8",Exit:"\u9000\u51FA",Deleted:"\u5DF2\u5220\u9664",Recovered:"\u5DF2\u6062\u590D","Stale Cleaned":"\u5DF2\u6E05\u7406\u8FC7\u671F\u9879","Mux Died":"Mux \u5DF2\u7EC8\u6B62","Server Started":"\u670D\u52A1\u5668\u5DF2\u542F\u52A8","Server Stopped":"\u670D\u52A1\u5668\u5DF2\u505C\u6B62",Extra:"\u9644\u52A0\u4FE1\u606F","Token Usage Statistics":"Token \u4F7F\u7528\u7EDF\u8BA1","Daily Breakdown":"\u6BCF\u65E5\u660E\u7EC6","Export JSON":"\u5BFC\u51FA JSON","Export MD":"\u5BFC\u51FA Markdown","Settings saved":"\u8BBE\u7F6E\u5DF2\u4FDD\u5B58","Settings saved locally":"\u8BBE\u7F6E\u5DF2\u4FDD\u5B58\u5230\u672C\u673A","Tunnel active":"\u96A7\u9053\u5DF2\u542F\u7528","Tunnel starting \u2014 QR code will appear when ready...":"\u96A7\u9053\u6B63\u5728\u542F\u52A8\uFF0C\u51C6\u5907\u597D\u540E\u5C06\u663E\u793A\u4E8C\u7EF4\u7801\u2026","Push notifications enabled":"\u63A8\u9001\u901A\u77E5\u5DF2\u542F\u7528","Push notifications disabled":"\u63A8\u9001\u901A\u77E5\u5DF2\u7981\u7528","Permission Required":"\u9700\u8981\u6388\u6743","Waiting for Input":"\u7B49\u5F85\u8F93\u5165","Question Asked":"Claude \u6B63\u5728\u63D0\u95EE","Response Complete":"\u56DE\u590D\u5B8C\u6210","Task Completed":"\u4EFB\u52A1\u5DF2\u5B8C\u6210","Teammate Idle":"\u961F\u53CB\u7A7A\u95F2","Session Error":"\u4F1A\u8BDD\u9519\u8BEF","Respawn Blocked":"\u91CD\u751F\u5DF2\u963B\u6B62","Task Complete":"\u4EFB\u52A1\u5B8C\u6210","Copied to clipboard":"\u5DF2\u590D\u5236\u5230\u526A\u8D34\u677F","Failed to copy":"\u590D\u5236\u5931\u8D25","Checking\u2026":"\u6B63\u5728\u68C0\u67E5\u2026","Starting\u2026":"\u6B63\u5728\u542F\u52A8\u2026","Starting update\u2026":"\u6B63\u5728\u5F00\u59CB\u66F4\u65B0\u2026","Queued\u2026":"\u5DF2\u6392\u961F\u2026","Preparing\u2026":"\u6B63\u5728\u51C6\u5907\u2026","Stashing local changes\u2026":"\u6B63\u5728\u6682\u5B58\u672C\u5730\u66F4\u6539\u2026","Fetching release\u2026":"\u6B63\u5728\u83B7\u53D6\u53D1\u884C\u7248\u2026","Checking out release\u2026":"\u6B63\u5728\u68C0\u51FA\u53D1\u884C\u7248\u2026","Installing dependencies\u2026":"\u6B63\u5728\u5B89\u88C5\u4F9D\u8D56\u2026","Building\u2026":"\u6B63\u5728\u6784\u5EFA\u2026","Restarting Codeman\u2026":"\u6B63\u5728\u91CD\u542F {name}\u2026","Try again":"\u91CD\u8BD5","Could not check for updates. Try again later.":"\u65E0\u6CD5\u68C0\u67E5\u66F4\u65B0\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002","The previous version is still running.":"\u5148\u524D\u7248\u672C\u4ECD\u5728\u8FD0\u884C\u3002","Advanced Options":"\u9AD8\u7EA7\u9009\u9879","Advanced container settings":"\u9AD8\u7EA7\u5BB9\u5668\u8BBE\u7F6E",Basics:"\u57FA\u672C\u8BBE\u7F6E",Behavior:"\u884C\u4E3A",Alerts:"\u63D0\u9192",Limits:"\u9650\u5236",Paths:"\u8DEF\u5F84",Notes:"\u5907\u6CE8",Context:"\u4E0A\u4E0B\u6587",Duration:"\u6301\u7EED\u65F6\u95F4",Iterations:"\u8FED\u4EE3\u6B21\u6570",Elapsed:"\u5DF2\u7528\u65F6\u95F4",Launch:"\u542F\u52A8","Launch Command":"\u542F\u52A8\u547D\u4EE4","Background Agents":"\u540E\u53F0\u667A\u80FD\u4F53","Background Tasks":"\u540E\u53F0\u4EFB\u52A1",Tasks:"\u4EFB\u52A1","Explore Tasks":"\u63A2\u7D22\u4EFB\u52A1","Implement Tasks":"\u5B9E\u73B0\u4EFB\u52A1","Test Tasks":"\u6D4B\u8BD5\u4EFB\u52A1","Review Tasks":"\u5BA1\u67E5\u4EFB\u52A1","Agent Type":"\u667A\u80FD\u4F53\u7C7B\u578B","Implementation Plan":"\u5B9E\u65BD\u8BA1\u5212",Plan:"\u8BA1\u5212","Plan:":"\u8BA1\u5212\uFF1A","Plan Usage Limits":"\u5957\u9910\u4F7F\u7528\u9650\u5236","Plan Wizard Agents":"\u8BA1\u5212\u5411\u5BFC\u667A\u80FD\u4F53","Fix Plan Menu":"\u4FEE\u590D\u8BA1\u5212\u83DC\u5355","View Fix Plan":"\u67E5\u770B\u4FEE\u590D\u8BA1\u5212","Regenerate Plan":"\u91CD\u65B0\u751F\u6210\u8BA1\u5212","Cancel plan generation":"\u53D6\u6D88\u751F\u6210\u8BA1\u5212","Describe your task below. Claude will generate an implementation plan with testing steps.":"\u8BF7\u5728\u4E0B\u65B9\u63CF\u8FF0\u4EFB\u52A1\uFF0CClaude \u5C06\u751F\u6210\u5305\u542B\u6D4B\u8BD5\u6B65\u9AA4\u7684\u5B9E\u65BD\u8BA1\u5212\u3002","What do you want to build?":"\u4F60\u60F3\u6784\u5EFA\u4EC0\u4E48\uFF1F","A brief description...":"\u7B80\u8981\u63CF\u8FF0\u2026",Describe:"\u63CF\u8FF0",Enhanced:"\u589E\u5F3A","Enhanced: parallel subagents + verification (slower but more thorough)":"\u589E\u5F3A\uFF1A\u5E76\u884C\u5B50\u667A\u80FD\u4F53 + \u9A8C\u8BC1\uFF08\u901F\u5EA6\u8F83\u6162\uFF0C\u4F46\u66F4\u5168\u9762\uFF09",Standard:"\u6807\u51C6","Single-pass generation with Opus 4.5":"\u4F7F\u7528 Opus 4.5 \u5355\u8F6E\u751F\u6210","Initializing deep reasoning model":"\u6B63\u5728\u521D\u59CB\u5316\u6DF1\u5EA6\u63A8\u7406\u6A21\u578B","Starting Opus 4.5...":"\u6B63\u5728\u542F\u52A8 Opus 4.5\u2026","Auto-launch when plan completes":"\u8BA1\u5212\u5B8C\u6210\u540E\u81EA\u52A8\u542F\u52A8","Auto-accept prompts":"\u81EA\u52A8\u63A5\u53D7\u63D0\u793A","Presses Enter for plan approvals and default question options":"\u5BF9\u8BA1\u5212\u5BA1\u6279\u548C\u9ED8\u8BA4\u95EE\u9898\u9009\u9879\u81EA\u52A8\u6309 Enter","Auto-accepts, auto-clears, agent completions":"\u81EA\u52A8\u63A5\u53D7\u3001\u81EA\u52A8\u6E05\u7406\u548C\u667A\u80FD\u4F53\u5B8C\u6210\u63D0\u9192","Or click Run to start":"\u6216\u70B9\u51FB\u201C\u8FD0\u884C\u201D\u5F00\u59CB","to edit your task, or":"\u4EE5\u7F16\u8F91\u4EFB\u52A1\uFF0C\u6216","to continue without a plan":"\u4EE5\u4E0D\u4F7F\u7528\u8BA1\u5212\u76F4\u63A5\u7EE7\u7EED",Respawn:"\u91CD\u751F","Respawn loop":"\u91CD\u751F\u5FAA\u73AF","Enable Respawn":"\u542F\u7528\u91CD\u751F","Stop Respawn":"\u505C\u6B62\u91CD\u751F","Auto-resume when usage limit resets":"\u4F7F\u7528\u9650\u5236\u91CD\u7F6E\u540E\u81EA\u52A8\u7EE7\u7EED","Auto-restart sessions when context fills up (usually not needed)":"\u4E0A\u4E0B\u6587\u5DF2\u6EE1\u65F6\u81EA\u52A8\u91CD\u542F\u4F1A\u8BDD\uFF08\u901A\u5E38\u4E0D\u9700\u8981\uFF09","Auto-Compact":"\u81EA\u52A8\u538B\u7F29","Auto-Clear":"\u81EA\u52A8\u6E05\u7A7A","Token Management":"Token \u7BA1\u7406","Use 1M token context window":"\u4F7F\u7528 100 \u4E07 Token \u4E0A\u4E0B\u6587\u7A97\u53E3","Use 1M token context window for new sessions":"\u65B0\u4F1A\u8BDD\u4F7F\u7528 100 \u4E07 Token \u4E0A\u4E0B\u6587\u7A97\u53E3","Full context reset at threshold (use higher than compact)":"\u8FBE\u5230\u9608\u503C\u65F6\u5B8C\u5168\u91CD\u7F6E\u4E0A\u4E0B\u6587\uFF08\u9608\u503C\u5E94\u9AD8\u4E8E\u538B\u7F29\u9608\u503C\uFF09","Idle Threshold":"\u7A7A\u95F2\u9608\u503C","Max Iterations":"\u6700\u5927\u8FED\u4EE3\u6B21\u6570","Max Iterations:":"\u6700\u5927\u8FED\u4EE3\u6B21\u6570\uFF1A","Max Todos":"\u6700\u5927\u5F85\u529E\u6570","Todo Expiration":"\u5F85\u529E\u8FC7\u671F\u65F6\u95F4","Completion Phrase":"\u5B8C\u6210\u77ED\u8BED","Completion Phrase:":"\u5B8C\u6210\u77ED\u8BED\uFF1A","Phrase Claude outputs when loop is complete (without <promise> tags)":"\u5FAA\u73AF\u5B8C\u6210\u65F6 Claude \u8F93\u51FA\u7684\u77ED\u8BED\uFF08\u4E0D\u542B <promise> \u6807\u7B7E\uFF09","Prompt to send when idle":"\u7A7A\u95F2\u65F6\u53D1\u9001\u7684\u63D0\u793A\u8BCD","Prompt to send into the session":"\u53D1\u9001\u5230\u4F1A\u8BDD\u7684\u63D0\u793A\u8BCD","Prompt Source":"\u63D0\u793A\u8BCD\u6765\u6E90","Prompt File Path":"\u63D0\u793A\u8BCD\u6587\u4EF6\u8DEF\u5F84","Prompt file path":"\u63D0\u793A\u8BCD\u6587\u4EF6\u8DEF\u5F84","Prompt Preview":"\u63D0\u793A\u8BCD\u9884\u89C8","Load Preset":"\u52A0\u8F7D\u9884\u8BBE",Presets:"\u9884\u8BBE","Apply preset":"\u5E94\u7528\u9884\u8BBE","Save Preset":"\u4FDD\u5B58\u9884\u8BBE","Save Respawn Preset":"\u4FDD\u5B58\u91CD\u751F\u9884\u8BBE","Save current config as preset":"\u5C06\u5F53\u524D\u914D\u7F6E\u4FDD\u5B58\u4E3A\u9884\u8BBE","Preset Name":"\u9884\u8BBE\u540D\u79F0","Description (optional)":"\u63CF\u8FF0\uFF08\u53EF\u9009\uFF09","When to use this preset":"\u6B64\u9884\u8BBE\u7684\u9002\u7528\u573A\u666F","Start Loop":"\u542F\u52A8\u5FAA\u73AF","Start Ralph Loop":"\u542F\u52A8 Ralph \u5FAA\u73AF","Start Ralph Loop \u2192":"\u542F\u52A8 Ralph \u5FAA\u73AF \u2192","Enable Tracker":"\u542F\u7528\u8DDF\u8E2A\u5668","Ralph / Todo":"Ralph / \u5F85\u529E","Ralph / Todo Tracker":"Ralph / \u5F85\u529E\u8DDF\u8E2A\u5668","Cycle Steps":"\u5FAA\u73AF\u6B65\u9AA4","1. Update Prompt":"1. \u66F4\u65B0\u63D0\u793A\u8BCD","2. Send /clear":"2. \u53D1\u9001 /clear","3. Send /init":"3. \u53D1\u9001 /init","4. Kickstart Prompt":"4. \u542F\u52A8\u63D0\u793A\u8BCD","Sent only when /init completes but Claude stays idle \xB7 Auto-accept presses Enter for plan approvals and default options":"\u4EC5\u5728 /init \u5B8C\u6210\u540E Claude \u4ECD\u7A7A\u95F2\u65F6\u53D1\u9001\uFF1B\u81EA\u52A8\u63A5\u53D7\u4F1A\u5BF9\u8BA1\u5212\u5BA1\u6279\u548C\u9ED8\u8BA4\u9009\u9879\u6309 Enter","One autonomous work cycle: whenever Claude goes idle, Codeman sends the update prompt, optionally runs /clear + /init, and kickstarts the next round \u2014 repeating for the chosen duration. All settings below belong to this loop; configure them, then press Enable.":"\u4E00\u4E2A\u81EA\u4E3B\u5DE5\u4F5C\u5FAA\u73AF\uFF1AClaude \u6BCF\u6B21\u7A7A\u95F2\u65F6\uFF0C{name}\u90FD\u4F1A\u53D1\u9001\u66F4\u65B0\u63D0\u793A\u8BCD\uFF0C\u53EF\u9009\u6267\u884C /clear + /init\uFF0C\u5E76\u542F\u52A8\u4E0B\u4E00\u8F6E\uFF0C\u6301\u7EED\u5230\u8BBE\u5B9A\u65F6\u957F\u3002\u4E0B\u65B9\u8BBE\u7F6E\u5747\u5C5E\u4E8E\u6B64\u5FAA\u73AF\uFF1B\u914D\u7F6E\u540E\u70B9\u51FB\u201C\u542F\u7528\u201D\u3002",'If Claude pauses on a usage limit ("limit reached \xB7 resets 3pm"), Codeman waits for the reset time and automatically continues the work. Independent of the respawn loop below.':"\u5982\u679C Claude \u56E0\u4F7F\u7528\u9650\u5236\u6682\u505C\uFF08\u201Climit reached \xB7 resets 3pm\u201D\uFF09\uFF0C{name}\u4F1A\u7B49\u5F85\u9650\u5236\u91CD\u7F6E\u5E76\u81EA\u52A8\u7EE7\u7EED\u5DE5\u4F5C\u3002\u6B64\u529F\u80FD\u72EC\u7ACB\u4E8E\u4E0B\u65B9\u7684\u91CD\u751F\u5FAA\u73AF\u3002","Search sessions, events, files\u2026":"\u641C\u7D22\u4F1A\u8BDD\u3001\u4E8B\u4EF6\u548C\u6587\u4EF6\u2026","Search across sessions":"\u8DE8\u4F1A\u8BDD\u641C\u7D22","Filter by case":"\u6309\u6848\u4F8B\u7B5B\u9009","Filter by date range":"\u6309\u65E5\u671F\u8303\u56F4\u7B5B\u9009","Filter by session status":"\u6309\u4F1A\u8BDD\u72B6\u6001\u7B5B\u9009","Filter files...":"\u7B5B\u9009\u6587\u4EF6\u2026","Any status":"\u4EFB\u610F\u72B6\u6001","Any time":"\u4EFB\u610F\u65F6\u95F4","Last hour":"\u6700\u8FD1\u4E00\u5C0F\u65F6","Last 7 Days":"\u6700\u8FD1 7 \u5929","Past 24h":"\u8FC7\u53BB 24 \u5C0F\u65F6","Past 7 days":"\u8FC7\u53BB 7 \u5929","Past 30 days":"\u8FC7\u53BB 30 \u5929","Since last visit":"\u81EA\u4E0A\u6B21\u8BBF\u95EE\u4EE5\u6765",Since:"\u5F00\u59CB\u65F6\u95F4",Until:"\u7ED3\u675F\u65F6\u95F4","Away digest range":"\u79BB\u5F00\u671F\u95F4\u6458\u8981\u8303\u56F4","Open the digest to load recent activity":"\u6253\u5F00\u6458\u8981\u4EE5\u52A0\u8F7D\u6700\u8FD1\u6D3B\u52A8","Refresh away digest":"\u5237\u65B0\u79BB\u5F00\u671F\u95F4\u6458\u8981","Refresh summary":"\u5237\u65B0\u6458\u8981","Select a session to view files":"\u9009\u62E9\u4F1A\u8BDD\u4EE5\u67E5\u770B\u6587\u4EF6","Select a session to view summary":"\u9009\u62E9\u4F1A\u8BDD\u4EE5\u67E5\u770B\u6458\u8981","Select an agent to view details":"\u9009\u62E9\u667A\u80FD\u4F53\u4EE5\u67E5\u770B\u8BE6\u60C5","Select a run to view its agents":"\u9009\u62E9\u4E00\u6B21\u8FD0\u884C\u4EE5\u67E5\u770B\u5176\u667A\u80FD\u4F53","Source type filter":"\u6765\u6E90\u7C7B\u578B\u7B5B\u9009","Copy content":"\u590D\u5236\u5185\u5BB9","Edit file":"\u7F16\u8F91\u6587\u4EF6","Unsaved changes":"\u672A\u4FDD\u5B58\u7684\u66F4\u6539",Saved:"\u5DF2\u4FDD\u5B58","Export as JSON":"\u5BFC\u51FA\u4E3A JSON","Export as Markdown":"\u5BFC\u51FA\u4E3A Markdown","Mark all read":"\u5168\u90E8\u6807\u4E3A\u5DF2\u8BFB","Clear search":"\u6E05\u9664\u641C\u7D22","Clear all tracked subagents":"\u6E05\u9664\u6240\u6709\u5DF2\u8DDF\u8E2A\u7684\u5B50\u667A\u80FD\u4F53","Kill All Sessions":"\u7EC8\u6B62\u6240\u6709\u4F1A\u8BDD","Kill all sessions and their tmux processes":"\u7EC8\u6B62\u6240\u6709\u4F1A\u8BDD\u53CA\u5176 tmux \u8FDB\u7A0B","Kill All Claude + Tmux":"\u7EC8\u6B62\u5168\u90E8 Claude + Tmux","Kill Tmux & Claude Code":"\u7EC8\u6B62 Tmux \u4E0E Claude Code","Terminate everything completely":"\u5F7B\u5E95\u7EC8\u6B62\u6240\u6709\u5185\u5BB9","Tmux Sessions":"Tmux \u4F1A\u8BDD","Tmux sessions keep running in background":"Tmux \u4F1A\u8BDD\u7EE7\u7EED\u5728\u540E\u53F0\u8FD0\u884C","Refresh tmux sessions":"\u5237\u65B0 Tmux \u4F1A\u8BDD","Restore Terminal Size":"\u6062\u590D\u7EC8\u7AEF\u5927\u5C0F","Clear Terminal":"\u6E05\u7A7A\u7EC8\u7AEF","Stop current run":"\u505C\u6B62\u5F53\u524D\u8FD0\u884C","Stop respawn":"\u505C\u6B62\u91CD\u751F","Stop (Ctrl+C)":"\u505C\u6B62\uFF08Ctrl+C\uFF09",Case:"\u6848\u4F8B","Case:":"\u6848\u4F8B\uFF1A","Case settings":"\u6848\u4F8B\u8BBE\u7F6E","Create New":"\u65B0\u5EFA","Auto (directory name)":"\u81EA\u52A8\uFF08\u76EE\u5F55\u540D\uFF09","Custom name shown in the tab (right-click tab to rename inline)":"\u6807\u7B7E\u9875\u4E2D\u663E\u793A\u7684\u81EA\u5B9A\u4E49\u540D\u79F0\uFF08\u53F3\u952E\u6807\u7B7E\u53EF\u76F4\u63A5\u91CD\u547D\u540D\uFF09","Name to identify this case in Codeman":"\u7528\u4E8E\u5728{name}\u4E2D\u6807\u8BC6\u6B64\u6848\u4F8B\u7684\u540D\u79F0","Name to identify this remote case in Codeman":"\u7528\u4E8E\u5728{name}\u4E2D\u6807\u8BC6\u6B64\u8FDC\u7A0B\u6848\u4F8B\u7684\u540D\u79F0","Absolute path on the remote host. Codeman will not create or delete it.":"\u8FDC\u7A0B\u4E3B\u673A\u4E0A\u7684\u7EDD\u5BF9\u8DEF\u5F84\uFF1B{name}\u4E0D\u4F1A\u521B\u5EFA\u6216\u5220\u9664\u8BE5\u76EE\u5F55\u3002","Absolute path to an existing project folder, e.g. /home/you/my-project":"\u73B0\u6709\u9879\u76EE\u6587\u4EF6\u5939\u7684\u7EDD\u5BF9\u8DEF\u5F84\uFF0C\u4F8B\u5982 /home/you/my-project","Letters, numbers, hyphens, underscores only. Created in ~/codeman-cases/":"\u4EC5\u5141\u8BB8\u5B57\u6BCD\u3001\u6570\u5B57\u3001\u8FDE\u5B57\u7B26\u548C\u4E0B\u5212\u7EBF\uFF1B\u5C06\u5728 ~/codeman-cases/ \u4E2D\u521B\u5EFA\u3002","Docker exports":"Docker \u5BFC\u51FA","No exports yet. Export a docker case from its tab.":"\u6682\u65E0\u5BFC\u51FA\uFF1B\u8BF7\u4ECE Docker \u6848\u4F8B\u6807\u7B7E\u9875\u5BFC\u51FA\u3002","Runs inside an isolated container. Multiple sessions can share the same container.":"\u5728\u9694\u79BB\u5BB9\u5668\u5185\u8FD0\u884C\uFF1B\u591A\u4E2A\u4F1A\u8BDD\u53EF\u4EE5\u5171\u4EAB\u540C\u4E00\u5BB9\u5668\u3002","Runs this case in a hardened, isolated container. The base image is built automatically on first use. Docker/Podman must be installed.":"\u5728\u52A0\u56FA\u7684\u9694\u79BB\u5BB9\u5668\u4E2D\u8FD0\u884C\u6B64\u6848\u4F8B\u3002\u9996\u6B21\u4F7F\u7528\u65F6\u4F1A\u81EA\u52A8\u6784\u5EFA\u57FA\u7840\u955C\u50CF\uFF1B\u5FC5\u987B\u5B89\u88C5 Docker/Podman\u3002","Run in an isolated Docker container":"\u5728\u9694\u79BB\u7684 Docker \u5BB9\u5668\u4E2D\u8FD0\u884C","Absolute HOST directory, bind-mounted into the container. Codeman scaffolds CLAUDE.md + hooks into it.":"\u7ED1\u5B9A\u6302\u8F7D\u5230\u5BB9\u5668\u4E2D\u7684\u4E3B\u673A\u7EDD\u5BF9\u76EE\u5F55\uFF1B{name}\u4F1A\u5728\u5176\u4E2D\u751F\u6210 CLAUDE.md \u548C hooks\u3002","A reusable docker host profile. Reuse the same ID across cases to share settings.":"\u53EF\u590D\u7528\u7684 Docker \u4E3B\u673A\u914D\u7F6E\uFF1B\u591A\u4E2A\u6848\u4F8B\u4F7F\u7528\u540C\u4E00 ID \u53EF\u5171\u4EAB\u8BBE\u7F6E\u3002","Mount host credentials (~/.claude etc.)":"\u6302\u8F7D\u4E3B\u673A\u51ED\u636E\uFF08~/.claude \u7B49\uFF09","On: your existing login just works (creds stay on the host, never in exports). Off: sealed sandbox, log in inside the container.":"\u5F00\u542F\uFF1A\u76F4\u63A5\u4F7F\u7528\u73B0\u6709\u767B\u5F55\uFF08\u51ED\u636E\u4FDD\u7559\u5728\u4E3B\u673A\u4E14\u4E0D\u4F1A\u8FDB\u5165\u5BFC\u51FA\uFF09\uFF1B\u5173\u95ED\uFF1A\u4F7F\u7528\u5BC6\u5C01\u6C99\u7BB1\uFF0C\u9700\u8981\u5728\u5BB9\u5668\u5185\u767B\u5F55\u3002","Disk is elastic: storage grows automatically as data flows in (no fixed cap).":"\u78C1\u76D8\u4E3A\u5F39\u6027\u5BB9\u91CF\uFF1A\u4F1A\u968F\u6570\u636E\u81EA\u52A8\u589E\u957F\uFF08\u65E0\u56FA\u5B9A\u4E0A\u9650\uFF09\u3002","Needs the NVIDIA container toolkit on the host.":"\u4E3B\u673A\u9700\u8981\u5B89\u88C5 NVIDIA Container Toolkit\u3002","GPU \u2014 8 GB RAM, 4 CPU, all GPUs":"GPU \u2014 8 GB \u5185\u5B58\u30014 CPU\u3001\u5168\u90E8 GPU","Large \u2014 8 GB RAM, 4 CPU":"\u5927\u578B \u2014 8 GB \u5185\u5B58\u30014 CPU","Medium \u2014 4 GB RAM, 2 CPU (default)":"\u4E2D\u578B \u2014 4 GB \u5185\u5B58\u30012 CPU\uFF08\u9ED8\u8BA4\uFF09","Small \u2014 2 GB RAM, 1 CPU":"\u5C0F\u578B \u2014 2 GB \u5185\u5B58\u30011 CPU","bridge (internet on, default)":"\u6865\u63A5\uFF08\u53EF\u8054\u7F51\uFF0C\u9ED8\u8BA4\uFF09","bridge (internet on)":"\u6865\u63A5\uFF08\u53EF\u8054\u7F51\uFF09","none (fully isolated, no network)":"\u65E0\uFF08\u5B8C\u5168\u9694\u79BB\uFF0C\u4E0D\u8054\u7F51\uFF09","none (fully isolated)":"\u65E0\uFF08\u5B8C\u5168\u9694\u79BB\uFF09","Resume last conversation on relaunch":"\u91CD\u65B0\u542F\u52A8\u65F6\u7EE7\u7EED\u6700\u8FD1\u4E00\u6B21\u5BF9\u8BDD","Extra -o Options":"\u9644\u52A0 -o \u9009\u9879","SOCKS Proxy":"SOCKS \u4EE3\u7406","Host ID":"\u4E3B\u673A ID","Optional. Leave blank for the default port 22.":"\u53EF\u9009\uFF1B\u7559\u7A7A\u4F7F\u7528\u9ED8\u8BA4\u7AEF\u53E3 22\u3002","Optional. Path to a private key on this machine (passed to ssh -i). Never the key contents.":"\u53EF\u9009\uFF1B\u672C\u673A\u79C1\u94A5\u6587\u4EF6\u8DEF\u5F84\uFF08\u4F20\u7ED9 ssh -i\uFF09\uFF0C\u8BF7\u52FF\u586B\u5199\u5BC6\u94A5\u5185\u5BB9\u3002","Optional. [user@]host[:port] for ssh -J (jump/bastion host).":"\u53EF\u9009\uFF1Bssh -J \u4F7F\u7528\u7684 [user@]host[:port]\uFF08\u8DF3\u677F\u673A\uFF09\u3002","Optional. One KEY=VALUE per line; each becomes an ssh -o option.":"\u53EF\u9009\uFF1B\u6BCF\u884C\u4E00\u4E2A KEY=VALUE\uFF0C\u6BCF\u9879\u90FD\u4F1A\u6210\u4E3A ssh -o \u9009\u9879\u3002","Use the GPU-accelerated WebGL terminal renderer (desktop only). Turn off to force the DOM renderer if you hit GPU glitches. Codeman also auto-falls-back to the DOM renderer after repeated GPU stalls.":"\u4F7F\u7528 GPU \u52A0\u901F\u7684 WebGL \u7EC8\u7AEF\u6E32\u67D3\u5668\uFF08\u4EC5\u684C\u9762\u7AEF\uFF09\u3002\u5982\u9047 GPU \u663E\u793A\u95EE\u9898\uFF0C\u53EF\u5173\u95ED\u4EE5\u5F3A\u5236\u4F7F\u7528 DOM \u6E32\u67D3\u5668\uFF1B\u591A\u6B21 GPU \u5361\u987F\u540E{name}\u4E5F\u4F1A\u81EA\u52A8\u56DE\u9000\u3002","Show A-/A+ font size buttons in header":"\u5728\u9876\u90E8\u680F\u663E\u793A A-/A+ \u5B57\u4F53\u5927\u5C0F\u6309\u94AE","Show Claude plan usage limits (5-hour & weekly) in the header. Applies to newly created sessions.":"\u5728\u9876\u90E8\u680F\u663E\u793A Claude \u5957\u9910\u4F7F\u7528\u9650\u5236\uFF085 \u5C0F\u65F6\u548C\u6BCF\u5468\uFF09\uFF1B\u9002\u7528\u4E8E\u65B0\u5EFA\u4F1A\u8BDD\u3002","Show ultracode / Workflow runs as a master-detail tab (tasks on the left, agents with tokens + tool calls on the right)":"\u4EE5\u4E3B\u4ECE\u6807\u7B7E\u9875\u663E\u793A Ultracode / Workflow \u8FD0\u884C\uFF08\u5DE6\u4FA7\u4EFB\u52A1\uFF0C\u53F3\u4FA7\u667A\u80FD\u4F53 Token \u4E0E\u5DE5\u5177\u8C03\u7528\uFF09","Pop a floating window for each active ultracode / Workflow run, connected by a line to its session tab (additional to the Ultracode Agents panel)":"\u4E3A\u6BCF\u4E2A\u6D3B\u52A8\u7684 Ultracode / Workflow \u8FD0\u884C\u5F39\u51FA\u6D6E\u52A8\u7A97\u53E3\uFF0C\u5E76\u7528\u8FDE\u7EBF\u8FDE\u63A5\u5230\u5176\u4F1A\u8BDD\u6807\u7B7E\u9875","Shows typed characters instantly via overlay while forwarding keystrokes to the server in the background. Enables Tab completion, preserves input across tab switches, and protects against session crashes. Recommended for mobile and high-latency connections.":"\u901A\u8FC7\u8986\u76D6\u5C42\u5373\u65F6\u663E\u793A\u8F93\u5165\uFF0C\u540C\u65F6\u5728\u540E\u53F0\u628A\u6309\u952E\u8F6C\u53D1\u5230\u670D\u52A1\u5668\u3002\u652F\u6301 Tab \u8865\u5168\u3001\u5207\u6362\u6807\u7B7E\u65F6\u4FDD\u7559\u8F93\u5165\u5E76\u9632\u6B62\u4F1A\u8BDD\u5D29\u6E83\u4E22\u5B57\uFF1B\u63A8\u8350\u79FB\u52A8\u7AEF\u548C\u9AD8\u5EF6\u8FDF\u8FDE\u63A5\u4F7F\u7528\u3002","Show a dedicated input field below the terminal for CJK (Chinese/Japanese/Korean) IME composition. Recommended for mobile devices with Chinese input methods where xterm's native input handling may drop characters.":"\u5728\u7EC8\u7AEF\u4E0B\u65B9\u663E\u793A\u4E2D\u65E5\u97E9\u8F93\u5165\u6CD5\u4E13\u7528\u6587\u672C\u6846\u3002\u63A8\u8350\u5728\u53EF\u80FD\u56E0 xterm \u539F\u751F\u8F93\u5165\u800C\u4E22\u5B57\u7684\u79FB\u52A8\u7AEF\u4E2D\u6587\u8F93\u5165\u6CD5\u4E2D\u4F7F\u7528\u3002","Show additional buttons (Tab, Shift+Tab, Ctrl+O, Esc, Alt+Enter, left/right arrows) in the mobile keyboard accessory bar.":"\u5728\u79FB\u52A8\u7AEF\u952E\u76D8\u5DE5\u5177\u680F\u663E\u793A\u9644\u52A0\u6309\u952E\uFF08Tab\u3001Shift+Tab\u3001Ctrl+O\u3001Esc\u3001Alt+Enter\u3001\u5DE6\u53F3\u65B9\u5411\u952E\uFF09\u3002","Scroll local history (when mouse passthrough is active)":"\u6EDA\u52A8\u672C\u5730\u5386\u53F2\uFF08\u9F20\u6807\u76F4\u901A\u542F\u7528\u65F6\uFF09","Plain wheel/trackpad pages the terminal scrollback":"\u4F7F\u7528\u666E\u901A\u6EDA\u8F6E/\u89E6\u63A7\u677F\u7FFB\u9605\u7EC8\u7AEF\u5386\u53F2","Camera hand-tracking overlay (applied on reload)":"\u6444\u50CF\u5934\u624B\u52BF\u8DDF\u8E2A\u8986\u76D6\u5C42\uFF08\u91CD\u65B0\u52A0\u8F7D\u540E\u751F\u6548\uFF09","Enable the camera hand-tracking gesture overlay (applied on reload). The instance must run with CODEMAN_GESTURE=1.":"\u542F\u7528\u6444\u50CF\u5934\u624B\u52BF\u8DDF\u8E2A\u8986\u76D6\u5C42\uFF08\u91CD\u65B0\u52A0\u8F7D\u540E\u751F\u6548\uFF09\uFF1B\u5B9E\u4F8B\u5FC5\u987B\u4EE5 CODEMAN_GESTURE=1 \u8FD0\u884C\u3002","How Claude CLI is started in screen sessions. Auto Mode runs without routine prompts behind a background safety classifier (needs Claude Code 2.1.207+ and Opus 4.6+/Sonnet 4.6+/Fable 5)":"\u8BBE\u7F6E Claude CLI \u5728\u4F1A\u8BDD\u4E2D\u7684\u542F\u52A8\u65B9\u5F0F\u3002\u81EA\u52A8\u6A21\u5F0F\u7531\u540E\u53F0\u5B89\u5168\u5206\u7C7B\u5668\u4FDD\u62A4\uFF0C\u65E0\u9700\u5E38\u89C4\u786E\u8BA4\uFF08\u9700\u8981 Claude Code 2.1.207+ \u548C Opus 4.6+/Sonnet 4.6+/Fable 5\uFF09\u3002","Auto-enable for new sessions (otherwise auto-enables on Ralph pattern detection)":"\u4E3A\u65B0\u4F1A\u8BDD\u81EA\u52A8\u542F\u7528\uFF08\u5426\u5219\u68C0\u6D4B\u5230 Ralph \u6A21\u5F0F\u65F6\u81EA\u52A8\u542F\u7528\uFF09","Enable experimental Agent Teams for all new Claude sessions (disabled by default)":"\u4E3A\u6240\u6709\u65B0 Claude \u4F1A\u8BDD\u542F\u7528\u5B9E\u9A8C\u6027\u667A\u80FD\u4F53\u56E2\u961F\uFF08\u9ED8\u8BA4\u5173\u95ED\uFF09","Automatically re-establish remote (SSH) sessions when the connection drops, reattaching to the durable remote tmux session (on by default; bounded backoff)":"\u8FDE\u63A5\u65AD\u5F00\u65F6\u81EA\u52A8\u91CD\u5EFA\u8FDC\u7A0B SSH \u4F1A\u8BDD\uFF0C\u5E76\u91CD\u65B0\u9644\u52A0\u5230\u6301\u4E45\u5316\u8FDC\u7A0B tmux \u4F1A\u8BDD\uFF08\u9ED8\u8BA4\u5F00\u542F\uFF0C\u6709\u9650\u9000\u907F\uFF09","Default effort for new Claude sessions \u2014 soft default, switchable anytime in-session via /effort (e.g. /effort ultracode)":"\u65B0 Claude \u4F1A\u8BDD\u7684\u9ED8\u8BA4\u601D\u8003\u5F3A\u5EA6\uFF1B\u8FD9\u662F\u8F6F\u9ED8\u8BA4\u503C\uFF0C\u53EF\u968F\u65F6\u5728\u4F1A\u8BDD\u4E2D\u901A\u8FC7 /effort \u5207\u6362\u3002","Lower priority of Claude sessions (reduces system impact, only affects new sessions)":"\u964D\u4F4E Claude \u4F1A\u8BDD\u7684\u8FDB\u7A0B\u4F18\u5148\u7EA7\uFF08\u51CF\u5C11\u7CFB\u7EDF\u5F71\u54CD\uFF0C\u4EC5\u5F71\u54CD\u65B0\u4F1A\u8BDD\uFF09","Process priority (-20 to 19, higher = lower priority, default: 10)":"\u8FDB\u7A0B\u4F18\u5148\u7EA7\uFF08-20 \u5230 19\uFF1B\u6570\u503C\u8D8A\u5927\u4F18\u5148\u7EA7\u8D8A\u4F4E\uFF1B\u9ED8\u8BA4 10\uFF09","Start new Codex sessions with --dangerously-bypass-approvals-and-sandbox":"\u4F7F\u7528 --dangerously-bypass-approvals-and-sandbox \u542F\u52A8\u65B0\u7684 Codex \u4F1A\u8BDD","Model used for execution tasks. Optimizer suggestions are advisory only.":"\u6267\u884C\u4EFB\u52A1\u4F7F\u7528\u7684\u6A21\u578B\uFF1B\u4F18\u5316\u5668\u5EFA\u8BAE\u4EC5\u4F9B\u53C2\u8003\u3002","Show what the optimizer recommends (doesn't override your choice)":"\u663E\u793A\u4F18\u5316\u5668\u5EFA\u8BAE\uFF08\u4E0D\u4F1A\u8986\u76D6\u4F60\u7684\u9009\u62E9\uFF09",'Optionally set specific models for each task type. Leave as "Use Default" to use your default model.':"\u53EF\u4E3A\u6BCF\u79CD\u4EFB\u52A1\u7C7B\u578B\u6307\u5B9A\u6A21\u578B\uFF1B\u4FDD\u7559\u201C\u4F7F\u7528\u9ED8\u8BA4\u503C\u201D\u5373\u53EF\u4F7F\u7528\u9ED8\u8BA4\u6A21\u578B\u3002","Request browser notification permission":"\u8BF7\u6C42\u6D4F\u89C8\u5668\u901A\u77E5\u6743\u9650","Show OS-level notifications when tab is hidden":"\u6807\u7B7E\u9875\u9690\u85CF\u65F6\u663E\u793A\u7CFB\u7EDF\u7EA7\u901A\u77E5","OS-level push notifications \u2014 works even when tab is closed":"\u7CFB\u7EDF\u7EA7\u63A8\u9001\u901A\u77E5\uFF0C\u5373\u4F7F\u6807\u7B7E\u9875\u5173\u95ED\u4E5F\u53EF\u63A5\u6536","Play a short beep for critical events":"\u4E25\u91CD\u4E8B\u4EF6\u53D1\u751F\u65F6\u64AD\u653E\u77ED\u63D0\u793A\u97F3","Completions, budget warnings, stuck sessions":"\u5B8C\u6210\u63D0\u9192\u3001\u9884\u7B97\u8B66\u544A\u548C\u4F1A\u8BDD\u5361\u4F4F\u63D0\u9192","Errors, crashes, agent failures":"\u9519\u8BEF\u3001\u5D29\u6E83\u548C\u667A\u80FD\u4F53\u5931\u8D25","Notify when a session is idle longer than this":"\u4F1A\u8BDD\u7A7A\u95F2\u8D85\u8FC7\u6B64\u65F6\u957F\u65F6\u901A\u77E5","Stored locally only, never sent to server. Get a key at":"\u4EC5\u5B58\u50A8\u5728\u672C\u673A\uFF0C\u7EDD\u4E0D\u4F1A\u53D1\u9001\u5230\u670D\u52A1\u5668\u3002\u53EF\u5728\u6B64\u83B7\u53D6\u5BC6\u94A5\uFF1A","Comma-separated terms to boost recognition accuracy":"\u4EE5\u9017\u53F7\u5206\u9694\u53EF\u63D0\u9AD8\u8BC6\u522B\u51C6\u786E\u7387\u7684\u672F\u8BED","Start voice input":"\u5F00\u59CB\u8BED\u97F3\u8F93\u5165","Voice input":"\u8BED\u97F3\u8F93\u5165","Voice input (Ctrl+Shift+V)":"\u8BED\u97F3\u8F93\u5165\uFF08Ctrl+Shift+V\uFF09","Insert Newline":"\u63D2\u5165\u6362\u884C","Close Panels":"\u5173\u95ED\u9762\u677F","Previous / Next Session":"\u4E0A\u4E00\u4E2A / \u4E0B\u4E00\u4E2A\u4F1A\u8BDD","Next Session":"\u4E0B\u4E00\u4E2A\u4F1A\u8BDD","Switch to Tab N":"\u5207\u6362\u5230\u7B2C N \u4E2A\u6807\u7B7E\u9875","Move Active Tab Left":"\u5411\u5DE6\u79FB\u52A8\u5F53\u524D\u6807\u7B7E\u9875","Move Active Tab Right":"\u5411\u53F3\u79FB\u52A8\u5F53\u524D\u6807\u7B7E\u9875","Focus First Tab":"\u805A\u7126\u7B2C\u4E00\u4E2A\u6807\u7B7E\u9875","Focus Last Tab":"\u805A\u7126\u6700\u540E\u4E00\u4E2A\u6807\u7B7E\u9875","Focus Next Tab":"\u805A\u7126\u4E0B\u4E00\u4E2A\u6807\u7B7E\u9875","Focus Previous Tab":"\u805A\u7126\u4E0A\u4E00\u4E2A\u6807\u7B7E\u9875","Activate Focused Tab":"\u6FC0\u6D3B\u805A\u7126\u7684\u6807\u7B7E\u9875","Remove Tab":"\u79FB\u9664\u6807\u7B7E\u9875","Remove All Tabs":"\u79FB\u9664\u6240\u6709\u6807\u7B7E\u9875","Use arrows to reorder. Changes are saved automatically.":"\u4F7F\u7528\u65B9\u5411\u952E\u91CD\u65B0\u6392\u5E8F\uFF1B\u66F4\u6539\u4F1A\u81EA\u52A8\u4FDD\u5B58\u3002"}),C=new Map(Object.entries(m).map(([e,t])=>[e.toLocaleLowerCase("en"),t])),S=new WeakMap,b=new WeakMap;let r=f(a.__codemanLanguage),i=c,h=null,p=!1;function f(e){return O.has(e)?e:"en"}function T(e){if(typeof e!="string")return c;const t=e.normalize("NFC").replace(/[\u0000-\u001f\u007f]/g,"").trim();return t?Array.from(t).slice(0,40).join(""):c}function v(e,t){return e.replace(/\{([a-zA-Z][\w]*)\}/g,(s,o)=>String(t[o]??""))}function L(e){const t=[[/^(\d+) tokens?$/,(o,n)=>`${n} \u4E2A Token`],[/^(\d+) sessions?$/,(o,n)=>`${n} \u4E2A\u4F1A\u8BDD`],[/^(\d+) tasks?$/,(o,n)=>`${n} \u4E2A\u4EFB\u52A1`],[/^(\d+) running$/,(o,n)=>`${n} \u4E2A\u8FD0\u884C\u4E2D`],[/^(\d+) active$/,(o,n)=>`${n} \u4E2A\u6D3B\u52A8`],[/^Show (\d+) more$/,(o,n)=>`\u518D\u663E\u793A ${n} \u9879`],[/^Show (\d+) more \((\d+) remaining\)$/,(o,n,l)=>`\u518D\u663E\u793A ${n} \u9879\uFF08\u5269\u4F59 ${l} \u9879\uFF09`],[/^Lifetime: (\d+) sessions created$/,(o,n)=>`\u7D2F\u8BA1\u5DF2\u521B\u5EFA ${n} \u4E2A\u4F1A\u8BDD`],[/^Tunnel active: (.+)$/,(o,n)=>`\u96A7\u9053\u5DF2\u542F\u7528\uFF1A${n}`],[/^Tunnel error: (.+)$/,(o,n)=>`\u96A7\u9053\u9519\u8BEF\uFF1A${n}`],[/^Update to v(.+)$/,(o,n)=>`\u66F4\u65B0\u5230 v${n}`],[/^You're up to date \(v(.+)\)\.$/,(o,n)=>`\u5DF2\u662F\u6700\u65B0\u7248\u672C\uFF08v${n}\uFF09\u3002`],[/^Update available: v(.+)$/,(o,n)=>`\u6709\u53EF\u7528\u66F4\u65B0\uFF1Av${n}`],[/^Selected: (.+)$/,(o,n)=>`\u5DF2\u9009\u62E9\uFF1A${n}`],[/^Failed to (.+)$/,(o,n)=>`\u64CD\u4F5C\u5931\u8D25\uFF1A${n}`]];for(const[o,n]of t){const l=e.match(o);if(l)return n(...l)}const s=e.match(/^(Open|Close|Show|Hide|Enable|Disable|Start|Stop|Refresh|Save|Cancel|Clear|Select|View|Export|Import|Remove|Kill|Toggle|Increase|Decrease) (.+)$/i);if(s){const o={open:"\u6253\u5F00",close:"\u5173\u95ED",show:"\u663E\u793A",hide:"\u9690\u85CF",enable:"\u542F\u7528",disable:"\u7981\u7528",start:"\u542F\u52A8",stop:"\u505C\u6B62",refresh:"\u5237\u65B0",save:"\u4FDD\u5B58",cancel:"\u53D6\u6D88",clear:"\u6E05\u9664",select:"\u9009\u62E9",view:"\u67E5\u770B",export:"\u5BFC\u51FA",import:"\u5BFC\u5165",remove:"\u79FB\u9664",kill:"\u7EC8\u6B62",toggle:"\u5207\u6362",increase:"\u589E\u5927",decrease:"\u51CF\u5C0F"}[s[1].toLowerCase()],n=m[s[2]]||C.get(s[2].toLocaleLowerCase("en"));if(o&&n)return`${o}${n}`}return null}function g(e){return!e||i===c?e:e.replace(/Codeman/g,i).replace(/codeman(?=:)/g,i)}function d(e,t={}){if(typeof e!="string"||!e)return e;const s={name:i,...t};if(r==="zh-CN"){const o=m[e]||C.get(e.toLocaleLowerCase("en"))||L(e);if(o)return g(v(o,s))}return g(v(e,s))}function k(e){const t=e.nodeType===Node.ELEMENT_NODE?e:e.parentElement;return!t||!!t.closest(x)}function U(e){const t=e.nodeType===Node.ELEMENT_NODE?e:e.parentElement;return k(e)||!!t?.closest(D)}function M(e,t){const s=e.match(/^\s*/)?.[0]||"",o=e.match(/\s*$/)?.[0]||"";return s+t+o}function E(e){let t=S.get(e);if(U(e)||!t&&!/[A-Za-z]/.test(e.nodeValue||""))return;(!t||e.nodeValue!==t.applied)&&(t={source:e.nodeValue,applied:e.nodeValue});const s=t.source.trim();if(!s)return;const o=M(t.source,d(s));t.applied=o,S.set(e,t),e.nodeValue!==o&&(e.nodeValue=o)}function w(e){if(k(e)||e.matches(".history-item[title]"))return;let t=b.get(e);t||(t=new Map);for(const s of y){if(!e.hasAttribute(s))continue;const o=e.getAttribute(s)||"";let n=t.get(s);(!n||o!==n.applied)&&(n={source:o,applied:o});const l=d(n.source);n.applied=l,t.set(s,n),o!==l&&e.setAttribute(s,l)}b.set(e,t)}function u(e){if(!(!e||p)){p=!0;try{if(e.nodeType===Node.TEXT_NODE){E(e);return}if(e.nodeType!==Node.ELEMENT_NODE&&e.nodeType!==Node.DOCUMENT_NODE)return;e.nodeType===Node.ELEMENT_NODE&&w(e);const t=document.createTreeWalker(e,NodeFilter.SHOW_ELEMENT|NodeFilter.SHOW_TEXT);for(let s=t.nextNode();s;s=t.nextNode())s.nodeType===Node.TEXT_NODE?E(s):w(s)}finally{p=!1}}}function A(){const e=document.title||"",t=document.documentElement.dataset.i18nTitleSource||e;document.documentElement.dataset.i18nTitleSource=t,document.title=g(t)}function I(e={}){const t=i;if(r=f(e.language??r),i=T(e.displayName??i),a.__codemanLanguage=r,a.__codemanDisplayName=i,document.documentElement.lang=r,document.documentElement.dataset.language=r,t!==i){const s=document.documentElement.dataset.i18nTitleSource||document.title||"";t!==c&&s.includes(t)&&(document.documentElement.dataset.i18nTitleSource=s.replaceAll(t,i))}return u(document.body),A(),{language:r,displayName:i}}function P(){u(document.body),A(),!h&&(h=new MutationObserver(e=>{if(!p)for(const t of e){t.type==="characterData"&&u(t.target),t.type==="attributes"&&w(t.target);for(const s of t.addedNodes)u(s)}}),h.observe(document.body,{subtree:!0,childList:!0,characterData:!0,attributes:!0,attributeFilter:y}))}const _=Object.freeze({t:d,configure:I,start:P,translateNode:u,normalizeDisplayName:T,normalizeLanguage:f,get language(){return r},get displayName(){return i}});a.CodemanI18n=_,a.codemanT=d;const N=typeof a.confirm=="function"?a.confirm.bind(a):null,R=typeof a.alert=="function"?a.alert.bind(a):null;N&&(a.confirm=e=>N(d(String(e)))),R&&(a.alert=e=>R(d(String(e)))),document.addEventListener("DOMContentLoaded",P,{once:!0})})(window);