Skip to main content
The terminal driver drives any interactive TUI, but two coding CLIs are supported first-class: Claude Code (Anthropic) and OpenAI Codex. The agent operates them the way a developer does — launches the interactive CLI, gives it a task, answers its prompts, and verifies the result — inside the operator-controlled sandbox. A CLI is “first-class” when it has all three pieces below. Adding a third (aider, gemini-cli, …) is a drop-in profile + skill with no engine change — see Adding a platform.

How it works — three layers

The skill and profile ship with Comis; your only job is the sandbox — one allowlist entry per CLI, plus installing and authenticating the CLI on the host. The profile is read-side only: it never widens the jail or the launch — that stays your allowlist entry.

Prerequisites (once, per host)

1

Install the CLI as the service user

Install Claude Code / Codex for the user the daemon runs as (the standard install puts the binary at ~/.local/bin/claude / ~/.local/bin/codex).
2

Authenticate it OUTSIDE the jail

Run claude / codex login as the service user once so credentials are written to ~/.claude / ~/.codex. The driver never logs a CLI in — an unauthenticated CLI escalates to you. Under filesystem: home those dirs are bound read-write, so the CLI refreshes its own token across drives.
3

Accept the first-run gates once

Launch the CLI once by hand and clear its startup gates — Claude Code’s “trust this folder” prompt and, under --permission-mode bypassPermissions, the “Bypass Permissions” warning (whose default highlight is “No, exit”, so a reflexive Enter quits). Once accepted, the state is recorded in ~/.claude.json (bound RW), so later drives open straight to the prompt.

Claude Code

Why these settings
  • filesystem: home — Claude Code is home-installed (~/.local/bin/claude~/.local/share/...), which filesystem: workspace cannot exec; and it writes ~/.claude (session state + OAuth refresh), which a read-only credentialPaths bind would block.
  • argsPrefix pins --permission-mode bypassPermissions — the agent drives an allowlisted command, so pinning the permission mode in the operator entry means the agent can never select a weaker/different mode. The jail (uid/network/~/.comis mask) is the real boundary, not Claude’s own permission prompts.
  • uid: daemon — Claude’s creds under ~/.claude are owned by the daemon user; running as that uid lets it read/refresh them.
How the agent drives it — the agent calls terminal_session_create({ allowId: "claude", command: "claude", project: "<short-kebab-name>" }) (the argsPrefix is prepended automatically), then drives the session per the bundled skill. The project opens a persistent, retrievable folder ~/.comis/workspace/projects/<name> — see Per-project folders. The claude-code profile makes the perception clean:
  • Render — strips Claude’s dim autocomplete “ghost-text” from the captured screen, so the driving model never mistakes a suggestion (e.g. commit this) for queued input.
  • Perception — Claude’s spinner reads working; a /model-style picker reads awaiting-input (not stuck).
  • Dialogs — the “trust this folder” gate is answered with the safe keystroke under autoAnswer: safe-only; any destructive/approval prompt always escalates.
Claude Code’s Bash tool inside the jail. Claude wraps each Bash-tool command in a second bubblewrap that remounts $HOME read-only — which would break its per-command state dir. The driver handles this automatically (a writable tmpfs carve-out at ~/.claude/session-env); no configuration needed. Details: Nested sandboxes.

OpenAI Codex

Why these settings
  • --dangerously-bypass-approvals-and-sandbox — Codex would otherwise start its own nested sandbox (landlock/seccomp) and per-command approval prompts. Nested inside this driver’s bwrap jail, Codex’s sandbox fails to initialize (bwrap: loopback … not permitted / seccomp/landlock … not supported). The flag disables Codex’s redundant layer — Comis’s jail is the sandbox. Without it, a driven Codex session dies at startup.
  • filesystem: home — same as Claude: a home-installed binary plus a writable cred/state dir (~/.codex).
  • autoAnswer: safe-only — Codex’s run-command approval overlay is declared destructive in the codex profile, so it always escalates to you and is never auto-answered.
How the agent drives itterminal_session_create({ allowId: "codex", command: "codex", project: "<name>" }). Use Codex when you specifically want it; otherwise the agent prefers Claude Code for general coding. The codex profile — perception only (Codex’s Working (Ns) line reads working; the /model picker reads awaiting-input); the run-command approval is the escalate-always dialog above. Codex has no /context command (its /status is the usage view), and the skill exits with /quit.

The bundled skills

The agent’s “how to drive it” knowledge ships as two markdown skills, seeded on boot to ~/.comis/skills/claude-code/ and ~/.comis/skills/codex/ (re-seeded when the bundled version changes). The agent auto-discovers them by description (progressive disclosure) and loads the right one for the task — no per-agent skill config is required. Each teaches:
  • Launch + named project folders — always pass project: "<name>" for retrievable, parallel-safe work.
  • In-session slash commands — the ones a developer uses: /compact (free context on a long build), /model (a picker — navigate with arrows/number + Enter), /status, /diff, /clear (⚠️ wipes), etc.
  • Completion detection + verification — read the screen, require a stable idle prompt, then verify the tests actually passed (never assume success).
  • Ghost-text rule — in a driven session the agent is the sole input source, so any text it didn’t type is the CLI’s autocomplete suggestion — ignore it, never act on it.

Autonomous Builds

Hand the agent a design doc → it drives Claude Code through GSD to build it, phase by phase

Terminal Driver

The full driver reference — tools, sandbox scope, durability, platform profiles

Tool Policy

Control which tools each agent can use