mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-09-30 12:39:42 +02:00
docs(wiki): catch the manual up to 1.29.0 and add the three run modes it never had
The wiki was written for seven run modes and never received Grok Build, DeepSeek Harness or OMP. They now appear everywhere the others do: the modes table and per-CLI notes, install commands, environment prefixes, the Quick Start table, the requirements rows, the vocabulary, and every "seven modes" count. The 1.27 to 1.29.0 changes land on the pages that own them: attaching a case to an existing container, multi-case adoption and the copy-a-case picker (Docker Cases); file reads over ssh in remote cases and what stays unavailable (Remote SSH Sessions, Working With Files, Security); single-page app routing, frame recovery, localhost links as tabs and the egress guard (Web Tabs); DeepSeek as the one non-Claude mode with real stop/blocked signals and Approvals items, Codex's own work detection, last-response, the model-endpoint routes and refreshed counts (HTTP API, Driving From An Agent, Hooks, Notifications, Keeping Agents Running, Core Concepts); Shift+drag, right-click copy, Auto Copy, the Ctrl+Z guard, font weight, the vertical rail and its activity sort (Keyboard Shortcuts, Input And Voice, The Dashboard, Settings Reference); the 600px phone cutoff, Codex shift arrows and iPhone Duo (Mobile Guide); the Docker Compose route and its update rule (Installation, Running As A Service); four new symptom entries and a "which CLIs" question (Troubleshooting, FAQ). Custom model endpoints are deliberately left to #430, which adds that page and edits Agent CLIs, Settings Reference and the sidebar; these edits stay out of the regions #430, #428 and #376 touch, and all three still merge cleanly on top. Both READMEs: the web-tab menu entry is labelled "Add URL" in the UI, not "Add dashboard". Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
@@ -443,7 +443,7 @@ PTY Output → 16ms Server Batch → DEC 2026 Wrap → SSE → Client rAF → xt
|
||||
- **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
|
||||
- **Multi-CLI** — run **Claude Code**, **OpenCode**, **Codex**, **Antigravity**, **Gemini**, **Pi**, **Grok**, **DeepSeek Harness**, or **OMP** per session; env-var prefixes auto-gate (`CLAUDE_CODE_*` vs `OPENCODE_*` vs `CODEX_*` vs `ANTIGRAVITY_*` vs `GEMINI_*`/`GOOGLE_*` vs `PI_*` vs `GROK_*`/`XAI_*` vs `DSH_*`/`DEEPSEEK_*` vs `OMP_*`). See [`docs/opencode-integration.md`](docs/opencode-integration.md), [`docs/pi-integration.md`](docs/pi-integration.md), [`docs/grok-integration.md`](docs/grok-integration.md), [`docs/deepseek-integration.md`](docs/deepseek-integration.md) and [`docs/omp-integration.md`](docs/omp-integration.md)
|
||||
- **Custom model endpoints** _(new in 1.29.0, HTTP API for now)_ — point a session's CLI at any OpenAI-compatible endpoint instead of its native backend: a local llama.cpp, llama-swap, Ollama or vLLM box, or a cloud gateway such as Azure AI Foundry or OpenRouter. Save an endpoint once (`POST /api/model-endpoints`; its models are discovered from `/v1/models`), apply it to a session (`POST /api/sessions/:id/custom-model`), and the CLI restarts in place on that endpoint. Verified live for Claude, OpenCode, Pi, Grok and OMP; Codex, Gemini and DeepSeek have documented gaps, Antigravity has no mechanism. A toolbar picker is the follow-up. See [`docs/custom-model-endpoints.md`](docs/custom-model-endpoints.md)
|
||||
- **Web tabs** — open Grafana, Uptime Kuma, a Vite dev server or any dashboard URL as a tab beside your sessions (Run dropdown → **Web / URL** → **Add dashboard**). Dashboards are proxied through Codeman's own origin, so an `http://` target works from a phone over HTTPS and through the tunnel, single-page apps route on their own paths, and a frame that reloads recovers itself. A `localhost` link an agent prints opens as a web tab automatically. See [`docs/web-tabs.md`](docs/web-tabs.md)
|
||||
- **Web tabs** — open Grafana, Uptime Kuma, a Vite dev server or any dashboard URL as a tab beside your sessions (Run dropdown → **Web / URL** → **Add URL**). Dashboards are proxied through Codeman's own origin, so an `http://` target works from a phone over HTTPS and through the tunnel, single-page apps route on their own paths, and a frame that reloads recovers itself. A `localhost` link an agent prints opens as a web tab automatically. See [`docs/web-tabs.md`](docs/web-tabs.md)
|
||||
- **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, or attach a case to a container you already run; 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)
|
||||
- **Remote SSH sessions** — point a case at another machine and run the agent there inside a durable remote tmux: survives SSH drops, auto-reconnects, and can discover + attach sessions already running on the host; file previews and downloads come over the same ssh connection. See [`docs/remote-sessions.md`](docs/remote-sessions.md)
|
||||
- **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
|
||||
|
||||
+1
-1
@@ -445,7 +445,7 @@ PTY 输出 → 16ms 服务端批处理 → DEC 2026 包裹 → SSE → 客户端
|
||||
- **把 GitHub 仓库克隆成 case** —— 在 **Add Case → Clone Repo** 里粘贴一个仓库 URL,Codeman 会把它克隆到 `~/codeman-cases/<name>` 并注册为普通 case,随时可以跑智能体。输入时它会预检 URL(告诉你能否匿名克隆,并为可选的分支/标签字段提供仓库真实的分支与标签),从 URL 里填好 case 名,还让你选 Run 按钮该用哪个 CLI。支持 `https://` 的公开仓库;Codeman 绝不收集或保存凭据
|
||||
- **多 CLI** —— 每个会话可选 **Claude Code**、**OpenCode**、**Codex**、**Antigravity**、**Gemini**、**Pi**、**Grok**、**DeepSeek Harness** 或 **OMP**;环境变量前缀自动隔离(`CLAUDE_CODE_*`、`OPENCODE_*`、`CODEX_*`、`ANTIGRAVITY_*`、`GEMINI_*`/`GOOGLE_*`、`PI_*`、`GROK_*`/`XAI_*`、`DSH_*`/`DEEPSEEK_*` 与 `OMP_*`)。详见 [`docs/opencode-integration.md`](docs/opencode-integration.md)、[`docs/pi-integration.md`](docs/pi-integration.md)、[`docs/grok-integration.md`](docs/grok-integration.md)、[`docs/deepseek-integration.md`](docs/deepseek-integration.md) 与 [`docs/omp-integration.md`](docs/omp-integration.md)
|
||||
- **自定义模型端点**(1.29.0 新增,目前仅 HTTP API)—— 让某个会话的 CLI 指向任意 OpenAI 兼容端点,而不是它自己的官方后端:本地的 llama.cpp、llama-swap、Ollama 或 vLLM 机器,也可以是 Azure AI Foundry、OpenRouter 这类云端网关。端点只需保存一次(`POST /api/model-endpoints`,模型列表从它的 `/v1/models` 自动发现),再应用到会话(`POST /api/sessions/:id/custom-model`),CLI 就会在原地重启并接上该端点。Claude、OpenCode、Pi、Grok 与 OMP 已实测通过;Codex、Gemini 与 DeepSeek 存在已记录的缺口,Antigravity 没有可用机制。工具栏选择器是下一步。详见 [`docs/custom-model-endpoints.md`](docs/custom-model-endpoints.md)
|
||||
- **Web 标签页** —— 把 Grafana、Uptime Kuma、一个 Vite 开发服务器或任何仪表盘 URL 作为标签页打开在会话旁边(Run 下拉菜单 → **Web / URL** → **Add dashboard**)。仪表盘通过 Codeman 自己的源代理,因此 `http://` 目标在手机上走 HTTPS 也能用、走隧道也能用;单页应用能在自己的路径上正常路由,页面自己重载后也能自行恢复。智能体打印出的 `localhost` 链接会自动以 Web 标签页打开。详见 [`docs/web-tabs.md`](docs/web-tabs.md)
|
||||
- **Web 标签页** —— 把 Grafana、Uptime Kuma、一个 Vite 开发服务器或任何仪表盘 URL 作为标签页打开在会话旁边(Run 下拉菜单 → **Web / URL** → **Add URL**)。仪表盘通过 Codeman 自己的源代理,因此 `http://` 目标在手机上走 HTTPS 也能用、走隧道也能用;单页应用能在自己的路径上正常路由,页面自己重载后也能自行恢复。智能体打印出的 `localhost` 链接会自动以 Web 标签页打开。详见 [`docs/web-tabs.md`](docs/web-tabs.md)
|
||||
- **Docker 会话** —— 在隔离且加固的容器中运行 case。**Create New** 上勾选一个复选框即可用合理的默认值启动容器并在其中启动智能体;同一 case 的多个会话共享一个容器,也可以把 case 挂到你已经在跑的容器上;可将容器连同工作区导出为可移植的 `.tar.gz`,迁移到另一台机器。详见 [`docs/docker-cases.md`](docs/docker-cases.md)
|
||||
- **远程 SSH 会话** —— 把 case 指向另一台机器,让智能体在那里一个持久的远程 tmux 中运行:SSH 断连不中断任务、自动重连,还能发现并附着主机上已在运行的会话;文件预览与下载走同一条 ssh 连接。详见 [`docs/remote-sessions.md`](docs/remote-sessions.md)
|
||||
- **Effort 与 Ultracode** —— 设置每会话的默认 effort(`low`–`max`),或启用 **ultracode**(动态多智能体工作流)。这些都只是软默认值 —— 会话中可随时用 `/effort` 切换。扩展思考预算也可配置
|
||||
|
||||
+85
-11
@@ -1,9 +1,9 @@
|
||||
# Agent CLIs
|
||||
|
||||
Codeman drives seven run modes: six agent CLIs plus a plain shell. This page covers picking
|
||||
Codeman drives ten run modes: nine agent CLIs plus a plain shell. This page covers picking
|
||||
one, setting it up, and the differences that actually change how you work.
|
||||
|
||||
## The seven modes
|
||||
## The ten modes
|
||||
|
||||
| Mode | CLI | Get it |
|
||||
| -------------------- | ---------------------------- | ---------------------------------------------------------------------- |
|
||||
@@ -13,6 +13,9 @@ one, setting it up, and the differences that actually change how you work.
|
||||
| **Gemini** | `gemini` | [github.com/google-gemini/gemini-cli](https://github.com/google-gemini/gemini-cli) |
|
||||
| **Antigravity** | `agy` | [antigravity.google](https://antigravity.google) |
|
||||
| **Pi** | `pi` | [pi.dev](https://pi.dev) |
|
||||
| **Grok Build** | `grok` | [github.com/xai-org/grok-build](https://github.com/xai-org/grok-build) |
|
||||
| **DeepSeek Harness** | `dsh` | [github.com/deepseek-ai/deepseek-harness](https://github.com/deepseek-ai/deepseek-harness) |
|
||||
| **OMP** | `omp` | [github.com/can1357/oh-my-pi](https://github.com/can1357/oh-my-pi) |
|
||||
| **Terminal / Shell** | your `$SHELL` | Already installed. |
|
||||
|
||||
Any combination works, including all of them. The run mode is chosen per session from the
|
||||
@@ -47,8 +50,12 @@ If a CLI is installed but a Run button for it never appears:
|
||||
precisely to avoid this; a hand-written plist or unit will not.
|
||||
3. Restart the server after installing a new CLI.
|
||||
|
||||
`pi` is additionally version-probed rather than trusted by name, because `pi` is a generic
|
||||
enough command that something else on your PATH may answer to it.
|
||||
`pi`, `grok`, `omp` and `dsh` are additionally identity-probed rather than trusted by name:
|
||||
`pi` and `omp` are generic enough that something else on your PATH may answer to them,
|
||||
`grok` has npm squatters, and Debian ships an unrelated `dsh` (dancer's shell). Each has a
|
||||
status endpoint (`/api/grok/status`, `/api/deepseek/status`, `/api/omp/status`) that reports
|
||||
the path and version that actually resolved, so a misresolution is visible rather than
|
||||
presenting as "the mode just does not work".
|
||||
|
||||
## Claude is the reference mode
|
||||
|
||||
@@ -62,15 +69,15 @@ output. The other CLIs expose no equivalent.
|
||||
| Respawn cycling and unattended runs | Yes | Yes |
|
||||
| Cron jobs | Yes | Yes |
|
||||
| Docker cases, remote SSH cases | Yes | Yes |
|
||||
| Precise idle detection (hook-driven) | Yes | Output-stabilization fallback, coarser |
|
||||
| Precise idle detection | Yes | Codex: same screen check, via its own prompt and working line. DeepSeek: reports its state itself. Others: output stabilization, coarser |
|
||||
| Auto-resume when a usage limit resets | Yes | No |
|
||||
| Plan usage chip | Yes | No |
|
||||
| Approvals Inbox | Yes | No |
|
||||
| Approvals Inbox | Yes | DeepSeek yes; others no |
|
||||
| Read My Mind | Yes | No |
|
||||
| Ralph loop and its task tracker | Yes | No |
|
||||
| Subagent and team windows | Yes | No |
|
||||
| Model, effort, and ultracode controls | Yes | No |
|
||||
| `stop` and `blocked` wait signals | Yes | 400 if you ask for them explicitly |
|
||||
| `stop` and `blocked` wait signals | Yes | DeepSeek yes; elsewhere 400 if you ask for them explicitly |
|
||||
| The bundled agent skill | Yes | No |
|
||||
|
||||
Everything that makes a session a session works everywhere. What is Claude-only is mostly
|
||||
@@ -124,6 +131,11 @@ Two behaviours that are deliberate and worth knowing:
|
||||
- **The wheel is not forwarded** into its transcript. Codex ignores the mouse reports
|
||||
Codeman would send, so forwarding produced a dead wheel. Scrolling in a Codex session is
|
||||
local scrollback.
|
||||
- **Work detection is Codex's own.** Codex declares its `›` composer glyph and its
|
||||
`esc to interrupt` working line, so it gets the same screen-checked idle detection Claude
|
||||
does; before 1.26.1 every Codex session reported idle for its whole life. Codex
|
||||
conversations also appear in Past Sessions and can be resumed, and on phones the keyboard
|
||||
bar grows `⇧←` / `⇧→` for Codex's queued-message editing and prompt stack.
|
||||
|
||||
### Gemini
|
||||
|
||||
@@ -157,6 +169,60 @@ Pi needs the opposite instincts from every other CLI here.
|
||||
|
||||
Guide: [`docs/pi-integration.md`](https://github.com/Ark0N/Codeman/blob/master/docs/pi-integration.md).
|
||||
|
||||
### Grok Build
|
||||
|
||||
xAI's `grok`, installed with `curl -fsSL https://x.ai/cli/install.sh | bash` into
|
||||
`~/.grok/bin`. Codex-shaped on permissions and OpenCode-shaped on rendering:
|
||||
|
||||
- **Its bypass switch is `--always-approve`**, Grok's own `bypassPermissions` mode, and the
|
||||
Run button sends it the way it sends Codex's. In multi-user mode a user without a grant
|
||||
has it stripped.
|
||||
- **Authentication is Grok's own**: browser OAuth on first run (a device-code screen inside
|
||||
a Codeman pane), `grok login --device-auth` for headless hosts, or `XAI_API_KEY` as a
|
||||
per-session environment override.
|
||||
- It renders a full-screen TUI, so scrolling is local scrollback.
|
||||
|
||||
Guide: [`docs/grok-integration.md`](https://github.com/Ark0N/Codeman/blob/master/docs/grok-integration.md).
|
||||
|
||||
### DeepSeek Harness
|
||||
|
||||
The mode wired least like the others, for two reasons worth knowing before you use it.
|
||||
|
||||
**`dsh` is a launcher, not an agent.** It boots a *profile*, and the three DeepSeek ships
|
||||
(`web`, `headless`, `base`) cannot drive a terminal pane. So "installed" and "runnable" are
|
||||
different questions: the Run menu offers **DeepSeek** only once a pane-capable profile
|
||||
exists, and until then shows **DeepSeek — add a terminal profile…**, which installs the
|
||||
community `dsh-tui` with one click (`pnpm` must be on PATH, because the launcher spawns it
|
||||
directly).
|
||||
|
||||
**Permissions are an environment variable, not a flag.** The harness has no
|
||||
skip-permissions switch. `DSH_PERMISSION_MODE` (`read-only`, `workspace-write`,
|
||||
`danger-full-access`) is the whole control, and it is the one setting Codeman deliberately
|
||||
carries as an environment variable, because the harness reads it as a soft boot-time
|
||||
default. In multi-user mode a user without a grant is clamped to `workspace-write`.
|
||||
|
||||
The reward for the odd wiring: **DeepSeek is the one non-Claude mode with real signals.**
|
||||
Its terminal front door reports idle, working and blocked to Codeman, so a DeepSeek
|
||||
session gets precise idle detection, the `stop` and `blocked` wait signals, and Approvals
|
||||
Inbox items. Answers are read from the harness's own transcript on disk rather than
|
||||
scraped off the pane. The model is not a session setting; it is part of the profile.
|
||||
|
||||
Guide: [`docs/deepseek-integration.md`](https://github.com/Ark0N/Codeman/blob/master/docs/deepseek-integration.md).
|
||||
|
||||
### OMP
|
||||
|
||||
Oh My Pi, installed with `curl -fsSL https://omp.sh/install | sh` into `~/.local/bin`.
|
||||
OMP owns its auth, provider routing and approval mode entirely in `~/.omp`: there is no
|
||||
Codeman-side login, key field, or bypass switch. Run `omp` once outside Codeman to finish
|
||||
its own onboarding, and every session started through Codeman inherits that config. Its
|
||||
documented default approval mode is `yolo`, so an OMP pane auto-approves tool use with no
|
||||
flag from Codeman; change that in OMP's own config, not here.
|
||||
|
||||
OMP conversations appear in Past Sessions and can be resumed, and a respawn continues the
|
||||
same conversation with `--continue`.
|
||||
|
||||
Guide: [`docs/omp-integration.md`](https://github.com/Ark0N/Codeman/blob/master/docs/omp-integration.md).
|
||||
|
||||
### Terminal / Shell
|
||||
|
||||
A plain shell in a tmux session. No agent, no hooks, no idle detection.
|
||||
@@ -180,9 +246,15 @@ respawns. Which variables are accepted depends on the mode:
|
||||
| Gemini | `GEMINI_*`, `GOOGLE_*` |
|
||||
| Antigravity | `ANTIGRAVITY_*` |
|
||||
| Pi | `PI_*` |
|
||||
| Grok | `GROK_*`, `XAI_*` |
|
||||
| DeepSeek | `DSH_*`, `DEEPSEEK_*` |
|
||||
| OMP | `OMP_*` |
|
||||
|
||||
Anything outside the allowlist is rejected at the schema. This is intentional: the allowlist
|
||||
is one global list, so widening it for one CLI widens it for all of them.
|
||||
is one global list, so widening it for one CLI widens it for all of them. In multi-user mode
|
||||
the keys that could redirect a CLI's traffic or move its config home (`DSH_PERMISSION_MODE`,
|
||||
`DSH_HOME`, `DEEPSEEK_BASE_URL`, `OMP_AUTH_BROKER_URL`, and the base URLs and config
|
||||
directories of the others) are dropped for a user without the bypass grant.
|
||||
|
||||
Two things that deliberately do **not** travel as environment variables: **effort**, because
|
||||
an environment variable hard-locks it and blocks `/effort`, and **model**, which is written
|
||||
@@ -192,9 +264,11 @@ into the case's `.claude/settings.local.json` so that `/model` keeps working.
|
||||
|
||||
- **Claude Code** if you want every Codeman feature. Unattended overnight runs, usage-limit
|
||||
auto-resume, the Approvals Inbox, and subagent visualization all assume it.
|
||||
- **Codex, OpenCode, Gemini, Antigravity** when you prefer that agent or that model. You get
|
||||
the session layer, respawn, cron, Docker, and remote SSH; you do not get the hook-driven
|
||||
features.
|
||||
- **Codex, OpenCode, Gemini, Antigravity, Grok, OMP** when you prefer that agent or that
|
||||
model. You get the session layer, respawn, cron, Docker, and remote SSH; you do not get the
|
||||
hook-driven features.
|
||||
- **DeepSeek Harness** if you want DeepSeek's models with real status signals. It is the one
|
||||
non-Claude mode that reports idle, working and blocked to Codeman itself.
|
||||
- **Pi** if you want a fast, unsandboxed agent and you understand what project trust does.
|
||||
- **Shell** for the times you want a terminal on your phone with no agent at all. It is a
|
||||
genuinely useful mode, not a fallback.
|
||||
|
||||
@@ -108,7 +108,7 @@ Conventions for wiki pages:
|
||||
- Images are referenced from the main repository over raw URLs rather than being copied into
|
||||
the wiki.
|
||||
- Say what the default is, especially when it is off. Most of Codeman is opt-in.
|
||||
- Label Claude-only behaviour every time it appears. Six of the seven run modes are not
|
||||
- Label Claude-only behaviour every time it appears. Nine of the ten run modes are not
|
||||
Claude.
|
||||
|
||||
## Conduct
|
||||
|
||||
@@ -50,10 +50,10 @@ A session carries state the case does not:
|
||||
## Run mode
|
||||
|
||||
The **run mode** is which CLI the session runs: `claude`, `opencode`, `codex`, `gemini`,
|
||||
`antigravity`, `pi`, or `shell`. It is chosen at start and does not change afterwards; to
|
||||
`antigravity`, `pi`, `grok`, `deepseek`, `omp`, or `shell`. It is chosen at start and does not change afterwards; to
|
||||
switch, start another session.
|
||||
|
||||
Claude is the reference mode. Six of the seven are not Claude, and a number of Codeman
|
||||
Claude is the reference mode. Nine of the ten are not Claude, and a number of Codeman
|
||||
features are Claude-only for structural reasons rather than missing effort: they depend on
|
||||
Claude Code's hook system or on parsing its terminal output. Every such feature is labelled
|
||||
Claude-only where it appears, and [Agent CLIs](Agent-CLIs) lists them in one place.
|
||||
@@ -68,8 +68,8 @@ Where a case runs is **separate from** which CLI it runs. There are three locati
|
||||
| **Docker** | One long-lived container per case; sessions `docker exec` into it. See [Docker Cases](Docker-Cases). |
|
||||
| **Remote SSH** | A durable tmux server on the remote host, fronted by a local pane running `ssh`. See [Remote SSH Sessions](Remote-SSH-Sessions). |
|
||||
|
||||
This matters because it is a common source of confusion: Docker is **not** an eighth run
|
||||
mode. All seven run modes work in all three locations. A case is docker-backed or
|
||||
This matters because it is a common source of confusion: Docker is **not** an eleventh run
|
||||
mode. All ten run modes work in all three locations. A case is docker-backed or
|
||||
ssh-backed; a session is claude or codex or shell.
|
||||
|
||||
**Web tabs** are the other thing that is not a session. A saved dashboard URL renders as a
|
||||
@@ -155,9 +155,11 @@ report events back: a permission prompt appeared, the turn finished, the agent w
|
||||
task completed. Those events drive tab alerts, the Approvals Inbox, notifications, and the
|
||||
wait primitives.
|
||||
|
||||
This is why some features are Claude-only. The other CLIs have no equivalent hook system,
|
||||
so for them Codeman falls back to watching terminal output, which is coarser: it can see
|
||||
that something happened, not what it was.
|
||||
This is why some features are Claude-only. The one partial exception is DeepSeek Harness,
|
||||
whose terminal front door reports idle, working and blocked to Codeman over the harness's
|
||||
own supervisor contract, so it gets the hook-driven signals without a hook file. The other
|
||||
CLIs have no equivalent, so for them Codeman falls back to watching terminal output, which
|
||||
is coarser: it can see that something happened, not what it was.
|
||||
|
||||
See [Hooks And Integrations](Hooks-And-Integrations).
|
||||
|
||||
@@ -167,7 +169,7 @@ See [Hooks And Integrations](Hooks-And-Integrations).
|
||||
| --------------- | ---------------------------------------------------------------------------- |
|
||||
| **Case** | Named working directory. |
|
||||
| **Session** | One CLI in one tmux session. |
|
||||
| **Run mode** | Which CLI: claude, opencode, codex, gemini, antigravity, pi, shell. |
|
||||
| **Run mode** | Which CLI: claude, opencode, codex, gemini, antigravity, pi, grok, deepseek, omp, shell. |
|
||||
| **Respawn** | Restarting the CLI on idle to keep an unattended run going. |
|
||||
| **Ralph loop** | An autonomous single-session task loop. |
|
||||
| **Orchestrator**| A phased plan driven across multiple agents. |
|
||||
@@ -178,6 +180,6 @@ See [Hooks And Integrations](Hooks-And-Integrations).
|
||||
## Read next
|
||||
|
||||
- [The Dashboard](The-Dashboard) - what the UI is showing you.
|
||||
- [Agent CLIs](Agent-CLIs) - the seven run modes in detail.
|
||||
- [Agent CLIs](Agent-CLIs) - the ten run modes in detail.
|
||||
- [Keeping Agents Running](Keeping-Agents-Running) - respawn, idle detection, usage limits.
|
||||
- [`docs/architecture-invariants.md`](https://github.com/Ark0N/Codeman/blob/master/docs/architecture-invariants.md) - the mechanisms behind all of this, for contributors.
|
||||
|
||||
@@ -4,7 +4,7 @@ Run a case inside its own container instead of directly on your host: for isolat
|
||||
reproducible toolchain, and for the ability to pick the whole environment up and move it to
|
||||
another machine.
|
||||
|
||||
A docker case is a **location overlay**, not a run mode. All seven run modes work inside a
|
||||
A docker case is a **location overlay**, not a run mode. All ten run modes work inside a
|
||||
container. See [Core Concepts](Core-Concepts).
|
||||
|
||||
## One-time setup: the base image
|
||||
@@ -26,7 +26,7 @@ A zero exit code proves the layers ran, not that the toolchain works. Verify:
|
||||
|
||||
```bash
|
||||
docker run --rm codeman/agent:base bash -lc \
|
||||
'for c in claude codex gemini opencode agy pi; do printf "%-9s " $c; $c --version 2>&1 | head -1; done'
|
||||
'for c in claude codex gemini opencode agy pi grok dsh omp; do printf "%-9s " $c; $c --version 2>&1 | head -1; done'
|
||||
```
|
||||
|
||||
The image is secret-free. Credentials are delivered at runtime, never baked in, so exports
|
||||
@@ -79,6 +79,25 @@ Exactly one long-lived container per case, shared by every session in it.
|
||||
conversation** from the bind-mounted transcript.
|
||||
- Deleting the case removes the container. The workspace on the host survives.
|
||||
|
||||
## Attaching to a container you already run
|
||||
|
||||
Tick **Attach to an existing container** on **Add Case → Docker** to link a case to a
|
||||
container that already exists instead of creating one. Codeman only `exec`s into it and
|
||||
never creates, starts, stops, restarts or removes it, so a container that is missing or
|
||||
stopped fails with a message rather than being fixed for you. Drift detection does not
|
||||
apply (the container carries no Codeman configuration label). The full-image export is
|
||||
refused, since it would `docker commit` someone else's container, and the workspace export
|
||||
skips the pause that keeps an owned container consistent during the capture.
|
||||
|
||||
One adopted container can back several cases at different in-container directories, and
|
||||
**copy an existing case** pre-fills the form from a sibling on the same container. An exact
|
||||
twin (the same container and the same directory) is refused, as is a container another
|
||||
user adopted.
|
||||
|
||||
Adoption is **admin-only in multi-user mode**. Linking creates Codeman's own container
|
||||
with one bind mount that has already been checked; an adopted container's mounts belong to
|
||||
whoever started it, and one that mounts `/` hands the adopter the host.
|
||||
|
||||
## Credentials
|
||||
|
||||
Your existing host logins work inside the container without logging in again. Credentials
|
||||
@@ -92,10 +111,12 @@ the container instead.
|
||||
|
||||
Bind mounts are excluded from image capture, so exports stay secret-free.
|
||||
|
||||
One consequence worth knowing: Pi's credentials are seeded per file rather than as a whole
|
||||
directory, because that directory also holds sessions, extensions, and installed packages,
|
||||
which can be gigabytes. So in-container Pi sessions are invisible from the host, and `pi -c`
|
||||
inside a docker case sees only that container's history.
|
||||
One consequence worth knowing: Pi, Grok and OMP credentials are seeded per file rather than
|
||||
as whole directories, because those directories also hold sessions, extensions, downloads and
|
||||
installed packages, which can be gigabytes. So in-container Pi and Grok sessions are
|
||||
invisible from the host (`pi -c` and `grok -c` inside a docker case see only that
|
||||
container's history). OMP's `sessions/` is the exception and is shared read-write, because
|
||||
Codeman reads it host-side for history and resume.
|
||||
|
||||
## Isolation
|
||||
|
||||
|
||||
@@ -54,7 +54,10 @@ create-time sweep would yank the skill out from under other live sessions sharin
|
||||
directory. Remove them per case with `codeman skill uninstall --case <name>`.
|
||||
|
||||
The skill ships with the verb index always loaded, plus on-demand references for the verbs,
|
||||
worked multi-worker recipes, endpoint tables, and cross-session messaging.
|
||||
worked multi-worker recipes, endpoint tables, and cross-session messaging. It drives
|
||||
DeepSeek Harness workers the same way it drives Claude ones (`spawn_workers alpha
|
||||
beta:deepseek` is a mixed fleet in one call), since those are the two modes with real
|
||||
completion signals.
|
||||
|
||||
## The manual path
|
||||
|
||||
@@ -92,8 +95,9 @@ Read these before writing any code. Each one has cost somebody an afternoon.
|
||||
5. **Wait instead of polling, and a timeout is not an error.** The wait endpoints answer
|
||||
`200` with `wait.timedOut: true`. Loop over short waits rather than one long call, because
|
||||
tunnels cut idle connections.
|
||||
6. **Only `claude` sessions emit `stop` and `blocked`.** They come from Claude Code hooks.
|
||||
Shell and the external CLIs accept only `idle`, `working`, and `exit`; asking for `stop`
|
||||
6. **Only `claude` and `deepseek` sessions emit `stop` and `blocked`.** Claude's come from
|
||||
Claude Code hooks, DeepSeek's from the harness reporting its state to Codeman. Shell and
|
||||
the other external CLIs accept only `idle`, `working`, and `exit`; asking for `stop`
|
||||
explicitly there is a `400`, while omitting `until` is always safe. On a shell session
|
||||
`idle` fires **once at startup and never again**, so synchronize hook-less sessions with an
|
||||
output marker instead.
|
||||
@@ -130,7 +134,10 @@ curl -s -X POST "$API/api/sessions/$ID/input" \
|
||||
# Or wait for a marker in the output, which works on shell sessions too
|
||||
curl -s "$API/api/sessions/$ID/wait-output?contains=DONE_17909&from=buffer" | jq
|
||||
|
||||
# Read the terminal back
|
||||
# Read the last answer as clean text (claude, codex, deepseek sessions)
|
||||
curl -s "$API/api/sessions/$ID/last-response" | jq -r '.data.text'
|
||||
|
||||
# Or read the terminal back
|
||||
curl -s "$API/api/sessions/$ID/terminal?tail=4000" | jq -r '.data.output'
|
||||
|
||||
# Clean up, by exact id
|
||||
@@ -157,7 +164,13 @@ Make it unique per call, because tmux repaints replay old screen text.
|
||||
|
||||
### Reading output
|
||||
|
||||
Use `terminal?tail=`, not `/output`. The latter's text field is empty for every tmux-backed
|
||||
For `claude`, `codex` and `deepseek` sessions, read the answer from the transcript rather
|
||||
than the screen: `GET /api/sessions/:id/last-response` returns the last reply as clean text
|
||||
with no TUI frames or repaint noise. Poll it briefly rather than reading once, because the
|
||||
transcript lands slightly after the `stop` signal, so a read immediately after send-and-wait
|
||||
returns often comes back empty.
|
||||
|
||||
For everything else, use `terminal?tail=`, not `/output`. The latter's text field is empty for every tmux-backed
|
||||
session, which is every interactive session. `tail` counts **bytes**, and what comes back is
|
||||
terminal data with ANSI sequences included.
|
||||
|
||||
|
||||
@@ -21,6 +21,12 @@ No. Codeman drives agent CLIs you have already installed and logged in yourself.
|
||||
subscription or key that CLI uses is what pays for the tokens. Codeman never collects,
|
||||
stores, or refreshes your credentials.
|
||||
|
||||
### Which agent CLIs does it support?
|
||||
|
||||
Claude Code, OpenCode, Codex, Gemini, Antigravity, Pi, Grok Build, DeepSeek Harness and
|
||||
OMP, plus a plain shell, chosen per session. Claude is the reference mode and a few features
|
||||
are Claude-only; [Agent CLIs](Agent-CLIs) has the table.
|
||||
|
||||
### Does Codeman send my code or prompts anywhere?
|
||||
|
||||
No. There is no telemetry, no analytics, and no phone-home. The only network traffic
|
||||
|
||||
+18
-9
@@ -66,14 +66,14 @@ self-signed certificate, add `-k`.
|
||||
|
||||
## Endpoint map
|
||||
|
||||
Roughly 200 handlers across 24 route modules. By domain:
|
||||
Roughly 235 handlers across 26 route modules. By domain:
|
||||
|
||||
| Domain | Handlers | Covers |
|
||||
| ------------------- | -------- | --------------------------------------------------- |
|
||||
| System | 45 | Status, settings, search, digest, updates. |
|
||||
| Sessions | 34 | Create, input, terminal, wait, kill. |
|
||||
| Cases | 29 | Create, link, clone, remote and docker cases. |
|
||||
| Files | 16 | Preview, edit, raw, attachments, path picker. |
|
||||
| System | 56 | Status, settings, digest, updates, tunnel. |
|
||||
| Sessions | 34 | Create, input, terminal, wait, last response, kill. |
|
||||
| Cases | 34 | Create, link, clone, remote and docker cases. |
|
||||
| Files | 17 | Preview, edit, raw, attachments, path picker. |
|
||||
| Orchestrator | 10 | Plans and phases. |
|
||||
| Ralph | 9 | Loop control and configuration. |
|
||||
| Cron | 9 | Jobs and run history. |
|
||||
@@ -82,10 +82,12 @@ Roughly 200 handlers across 24 route modules. By domain:
|
||||
| Respawn | 7 | Respawn configuration and presets. |
|
||||
| Webviews | 6 | Saved dashboards, plus the proxy. |
|
||||
| Mux | 5 | tmux operations. |
|
||||
| Custom model endpoints | 5 | Saved OpenAI-compatible endpoints, and applying one to a session. |
|
||||
| Push | 4 | Web push subscriptions. |
|
||||
| Read My Mind | 4 | Intent profiles and prediction. |
|
||||
| Scheduled | 4 | The legacy scheduled-run concept. |
|
||||
| Approvals | 3 | The inbox and answering. |
|
||||
| Approvals | 4 | The inbox, answering, acknowledging. |
|
||||
| Tab layout | 2 | Named tab groups per owner. |
|
||||
| Teams, me, search, hooks, clipboard, telemetry, voice, ws | 1-2 each | |
|
||||
|
||||
Each route module documents its own endpoints in its file header.
|
||||
@@ -114,12 +116,13 @@ Three semantics that break callers who assume otherwise:
|
||||
`wait-output` matches a **literal substring, never a regex.** That is deliberate: no regex
|
||||
means no catastrophic backtracking on attacker-influenced output.
|
||||
|
||||
Only `claude` sessions emit `stop` and `blocked`, because those come from Claude Code hooks.
|
||||
Shell and external CLI sessions accept `idle`, `working`, and `exit`.
|
||||
Only `claude` and `deepseek` sessions emit `stop` and `blocked`: Claude's come from Claude
|
||||
Code hooks, DeepSeek's from the harness reporting its state to Codeman. Shell and the other
|
||||
external CLI sessions accept `idle`, `working`, and `exit`.
|
||||
|
||||
## SSE
|
||||
|
||||
`GET /api/events` is the live event stream. 156 event names, kept in sync between server and
|
||||
`GET /api/events` is the live event stream. 158 event names, kept in sync between server and
|
||||
client with a test that fails on drift.
|
||||
|
||||
The heartbeat is a **named** `sse:heartbeat` event rather than an SSE comment, because
|
||||
@@ -141,6 +144,12 @@ curl -s "$API/api/sessions" | jq '.data[].name' # live sessions
|
||||
curl -s "$API/api/sessions/unified" | jq # live + historical, deduped
|
||||
curl -s "$API/api/subagents" | jq # background agents
|
||||
curl -s "$API/api/search?q=deploy" | jq # cross-session search
|
||||
|
||||
# with ID set to a session id:
|
||||
curl -s "$API/api/sessions/$ID/last-response" | jq -r '.data.text' # last answer, from the transcript (claude, codex, deepseek)
|
||||
curl -s "$API/api/model-endpoints" | jq # saved custom OpenAI-compatible endpoints
|
||||
curl -s -X POST "$API/api/sessions/$ID/custom-model" -H 'Content-Type: application/json' \
|
||||
-d '{"endpointId":"local-llama","modelId":"qwen3-27b"}' | jq # restart the CLI on that endpoint; {"clear":true} undoes it
|
||||
```
|
||||
|
||||
## Limits
|
||||
|
||||
+4
-4
@@ -5,8 +5,8 @@
|
||||
<h3 align="center">Mission control for AI coding agents</h3>
|
||||
|
||||
Codeman runs your coding agents on your own machine and puts them behind one dashboard you
|
||||
can open from any device. It spawns Claude Code, OpenCode, Codex, Antigravity, Gemini, or
|
||||
Pi inside persistent tmux sessions, streams the real terminal to the browser, and keeps
|
||||
can open from any device. It spawns Claude Code, OpenCode, Codex, Antigravity, Gemini, Pi,
|
||||
Grok, DeepSeek Harness, or OMP inside persistent tmux sessions, streams the real terminal to the browser, and keeps
|
||||
working while you are away from the keyboard: it re-prompts idle agents, resumes when a
|
||||
subscription limit resets, runs jobs on a schedule, and shows every background subagent
|
||||
live.
|
||||
@@ -33,7 +33,7 @@ codeman web # then open http://localhost:3000
|
||||
|
||||
**Already running it**
|
||||
|
||||
- [Agent CLIs](Agent-CLIs) - the seven run modes, their setup, and which features are Claude-only.
|
||||
- [Agent CLIs](Agent-CLIs) - the ten run modes, their setup, and which features are Claude-only.
|
||||
- [Mobile Guide](Mobile-Guide) - phone and tablet use, QR login, the touch keyboard bar.
|
||||
- [Remote Access](Remote-Access) - Tailscale, Cloudflare tunnel, LAN plus password, QR login.
|
||||
- [Keeping Agents Running](Keeping-Agents-Running) - idle detection, respawn cycling, auto-resume on usage limits.
|
||||
@@ -122,7 +122,7 @@ codeman web # then open http://localhost:3000
|
||||
| OS | macOS or Linux. Windows works through WSL2. |
|
||||
| Node.js | 22 or newer. |
|
||||
| tmux | Required. Sessions live in tmux, which is what makes them survive restarts. |
|
||||
| An agent CLI | At least one of Claude Code, OpenCode, Codex, Gemini, Antigravity, Pi. Plain shell sessions need none. |
|
||||
| An agent CLI | At least one of Claude Code, OpenCode, Codex, Gemini, Antigravity, Pi, Grok Build, DeepSeek Harness, OMP. Plain shell sessions need none. |
|
||||
| Network | Binds to `127.0.0.1` by default. Reaching it from another device is a deliberate step: see [Remote Access](Remote-Access). |
|
||||
|
||||
Codeman is MIT licensed, self-hosted, and sends no telemetry. Everything runs on your
|
||||
|
||||
@@ -19,9 +19,11 @@ terminal into something that can notify you.
|
||||
| `teammate_idle` | An agent-team member goes idle. | Team surfaces. |
|
||||
| `task_completed` | A task finishes. | Task tracking, run summary. |
|
||||
|
||||
This is why several Codeman features are Claude-only. The other CLIs have no hook system, so
|
||||
for them Codeman watches terminal output, which reveals that something happened but not what
|
||||
it was.
|
||||
This is why several Codeman features are Claude-only. The one partial exception is DeepSeek
|
||||
Harness, whose terminal front door reports idle, working and blocked to Codeman over the
|
||||
harness's own supervisor contract, so it gets the hook-driven surfaces without any hook
|
||||
file. The other CLIs have no equivalent, so for them Codeman watches terminal output, which
|
||||
reveals that something happened but not what it was.
|
||||
|
||||
### How hooks get installed
|
||||
|
||||
@@ -67,7 +69,7 @@ sit beside the agents with no code at all. See [Web Tabs](Web-Tabs).
|
||||
### 2. SSE events
|
||||
|
||||
`GET /api/events` streams everything Codeman knows: session lifecycle, output, agent
|
||||
activity, approvals, cron runs. 155 named events, stable under semantic versioning.
|
||||
activity, approvals, cron runs. 158 named events, stable under semantic versioning.
|
||||
|
||||
This is the seam for anything that reacts. A bot that pings your chat channel when an agent
|
||||
needs a human is a short script over this stream.
|
||||
|
||||
@@ -27,6 +27,15 @@ The result is the property you want on a phone: a connection that drops mid-prom
|
||||
loses the prompt and never delivers it twice. Two browser tabs on the same session coexist,
|
||||
and only a reconnect from the *same* tab supersedes the old connection.
|
||||
|
||||
## Selecting and copying
|
||||
|
||||
Agent CLIs hold the mouse: clicks and drags are reported into the transcript rather than
|
||||
selecting text. `Shift+drag` starts a selection anyway, right-click copies it (with nothing
|
||||
selected the native context menu is left alone), and `Ctrl+Shift+C` copies without ever
|
||||
interrupting. **Auto Copy Selection** in **App Settings → Terminal & Input**, off by
|
||||
default, copies the moment you release the mouse. On phones, long-press selects; see
|
||||
[Mobile Guide](Mobile-Guide).
|
||||
|
||||
## Zero-lag local echo
|
||||
|
||||
On touch devices, keystrokes are painted in the terminal immediately and sent when you press
|
||||
@@ -55,6 +64,8 @@ reconcile against the real buffer and only apply while the cursor is on the comp
|
||||
Chinese, Japanese, and Korean input needs an IME, and an IME needs a real text field.
|
||||
Turning on CJK input in **App Settings → Terminal & Input** puts an always-visible textarea
|
||||
below the terminal that owns composition, then delivers the composed text to the session.
|
||||
Ctrl- and Alt-modified navigation keys typed through it reach the CLI as the modified
|
||||
sequences, so word jumps and history keys keep working.
|
||||
|
||||
## Voice dictation
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ Getting Codeman onto a machine, verifying it works, updating it, and removing it
|
||||
| **macOS or Linux** | Windows works through WSL2. See [Windows](#windows-wsl) below. |
|
||||
| **Node.js 22+** | The installer offers to install it if missing. |
|
||||
| **tmux** | Not optional. Sessions live inside tmux, which is what makes them survive a server restart, a dropped connection, or a closed laptop. |
|
||||
| **An agent CLI** | At least one of [Claude Code](https://docs.anthropic.com/en/docs/claude-code), [OpenCode](https://opencode.ai), [Codex](https://developers.openai.com/codex/cli), [Antigravity](https://antigravity.google), [Gemini CLI](https://github.com/google-gemini/gemini-cli), [Pi](https://pi.dev). Plain shell sessions need none. See [Agent CLIs](Agent-CLIs). |
|
||||
| **An agent CLI** | At least one of [Claude Code](https://docs.anthropic.com/en/docs/claude-code), [OpenCode](https://opencode.ai), [Codex](https://developers.openai.com/codex/cli), [Antigravity](https://antigravity.google), [Gemini CLI](https://github.com/google-gemini/gemini-cli), [Pi](https://pi.dev), [Grok Build](https://github.com/xai-org/grok-build), [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness), [OMP](https://github.com/can1357/oh-my-pi). Plain shell sessions need none. See [Agent CLIs](Agent-CLIs). |
|
||||
|
||||
Codeman itself sends no telemetry and phones no home. The only network traffic is your
|
||||
browser to your server, and whatever the agent CLI you chose does on its own.
|
||||
@@ -20,13 +20,16 @@ browser to your server, and whatever the agent CLI you chose does on its own.
|
||||
curl -fsSL https://getcodeman.com/install | bash
|
||||
```
|
||||
|
||||
This installs Node.js and tmux if they are missing, clones Codeman into `~/.codeman/app`,
|
||||
and builds it.
|
||||
This installs Node.js, tmux and a build toolchain if they are missing (node-pty ships no
|
||||
Linux prebuild, so it compiles from source), clones Codeman into `~/.codeman/app`, and
|
||||
builds it.
|
||||
|
||||
What it asks you:
|
||||
|
||||
1. **Permission for every system change.** Package installs and agent CLI downloads are
|
||||
prompted individually. Nothing is installed silently.
|
||||
prompted individually. Nothing is installed silently. If no agent CLI is found, a menu
|
||||
offers to install any of them (DeepSeek excepted: its npm package installs only a
|
||||
launcher with no runnable profile), or you skip and install one yourself later.
|
||||
2. **How the dashboard should be reachable.** Three choices:
|
||||
- **Tailscale** (recommended for phone access): keeps the loopback bind and walks you
|
||||
through `tailscale serve`, including the tailnet HTTPS toggle, then verifies the result
|
||||
@@ -101,6 +104,21 @@ at server start, so markup changes need a restart.
|
||||
|
||||
See [Contributing](Contributing) for the rest of the development loop.
|
||||
|
||||
## Route D: Docker Compose
|
||||
|
||||
Codeman itself can run in a container and spawn Docker cases as sibling containers through
|
||||
the host's Docker socket. Copy `docker/.env.example` to `docker/.env`, set
|
||||
`CODEMAN_PASSWORD`, then:
|
||||
|
||||
```bash
|
||||
bash docker/Start-Codeman.sh
|
||||
```
|
||||
|
||||
Run the script again after updating rather than a plain `docker compose up`, so the rebuilt
|
||||
image, the refreshed volumes and the entrypoint arrive together. The full guide, including
|
||||
storage and networking options, is
|
||||
[`docker/README.md`](https://github.com/Ark0N/Codeman/blob/master/docker/README.md).
|
||||
|
||||
## Installing an agent CLI
|
||||
|
||||
Codeman drives CLIs, it does not bundle them. Install at least one:
|
||||
@@ -113,6 +131,9 @@ Codeman drives CLIs, it does not bundle them. Install at least one:
|
||||
| **Antigravity** | See [antigravity.google](https://antigravity.google) | Google's successor to the consumer Gemini CLI. |
|
||||
| **Gemini CLI** | See [github.com/google-gemini/gemini-cli](https://github.com/google-gemini/gemini-cli) | Enterprise only since Google's June 2026 consumer cutover. |
|
||||
| **Pi** | See [pi.dev](https://pi.dev) | No permission prompts and no sandbox by design. Read [Agent CLIs](Agent-CLIs) before using it on a repo you care about. |
|
||||
| **Grok Build** | `curl -fsSL https://x.ai/cli/install.sh \| bash` | xAI. Lands in `~/.grok/bin`; `grok login --device-auth` for headless hosts. |
|
||||
| **DeepSeek Harness** | `npm i -g @deepseek-ai/dsh pnpm`, then a terminal profile | The npm package is only a launcher. Codeman's Run menu installs the community terminal profile for you. See [Agent CLIs](Agent-CLIs). |
|
||||
| **OMP** | `curl -fsSL https://omp.sh/install \| sh` | Oh My Pi. Run it once by hand to finish its own onboarding. |
|
||||
|
||||
Log each CLI in once, by hand, before pointing Codeman at it. Codeman never collects or
|
||||
stores your CLI credentials.
|
||||
@@ -161,6 +182,7 @@ Full detail, including logs and the self-updater, is in
|
||||
| Installer | Re-run the one-liner, or **App Settings → System → Updates** in the UI. |
|
||||
| npm | `npm update -g aicodeman` |
|
||||
| git clone | `git pull && npm install && npm run build`, then restart. |
|
||||
| Docker Compose | Re-run `Start-Codeman.sh`. The in-app updater works too, and refuses a release that changes the container definition until you re-run the script. |
|
||||
|
||||
The in-app updater covers git-clone installs supervised by systemd or launchd. It restarts
|
||||
the process that is running it, so the actual work happens in a detached script and the
|
||||
|
||||
@@ -27,9 +27,12 @@ keystroke echo. Idle now lands a few seconds after a turn genuinely ends.
|
||||
There are several layers stacked on that: a completion message from the CLI, an AI check,
|
||||
output silence, and token stability.
|
||||
|
||||
**For every other CLI**, there are no hooks to lean on, so detection is output
|
||||
stabilization: the session is idle when output stops changing. Coarser, and it is why the
|
||||
features further down this page are Claude-only.
|
||||
**For the other CLIs** it depends on what the CLI tells Codeman. Codex declares its own
|
||||
prompt glyph and working line, so it gets the same screen check Claude does (before 1.26.1
|
||||
every Codex session reported idle for its whole life). DeepSeek Harness reports idle,
|
||||
working and blocked to Codeman itself, which is as precise as hooks. Everything else is
|
||||
output stabilization: the session is idle when output stops changing. Coarser, and it is
|
||||
why the features further down this page are Claude-only.
|
||||
|
||||
## The Respawn Controller
|
||||
|
||||
@@ -101,13 +104,18 @@ subscription plan.
|
||||
**Claude only.** A header chip showing live subscription usage, on by default on desktop and
|
||||
off on phones.
|
||||
|
||||
It works by installing a status line exporter into Claude Code, which posts Claude's own
|
||||
rate limit data back to Codeman. The exporter is marker-identified, so it only ever touches
|
||||
a status line Codeman installed, never one you wrote yourself, and it prints your footer
|
||||
through so the in-terminal status line still works.
|
||||
It works through a status line exporter that Codeman hands to `claude` as an ephemeral
|
||||
setting when it spawns the session, never written to disk, which posts Claude's own rate
|
||||
limit data back to Codeman. Your own status line (project-local, project, then
|
||||
`~/.claude/settings.json`) is wrapped and printed through, and a `claude` you run by hand
|
||||
outside Codeman sees nothing of it. Workspaces an older Codeman wrote the exporter into are
|
||||
cleaned up the first time a session starts there. Codex limits come from a read-only poll of
|
||||
its own app-server. Known limit: sessions inside a Docker case do not feed the chip yet.
|
||||
|
||||
The chip and the exporter are the same setting. Turning the chip on without the exporter
|
||||
would leave it showing a dash forever, so resolve it in one place: **App Settings**.
|
||||
would leave it showing a dash forever, so resolve it in one place: **App Settings**. A
|
||||
device writes the switch only when it flips the chip, so a phone (chip off by default)
|
||||
saving its font size cannot switch collection off for your desktop.
|
||||
|
||||
## Circuit breakers
|
||||
|
||||
|
||||
@@ -30,6 +30,9 @@ Press `Ctrl+?` in the app for the same list in a floating overlay.
|
||||
| `Ctrl+Shift+R` | Restore terminal size. |
|
||||
| `Ctrl` `+` / `Ctrl` `-` | Font size. |
|
||||
| `Shift+Wheel` | Scroll the local buffer, even where the wheel is forwarded to the CLI. |
|
||||
| `Shift+drag` | Start a selection in a pane whose mouse events go to the CLI. |
|
||||
| Right-click | Copy the selection. With nothing selected the native menu is left alone. |
|
||||
| `Ctrl+Z` | Swallowed in agent sessions so a running CLI cannot be suspended. Normal job control in a shell. |
|
||||
|
||||
## Everything else
|
||||
|
||||
|
||||
@@ -30,8 +30,12 @@ require a secure context.
|
||||
| Toolbar | Bottom: Run, Stop, **Enter**, case picker, voice, settings. |
|
||||
| Keyboard bar | Above the on-screen keyboard when it is open. |
|
||||
|
||||
Layout respects notch and home-indicator safe areas, touch targets are 44px, and the case
|
||||
picker is a bottom sheet rather than a dropdown.
|
||||
The phone layout applies up to 599px of viewport width, so the Plus and Pro Max iPhones,
|
||||
the Pixel Pro and a folded Z Fold get it too; wider devices get the tablet layout. Layout
|
||||
respects notch and home-indicator safe areas, touch targets are 44px, and the case picker is
|
||||
a bottom sheet rather than a dropdown. On a folding phone (iPhone Duo) dialogs stay clear of
|
||||
the hinge, and opening or closing the device is treated as the device changing shape, never
|
||||
as the keyboard appearing.
|
||||
|
||||
**Swipe left and right** on the terminal to switch sessions.
|
||||
|
||||
@@ -58,7 +62,9 @@ A row of keys above the virtual keyboard, and what it contains depends on the se
|
||||
|
||||
**Agent sessions** get quick actions: `/init`, `/clear`, `/compact`, a clipboard key, `Esc`,
|
||||
a path picker, an image key, and 🧠 when Read My Mind is on. Destructive commands need a
|
||||
double press, so you cannot fire `/clear` with a stray thumb.
|
||||
double press, so you cannot fire `/clear` with a stray thumb. On Codex sessions the bar also
|
||||
shows `⇧←` and `⇧→`, the Shift-modified arrows Codex binds to editing the last queued
|
||||
message and walking the prompt stack.
|
||||
|
||||
**Shell sessions** automatically swap it for terminal controls: `Ctrl`, `Esc`, `Tab`, four
|
||||
arrows, paste, and dismiss. Your normal preference is remembered and restored when you
|
||||
|
||||
@@ -33,8 +33,8 @@ reloading the dashboard while a permission dialog is blocking a session does not
|
||||
with a normal-looking tab.
|
||||
|
||||
For Claude sessions, these come from Claude Code's hooks and are precise about *why* the
|
||||
session stopped. For other CLIs there are no hooks, so you get the coarser output-based
|
||||
signal.
|
||||
session stopped; DeepSeek Harness sessions report the same states themselves. For the other
|
||||
CLIs there are no hooks, so you get the coarser output-based signal.
|
||||
|
||||
## Window title and OS notifications
|
||||
|
||||
@@ -62,7 +62,8 @@ Once subscribed, a blocking prompt reaches your phone even from a locked screen.
|
||||
|
||||
## The Approvals Inbox
|
||||
|
||||
**Opt-in, off by default. Claude sessions only.**
|
||||
**Opt-in, off by default. Claude sessions, plus DeepSeek Harness sessions, whose terminal
|
||||
front door reports its prompts to Codeman.**
|
||||
|
||||
One queue of every prompt currently waiting on a human, across all your sessions, answerable
|
||||
in place. When you have eight workers running, this is the difference between checking eight
|
||||
@@ -136,7 +137,8 @@ from the lock screen.
|
||||
- **No push over plain HTTP.** It is a browser requirement, not a Codeman one.
|
||||
- **iOS needs the home screen install.** A Safari tab will never receive push.
|
||||
- **The bell is invisible at zero.** That is deliberate, not a broken setting.
|
||||
- **Approvals are Claude-only.** They are built on hook events the other CLIs do not emit.
|
||||
- **Approvals need real signals.** They are built on hook events, which Claude emits and
|
||||
DeepSeek Harness reports itself; the other CLIs do neither.
|
||||
- **A stale menu answer is refused, not sent.** If you answer a card for a dialog that has
|
||||
since gone away, Codeman declines rather than typing a digit into the composer.
|
||||
|
||||
|
||||
@@ -67,6 +67,9 @@ one:
|
||||
| **Gemini** | Enterprise only since Google's consumer cutover. |
|
||||
| **Antigravity** | Google's successor to the consumer Gemini CLI. |
|
||||
| **Pi** | No permission prompts and no sandbox by design. |
|
||||
| **Grok Build** | xAI's CLI. |
|
||||
| **DeepSeek Harness** | Needs a terminal profile; the menu offers to install one. |
|
||||
| **OMP** | Oh My Pi, configured entirely through its own `~/.omp`. |
|
||||
| **Terminal / Shell** | A plain shell, no agent. Also the **Run Shell** button. |
|
||||
|
||||
The dropdown also lists any saved dashboard URLs ([Web Tabs](Web-Tabs)) and your recent
|
||||
|
||||
@@ -4,7 +4,7 @@ Point a case at another machine and the agent runs **there**, with the same dash
|
||||
mobile UI, and autonomy features. Your laptop becomes a window onto a session living on the
|
||||
remote host.
|
||||
|
||||
Like Docker, this is a **location overlay** on a case, not a run mode. All seven run modes
|
||||
Like Docker, this is a **location overlay** on a case, not a run mode. All ten run modes
|
||||
work remotely. See [Core Concepts](Core-Concepts).
|
||||
|
||||
## Why bother
|
||||
@@ -52,7 +52,10 @@ A watcher with bounded backoff notices a dead SSH pane and quietly reattaches to
|
||||
running remote session. On by default; the kill switch is in
|
||||
**App Settings → Agents & CLIs → Remote auto-reconnect**.
|
||||
|
||||
Intentional kills are never revived. Closing a session means closing it.
|
||||
Intentional kills are never revived. Closing a session means closing it. Neither is a clean
|
||||
exit inside the pane (Ctrl-D, `exit`, Ctrl-C at the CLI's prompt): that tears the remote
|
||||
tmux session down, and the watcher revives a session only when that durable session is
|
||||
verifiably still alive. Only a transport drop is reconnected.
|
||||
|
||||
## Discover and attach
|
||||
|
||||
@@ -70,6 +73,14 @@ Attaching to someone else's session and closing your tab must not end their run,
|
||||
not. Several clients can attach the same remote session at different window sizes without
|
||||
clamping each other, and discovery shows a shared badge with the client count.
|
||||
|
||||
## Files
|
||||
|
||||
Previews, downloads and text reads in a remote case go over the same ssh connection the
|
||||
session uses, so a clicked path opens the file on the machine the agent is on, `Range`
|
||||
seeking included. Nothing is copied to the Codeman host. Editing, Office previews,
|
||||
thumbnails, the file tree and the tail viewer are not available remotely and answer a clear
|
||||
400 rather than a misleading 404. Details in [Working With Files](Working-With-Files).
|
||||
|
||||
## Security
|
||||
|
||||
Every SSH command line in Codeman flows through one builder that shell-escapes every
|
||||
|
||||
@@ -139,6 +139,7 @@ log stream --predicate 'process == "node"' # macOS, noisy
|
||||
| Installer | Re-run the one-liner, or **App Settings → System → Updates**. |
|
||||
| npm | `npm update -g aicodeman` |
|
||||
| git clone | `git pull && npm install && npm run build`, then restart. |
|
||||
| Docker Compose | Re-run `Start-Codeman.sh`, or the in-app updater, which restarts the container in place. |
|
||||
|
||||
### The in-app updater
|
||||
|
||||
@@ -170,6 +171,18 @@ service without colliding with the main one. `CODEMAN_DATA_DIR` and `CODEMAN_TMU
|
||||
exist for the rare case where they need to differ, but setting only one of them recreates
|
||||
exactly the problem you were avoiding.
|
||||
|
||||
## Running Codeman itself in Docker
|
||||
|
||||
The Compose deployment in `docker/` runs the server in a container and spawns Docker cases
|
||||
as sibling containers through the mounted host socket. Start it with
|
||||
`bash docker/Start-Codeman.sh` rather than a bare `docker compose up`: the script pre-creates
|
||||
the bind-mounted directories with the right owner, honours a `docker-compose.override.yml`,
|
||||
and refreshes the build volumes when the checkout moved under them. The in-app updater
|
||||
applies code only and restarts by letting the container exit, so it refuses a release that
|
||||
changes the Dockerfile, the compose file, or adds a new `.env` key, until you re-run the
|
||||
script. Guide:
|
||||
[`docker/README.md`](https://github.com/Ark0N/Codeman/blob/master/docker/README.md).
|
||||
|
||||
## The tunnel as a service
|
||||
|
||||
```bash
|
||||
|
||||
@@ -67,6 +67,7 @@ be wrong for at least one of them:
|
||||
| **File Viewer** | Real path resolution before boundary checks, so symlinks cannot escape. Sensitive trees blocked. Edit mode adds an extension allowlist, a size cap, `.git` denial, and optimistic concurrency. It never creates files. |
|
||||
| **Attachments** | An id-based registry, so browser requests never carry absolute paths. The magic-link scanner is prompt-injectable by nature and is therefore force-confined to the session's workspace. Extension allowlist, not a blocklist. |
|
||||
| **Path picker** | Its own root allowlist rather than the workspace confinement. In multi-user mode a non-admin gets only their own user space, because per-user spaces live inside the home directory. |
|
||||
| **Remote cases** | Reads go over the session's own ssh connection and are resolved and contained on the remote host, with a bounded number of ssh children. Nothing is copied to the Codeman host; writes, Office previews and thumbnails are refused. |
|
||||
|
||||
Downloads block sensitive paths outright (`.env`, credentials files, `~/.ssh`, AWS
|
||||
credentials), and SVG and HTML are served as downloads with `nosniff` so they cannot execute
|
||||
|
||||
@@ -46,6 +46,7 @@ supervised by systemd or launchd; npm installs report as non-updatable. See
|
||||
| Extended Keyboard Bar | Per device | Which accessory bar phones get. Shell sessions override it while they are active. |
|
||||
| Wheel Scrolls Local History | Off | Keeps the wheel on the local buffer instead of forwarding it to the CLI. |
|
||||
| Auto Copy Selection | Off | Copies highlighted terminal text to the clipboard the moment you finish selecting it. Ctrl+C still copies on demand. |
|
||||
| Normal / Bold font weight | xterm defaults | Per device, each slot from 100 to 900. The bundled JetBrains Mono renders every step, so a lighter normal weight makes Claude's bold headings stand out. Applies live to the terminal, both echo overlays and open team panes. |
|
||||
| WebGL Renderer | On | With a GPU-stall watchdog that falls back to DOM rendering. |
|
||||
| Gesture Control | Off | Camera hand tracking. Also needs `CODEMAN_GESTURE=1` on the server. |
|
||||
|
||||
@@ -72,7 +73,9 @@ every session or only the active tab.
|
||||
| Entrance Animations | Per-surface animation styles for tabs, terminals, windows, and lineage lines. All default to the legacy no-animation behaviour. |
|
||||
| Display Name | Your name in the UI. Cosmetic only; it never renames the package, CLI, API, or storage. |
|
||||
| Interface Language | English or Simplified Chinese. Per device. |
|
||||
| Session List Layout | Header tab strip (default) or a collapsible left sidebar. See [The Dashboard](The-Dashboard#session-list-layout). |
|
||||
| Session List Layout | Header tab strip (default), a collapsible left sidebar, or the sidebar with detailed rows. See [The Dashboard](The-Dashboard#session-list-layout). |
|
||||
| Tab Orientation | Keeps the header list but turns the strip vertical beside the terminal, resizable, with detailed rows by default. Desktop and tablet only. |
|
||||
| Vertical Rail Order | *By activity* (default) sorts the rail the way the home screens are sorted; *Manual* keeps your tab order and drag-reordering. |
|
||||
| Tall Tabs | Taller tab strip. |
|
||||
| Pop-out Button on Tabs | Adds the detach control to tabs, with a per-tab override. |
|
||||
| Spawn Lineage Lines | Arcs from a parent tab to sessions it spawned. Desktop only, on by default. |
|
||||
@@ -156,6 +159,9 @@ Some things are configured before the server starts, not in the UI:
|
||||
| `CODEMAN_DOCKER_BRIDGE_HOOKS` | Lets in-container hooks reach the host on a loopback bind. |
|
||||
| `CODEMAN_FILE_PICKER_ROOTS` | Extra roots for the path picker. |
|
||||
| `CODEMAN_ALLOW_UNAUTHENTICATED_NETWORK` | Acknowledges exposing the server with no password. |
|
||||
| `CODEMAN_BASE_URL` | Mounts Codeman under a sub-path behind a reverse proxy that forwards the prefix unchanged. See [Remote Access](Remote-Access). |
|
||||
| `CODEMAN_MAX_DOWNLOAD_BYTES` | Cap on raw file bodies and downloads. 2 GB by default, `0` for none. |
|
||||
| `CODEMAN_MAX_REMOTE_FILE_SSH` | Concurrent ssh reads for files in remote cases. 4 by default. |
|
||||
|
||||
## Gotchas
|
||||
|
||||
|
||||
@@ -22,12 +22,14 @@ page says so and names the setting.
|
||||
|
||||
The session list lives in the header as a horizontal strip by default. With a lot of
|
||||
sessions open that strip stops being scannable, so **App Settings → Appearance → Tabs →
|
||||
Session List Layout** can move it into a vertical sidebar on the left instead.
|
||||
Session List Layout** can move it into a vertical sidebar on the left instead, and
|
||||
**Tab Orientation** can turn the strip itself into a vertical rail.
|
||||
|
||||
| Layout | Behaviour |
|
||||
| -------------------- | --------------------------------------------------------------------------------- |
|
||||
| **Header tab strip** | The default. Wraps to a second row on desktop, scrolls sideways on a phone. |
|
||||
| **Left sidebar** | A vertical list with a filter box and a live session count. `Alt+B` collapses it to a narrow rail that keeps the status dots and task badges visible. On a phone it is an off-canvas drawer rather than a docked rail. |
|
||||
| **Left sidebar** | A vertical list with a filter box and a live session count. `Alt+B` collapses it to a narrow rail that keeps the status dots and task badges visible. On a phone it is an off-canvas drawer rather than a docked rail. A detailed variant adds the home screen's per-session line (`created 3d ago · working 12m`) and a status pill. |
|
||||
| **Vertical rail** | The strip turned vertical beside the terminal, resizable, with detailed rows by default. **Vertical Rail Order** sorts it by activity (blocked on you first, then longest running, then most recently quiet), the same order as the home screens; pick *Manual* to get your own order and drag-reordering back. Desktop and tablet only. |
|
||||
|
||||
It is the same list either way, just re-hosted: tab order, drag-to-reorder, the `Alt+1`
|
||||
to `Alt+9` numbers and every status colour below behave identically in both. The setting is
|
||||
@@ -154,6 +156,10 @@ Worth knowing:
|
||||
always local scrollback. Other CLIs scroll locally.
|
||||
- **Selection copy.** `Ctrl+C` copies when text is selected and interrupts when it is not.
|
||||
`Ctrl+Shift+C` always copies.
|
||||
- **Selecting where the CLI owns the mouse.** `Shift+drag` starts a selection even in a pane
|
||||
whose mouse events are forwarded to the CLI, and right-click copies the selection (with
|
||||
nothing selected the native menu is left alone). **Auto Copy Selection** in App Settings
|
||||
copies the moment you release.
|
||||
- **Zero-lag input.** On touch devices, keystrokes paint locally before the round trip. See
|
||||
[Input And Voice](Input-And-Voice).
|
||||
- **Renderer.** WebGL by default, with a watchdog that falls back to DOM rendering if the
|
||||
@@ -167,8 +173,9 @@ which lists past sessions including Claude conversations started outside Codeman
|
||||
|
||||
Two extras depending on the device:
|
||||
|
||||
- **Desktop, wide windows**: your open tabs appear as a rail docked to the left edge, in tab
|
||||
order, with created and last-active stamps. It needs at least 1180px of width; below that
|
||||
- **Desktop, wide windows**: your open tabs appear as a rail docked to the left edge, in
|
||||
overview order (blocked on you first, then longest running, then most recently quiet),
|
||||
with created and state-duration stamps. It needs at least 1180px of width; below that
|
||||
it is hidden so it cannot overlap the search panel.
|
||||
- **Phones**: tapping the "C" logo gives a session overview instead: NEEDS YOU first, then
|
||||
current sessions, then past ones. On by default.
|
||||
@@ -204,7 +211,9 @@ so it is fast and cannot be turned into a traversal.
|
||||
## Appearance
|
||||
|
||||
**App Settings → Appearance** carries the theme skins, including light ones. The choice is
|
||||
applied before the first paint, so there is no flash of the wrong theme on load.
|
||||
applied before the first paint, so there is no flash of the wrong theme on load. Terminal
|
||||
font family and weight are per device too: a normal and a bold weight, each from 100 to
|
||||
900, and the bundled JetBrains Mono renders every step.
|
||||
|
||||
The same section has the entrance animations for tabs, terminals, agent windows, and
|
||||
lineage lines. All of them default to the legacy no-animation behaviour, so an untouched
|
||||
|
||||
@@ -138,6 +138,12 @@ That is the PTY-exit circuit breaker. Repeated rapid PTY exits trip it, and it b
|
||||
automatic restarts so a broken configuration does not spin forever. Reset it explicitly from
|
||||
the session's controls. Reattaching does not clear it, deliberately.
|
||||
|
||||
### Typed prompts are silently ignored after restoring a tab
|
||||
|
||||
Update. A browser whose input sequence counter fell behind the server's (a restored tab,
|
||||
cleared site data) used to have every prompt deduplicated away. Since 1.29.0 the duplicate
|
||||
acknowledgement carries the watermark and the client re-sends.
|
||||
|
||||
### Sessions I did not create appeared, or my session resized itself
|
||||
|
||||
Two Codeman servers are running against the same data directory and tmux socket. The second
|
||||
@@ -167,6 +173,16 @@ Things to try:
|
||||
Codex ignores the mouse reports that forwarding would send, so Codeman does not forward
|
||||
there. Scrolling is local, and `Shift+Wheel` behaves the same way.
|
||||
|
||||
### Selected text is invisible on a light skin
|
||||
|
||||
Update. Every skin named its selection colour under a key xterm renamed in v5, so the four
|
||||
light skins painted white at 30% over near-white. Fixed in 1.29.0.
|
||||
|
||||
### `Ctrl+Z` suspended my agent
|
||||
|
||||
Update. Since 1.28.0 `Ctrl+Z` is swallowed in agent sessions, so a running CLI cannot be
|
||||
stopped by job control. Shell sessions keep it.
|
||||
|
||||
### `Ctrl+C` copies when I wanted to interrupt
|
||||
|
||||
With a selection, `Ctrl+C` copies. With no selection, it interrupts. Clear the selection
|
||||
@@ -252,11 +268,25 @@ node scripts/build-agent-image.mjs --no-cache
|
||||
A plain rebuild reuses the cached `npm install -g` layer and keeps the CLIs frozen at their
|
||||
original versions while reporting success.
|
||||
|
||||
### Every file in a remote case says "File not found"
|
||||
|
||||
Update. Before 1.29.0 the file routes resolved every path on the Codeman host, so in a
|
||||
remote case every click failed while the file plainly existed on the other machine. Reads
|
||||
now go over ssh; see [Working With Files](Working-With-Files). Editing and Office previews
|
||||
stay unavailable remotely and say so with a 400.
|
||||
|
||||
### Compose: the server crash-loops with `EACCES` on first start
|
||||
|
||||
Start the stack with `bash docker/Start-Codeman.sh` rather than a plain `docker compose up`,
|
||||
and update: since 1.29.0 the entrypoint corrects a root-owned bind mount before dropping
|
||||
privileges. See [Running As A Service](Running-As-A-Service).
|
||||
|
||||
### A remote SSH session dropped and did not come back
|
||||
|
||||
A bounded-backoff watcher reattaches dropped sessions, and it is on by default. Intentional
|
||||
kills are never revived. Check the host is reachable and that the remote tmux server is
|
||||
still running.
|
||||
kills are never revived, and neither is a clean exit inside the pane (Ctrl-D, `exit`): only
|
||||
a transport drop is reconnected. Check the host is reachable and that the remote tmux server
|
||||
is still running.
|
||||
|
||||
## Gathering diagnostics
|
||||
|
||||
|
||||
@@ -24,6 +24,23 @@ Switching tabs does not reload a dashboard. Frames stay alive in the background,
|
||||
took a while to authenticate is still there when you come back. Past six live frames, the
|
||||
least recently viewed is dropped to bound memory.
|
||||
|
||||
## Single-page apps, reloads and links
|
||||
|
||||
A history-routed dashboard (React Router, Vue Router, a Vite dev server) sees the path it
|
||||
would see on its own origin, not the proxy prefix, so it renders its real route instead of
|
||||
its own "page not found". A navigation the page starts itself afterwards, a dev server's
|
||||
full reload or a root-absolute `location.href`, would land outside the proxy with no
|
||||
capability; Codeman recognises it, answers with a small recovery page, and remounts the
|
||||
frame at the path that was lost, bounded to five recoveries a minute per frame. A reload on
|
||||
the dashboard's landing page is recovered the same way.
|
||||
|
||||
A `localhost` or `127.0.0.1` link in agent output opens as a web tab automatically, reusing
|
||||
a saved dashboard for the same server or saving one under its `host:port`. On a phone that
|
||||
address only exists on the Codeman box, so the link would otherwise be a guaranteed
|
||||
connection error. LAN and tailnet addresses still open directly. `*.localhost` names are
|
||||
deliberately not auto-routed: they are DNS names rather than address literals, and the link
|
||||
came from agent output. Add such a dashboard by hand instead.
|
||||
|
||||
## Why dashboards are proxied
|
||||
|
||||
A plain cross-origin iframe fails three ways at once in the setup Codeman actually ships in:
|
||||
@@ -89,6 +106,12 @@ The proxy authenticates on an in-memory capability embedded in the path, which i
|
||||
exempt from the cookie and Origin checks that every API route enforces. That exemption is
|
||||
fenced to safe methods and non-API paths, and there is a test pinning it in place.
|
||||
|
||||
Saved URLs are refused when they point at a link-local or cloud-metadata address, at save
|
||||
time and again against the address the name resolves to at connect time; loopback and
|
||||
private ranges stay allowed, because a `localhost` Grafana is the feature. Capabilities are
|
||||
revoked on logout, and proxied responses carry a same-origin referrer policy so a dashboard
|
||||
cannot hand the capability-bearing URL to a third party.
|
||||
|
||||
Two failure modes that only appear inside a sandboxed frame, and that curl can never
|
||||
reproduce, are handled: runtime-built root-absolute URLs escaping the injected base, and
|
||||
same-host requests being CORS-checked with a null origin. Both present as the dashboard's own
|
||||
|
||||
@@ -110,6 +110,22 @@ it is written. Outside the workspace they open in the preview instead: the tail
|
||||
|
||||
Nothing is registered until you click. Opening a file this way does not add an attachment card.
|
||||
|
||||
## Remote (SSH) cases
|
||||
|
||||
In a remote case the workspace lives on the other machine, and so do the files. Previews,
|
||||
downloads, text reads and the clicked-path route all go over the same ssh connection the
|
||||
session uses: one `realpath` plus `stat` probe for the file and the workspace root, then a
|
||||
streamed `cat` (or a slice of it, so video seeking works). Symlinks are resolved on the host
|
||||
that can resolve them, the size cap applies to the remote size before a byte is requested,
|
||||
and an unreachable host answers 502 rather than pretending the file is missing. Nothing is
|
||||
ever copied onto the Codeman host, and a same-named local file is never served under a
|
||||
remote name.
|
||||
|
||||
Not available over ssh, and said so with a 400 instead of a misleading 404: editing in
|
||||
place, Office previews and generated thumbnails (both need the bytes on the server's disk),
|
||||
the file tree and path picker, and the tail viewer. Docker cases are unaffected, because
|
||||
their workspace is bind-mounted at the same path.
|
||||
|
||||
## The path picker
|
||||
|
||||
For choosing a path rather than typing one. It appears in two places:
|
||||
|
||||
Reference in New Issue
Block a user