typed

typed CLI

The first-party coding agent CLI for typed.cloud. It runs the agent loop -- read, search, edit, run, verify -- in your terminal, against your own codebase, on your typed subscription.

The native protocol is the Anthropic Messages API, so the CLI works against typed.cloud by default and against any Anthropic-API-compatible endpoint if you point ANTHROPIC_BASE_URL elsewhere. It honors the same configuration surfaces as the reference CLI (Claude Code) -- CLAUDE.md, settings.json permission rules, skills, hooks, .mcp.json -- so an existing setup carries over without rewriting anything.

The typed CLI is the default client for new installs (apps/api/src/routes/launcher-version.ts advertises rollout.default_client = 'typed-cli' and the installer's setup_typed_cli writes ~/.config/typed/client = typed-cli on a successful install). Claude Code against typed.cloud remains fully supported; you can switch between the two clients at any time (see Install below).

Install

One curl installs the typed launcher with your API key wired in (the dashboard at app.typed.cloud pre-fills the command with your key):

curl -fsSL https://app.typed.cloud/install.sh | bash -s <your-typed-key>

By default typed and t launch the first-party CLI pointed at typed.cloud. Switch back to the reference client (or print the current state) with:

typed cli on       # default -- the launcher starts the first-party CLI
typed cli off      # back to the reference client
typed cli          # print the current state

(typed tui on|off is an interchangeable alias for typed cli on|off and still works. typed beta on|off is a deprecated alias for the same thing, still working for now.)

The opt-in is a one-line file at ~/.config/typed/client; nothing else about your setup changes, and typed cli off reverts it completely.

Quickstart

typed login       # browser device-auth; writes ~/.config/typed/api-key
t                 # start a session in the current project directory

Once you are in a session:

  • Type a task and press Enter.
  • Press ? on an empty input line (or run /help) for the one-screen help overlay: built-in commands, your discovered skills, key bindings, and how the permission gates work.
  • Ctrl+C interrupts the current run (twice within 1.5s exits); Ctrl+D exits; Tab completes / commands; Up/Down walk input history.

The status line at the bottom shows the model tier, the run state, live session spend in dollars (real spend reported by the server, not an estimate), token counts, and the prompt-cache hit rate.

The everyday surface

Tools

Read (text and images), Write, Edit, Grep, Glob, Bash, PowerShell (Windows), WebFetch, WebSearch, Agent (subagents for self-contained delegated tasks), and a model-driven progress list rendered in the footer. MCP servers from .mcp.json (stdio) register their tools as mcp__<server>__<tool>.

Permission gates

Tool calls that can mutate state are gated before they run. The engine is fully deterministic -- rules only, no model in the loop -- so a denial is reproducible and names the exact rule that produced it.

At a gate: y allows once, n denies, and a (when offered) allows always -- writing a CC-syntax allow rule (for example Bash(git status*)) to .claude/settings.local.json so that shape never gates again in this project. Destructive-class gates require Enter rather than a single key. Rules use the same allow / deny / ask arrays and Tool(prefix*) syntax as the reference CLI.

Auto mode

For unattended or long-running sessions, auto mode skips the per-prompt gate for mutating tools and fires the same a path the interactive a key does -- deriving a CC-syntax allow rule from the call, evaluating it, and running the tool. Each auto-fired decision is committed to the scrollback as + auto: <ToolName> (<rule>) so the session log shows exactly which rules the model self-allowed against.

Opt in three ways:

Surface Shape Effect
Startup flag typed --auto session-scoped auto mode; rules live only in memory and are lost on exit
Startup flag typed --auto --auto-persist session-scoped auto + write each new allow rule to .claude/settings.local.json as it fires
In-session /auto toggle auto mode on or off in the current session
In-session /auto persist turn the current session's auto mode into the persisting variant (sticky)

The status line shows an [auto] chip when auto is on, so it is visible at a glance. Auto mode does not bypass deny rules -- the engine still rejects any call that matches an explicit deny. Headless runs pick it up via --permission-mode auto; the headless default behavior (deny gated calls) is unchanged for default / accept-edits / readonly.

Built-in commands

Command What it does
/help (or ? on an empty line) one-screen help overlay
/undo restore every file the session has written, from per-session shadow snapshots taken before the first write to each file (works on dirty trees; no git required)
/compact summarize older history to free context (auto-compaction also triggers at a threshold)
/show <id> print the full output of a truncated tool result
/status session state: model, spend, config sources
/auto [on|off|persist] toggle auto mode (or set the persisting variant); see Permission gates above
/exit leave the session

Resuming work

typed --continue        # resume the most recent session for this directory
typed --resume <id>     # resume a specific session (id prefix ok)
typed --resume          # list available sessions for this directory and pick one

Sessions are JSONL transcripts stored per project directory (see Env vars below).

Subcommands

typed login | logout        # device-auth key management
typed use <tier> [--global] # pin a model tier (.typed file, or ~/.config/typed/model)
typed status                # offline: resolved config + key source
typed doctor                # probe the backend, key, and config for the common traps
typed ultracode [on|off]    # multi-agent orchestration mode (Pro tier and up)
typed update                # self-update: re-runs the installer; ~/.config/typed is preserved
typed codebase <verb>       # hosted codebase indexing (Team tier); see below

typed doctor is the first thing to run when something is off: it checks the key source, the model pin, the well-known env traps, and probes the service, printing [ok] / [warn] / [FAIL] lines with a one-line fix for each failure.

Hosted codebase indexing

Team / Team Max only. typed indexes an uploaded snapshot of your repository and retrieves from it on every turn, so the model can cite files that were never in the conversation. On any other plan these commands return the API's own upgrade payload, including the link.

typed codebase push [path]            # pack, upload, index; defaults to the cwd
typed codebase list                   # every codebase in your org
typed codebase status <id>            # one codebase, with its failure reason
typed codebase rm <id> [--yes]        # delete it (indexed chunks and archive too)

push packs the tree with .gitignore (and .typedignore, same syntax) honored and .git excluded, then drives create -> upload -> finalize and polls until the index is ready or failed, printing each step. It refuses before uploading if the archive is over the server's size limit, naming the limit and the actual size. On success it prints the codebase id and the line that attaches it:

typed --codebase <id>

That flag is a session flag: every turn of the session carries the codebase, and a startup note names the one it is attached to. When the backend answers that a turn could not use the index -- still indexing, indexing failed, or retrieval briefly unavailable -- the CLI says so rather than letting the answer look codebase-informed. The flag has no effect on the free local tier, where inference never leaves your machine; the session says that at startup instead of sending a header nothing will read.

What is never uploaded

Your ignore files are advisory, and the archive is retained in storage after indexing -- so push refuses credential-shaped files outright, whether or not you remembered to ignore them:

  • Credential filenames, by exact name, family prefix, or suffix: .env and every .env.*, .npmrc / .yarnrc (registry auth), .netrc, .pgpass, credentials, credentials.json, service-account.json, secrets.*, id_rsa and siblings, and *.pem / *.key / *.p12 / *.jks / *.gpg. Public certificates (*.crt, *.pub) are not treated as secrets.
  • Dotfiles you have not opted in, allowlisted down to declarative config (.gitignore, .editorconfig, .nvmrc, .tool-versions, the .eslintrc / .prettierrc families, .typedignore). .env.example is not on that list.
  • Any file whose contents look secret-bearing regardless of its name -- an api key, an AWS access key id, a JWT, a PEM private-key block, or a password-style assignment with a key-like value. The whole file is skipped; nothing is redacted and re-packed.

push names every file it withheld and why, before it uploads. Paths are printed so you know what is missing from the index; contents never are.

This cannot be overridden. An ignore file only excludes, it cannot re-include, and the server applies the same rules again after unpacking. If you genuinely need one of these files indexed, take the credential out of it first.

rm is irreversible (it wipes the indexed chunks and the uploaded archive), so it asks you to type the id back unless you pass --yes.

The full endpoint contract, the status lifecycle, and the retention policy are documented for Team customers in the dashboard.

Headless mode

For scripts and CI:

typed-cli -p "fix the failing test in src/foo.test.ts" --output-format json

--output-format text prints the final answer; json prints a single result envelope on stdout:

Field Meaning
type, subtype "result", "success" or "error"
is_error boolean
result final assistant text (or the error message)
num_turns turns used
duration_ms, duration_api_ms wall time and time spent in API calls
total_cost_usd real spend on typed backends; null when unknown
usage input_tokens, output_tokens, cache_read_input_tokens, cache_creation_input_tokens
api_error_status HTTP status when an API error ended the run (optional)
session_id id of the session transcript

Other flags: --model, --effort (maps to a typed tier when no explicit model is set), --max-budget-usd (stop when estimated spend exceeds the budget), --append-system-prompt-file, --permission-mode default|accept-edits|readonly|bypass|auto (alias --auto; add --auto-persist to write each new allow rule to .claude/settings.local.json as it fires), --tools <list>, --cwd <dir>, --codebase <id> (attach a hosted codebase index -- Team tier; see Subcommands above).

Headless runs never prompt: gated tool calls are denied (the model is told why) unless you pass --permission-mode bypass. Hooks run headless only when the project already has a trust record granting them, or TYPED_CLI_TRUST_HOOKS=1 is set.

Configuration surfaces

The CLI reads the same project configuration the reference CLI does:

Surface Support
CLAUDE.md (user, project, .claude/, CLAUDE.local.md) full, including @import lines
AGENTS.md (the client-neutral convention: root and ancestor directories) full; loaded alongside CLAUDE.md, identical copies deduped. Files below the start directory are not read
settings.json permissions (allow / deny / ask) full, same rule syntax; project settings.json + settings.local.json + user settings merge additively
.claude/skills/<name>/SKILL.md and .claude/commands/<name>.md full; discovered skills appear in / autocomplete and the ? overlay
.agents/skills/**/SKILL.md (project and ~/.agents/skills, the Agent Skills standard) full; grouping folders scanned 4 levels deep, linked skill dirs followed, spec frontmatter (license, compatibility, metadata, allowed-tools, disable-model-invocation) read, spec violations warned about and loaded anyway
.claude/agents/*.md full (name, description, tools, model frontmatter)
hooks (PreToolUse, PostToolUse, UserPromptSubmit, Stop, SessionStart, PreCompact, SubagentStop, SessionEnd, Notification) full for these nine events; same stdin-JSON and exit-code semantics
.mcp.json (stdio servers) full; project-scope servers are trust-gated
CLAUDE_CONFIG_DIR honored everywhere ~/.claude would be used

Skills the model can pick itself. Every skill with a description is listed for the model at session start as an Agent Skills catalog (name, description, and the absolute SKILL.md path), and the model loads one by reading the file when a task matches. The catalog is budgeted like CLAUDE.md (5% of the window, 4,096 chars, project skills kept first when it has to cut) and is left out entirely on windows of 16K tokens or less, when the session has no Read tool on the wire (the free local tier before its server proves tool calls), and for project skills in a headless run without an explicit trust grant (TYPED_CLI_TRUST_PROJECT=1 or a saved decision). Every omission is a startup note, and the catalog notes are also written to stderr in headless runs. A skill the model or you activated is named again after /compact, with an instruction to re-read it. disable-model-invocation: true keeps a skill slash-only; a skill whose name shadows a built-in command stays in the catalog but loses its slash command.

First-run trust: the first time you run the CLI in a project that ships any of this config, it shows what it found and asks before using it. Hooks are opt-in -- they execute arbitrary commands, so they never run silently. Decisions are remembered per project.

Env vars

Variable Effect
ANTHROPIC_BASE_URL backend endpoint (default https://api.typed.cloud)
ANTHROPIC_AUTH_TOKEN / ANTHROPIC_API_KEY / TYPED_API_KEY API key; falls back to ~/.config/typed/api-key
ANTHROPIC_MODEL model / tier (default typed, the free local tier -- pick a typed++ id to reach the hosted tiers)
CLAUDE_CONFIG_DIR overrides ~/.claude for config discovery
TYPED_VERIFY_CYCLE_CAP verification-cycle cap: how many times the loop allows the model to repeat an identical check (same command, same file read) without making a change before steering it onward. Default 2; 0 disables
TYPED_NO_UPDATE_CHECK=1 disable the background version check entirely
TYPED_CLI_STATUS_FD file descriptor number; when set, the CLI emits one JSON status event per line on that fd (session, turn, state, tool, usage, error, done) for host integrations such as terminal UIs
TYPED_CLI_SESSIONS_DIR session transcript root (default ~/.config/typed/sessions); transcripts live under a per-project subdirectory
TYPED_CLI_MEMORY_DIR persistent per-project memory root (default ~/.config/typed/memory)
TYPED_CLI_TRUST_HOOKS=1 headless only: run hooks without an interactive trust grant
TYPED_CLI_TRUST_PROJECT=1 headless only: treat the project as trusted for project-scope MCP servers and the model's skill catalog
TYPED_CLI_SKILL_ALLOWED_TOOLS=1 opt-in: /name on a skill in a trusted project arms its allowed-tools frontmatter as session allow rules when the run starts (a queued invocation arms nothing until it runs; in an untrusted project a line says the rules were not armed) the permission engine consults last (after your deny, allow and ask rules; ignored in readonly and plan). Each armed rule is committed to the scrollback as + allow for this session (skill <name>): <rule>; an entry the engine cannot evaluate is refused with a ! line, never armed dead. Nothing is written to disk
TYPED_CLI_COMPACT_THRESHOLD auto-compaction threshold in estimated tokens
TYPED_CODEBASE_POLL_MS typed codebase push poll interval while the index builds (default 3000)
TYPED_CODEBASE_POLL_TIMEOUT_MS how long typed codebase push waits before handing back (default 900000); the indexer keeps going either way
TYPED_INSTALL_URL installer URL used by typed update
TYPED_CLIENT one-shot launcher override (typed-cli or the reference client) without touching the typed cli state

Resilience details worth knowing

  • Stall watchdog: every streamed response runs under two timers -- a byte-idle timer and a content-progress timer (keepalive pings do not count as progress). A content-silent stall is aborted and retried once before surfacing an error.
  • Quota: when a request exceeds your monthly quota, the error rendered in the CLI includes the remediation path (one-click top-up, or enable auto-top-up in the dashboard) instead of a dead error string.
  • Verification cap: repeated identical verification commands within one edit cycle are short-circuited with guidance rather than executed again -- this is the measured fix for verify-loop runaway and is on by default (see TYPED_VERIFY_CYCLE_CAP).
  • Comments while a run is in flight: a comment typed while the model is streaming redirects it immediately -- the partial answer is kept, the comment is appended, and the same turn is re-sent (up to 10 redirects per model turn; after that the remaining comments start a fresh prompt). A comment typed during tool calls interrupts read-only and idempotent calls and subagents, lets a mutating call finish, skips the rest of that batch with a "not run" result, and lands right after the tool results -- the footer chip shows (after <tool>) while it waits. The chip counts only comments the model has not received yet. Every delivered comment gets a /rewind checkpoint. Ctrl+C parks the queue; the next submit merges the backlog in the order you typed it.
  • Hook-blocked prompts stay visible: a UserPromptSubmit hook that blocks a comment does NOT drop it. A ! prompt blocked by hook: <reason> line commits under the blocked item, the footer swap-in shows it as [blocked: <reason>] with red text, and the drain continues to the next pending item. Blocked items persist for the rest of the session -- remove them with /queue-cancel <n> or let them die with /exit. The queue cap is 100; the 101st submit is dropped with a ! queue full (N) -- submission dropped line. Use /queue to see the visible queue at any time.

Support

Run typed doctor first; it diagnoses the common setup traps with a fix line per failure. If you are still stuck, email support@typed.cloud with your account email, the doctor output, and the approximate UTC timestamp of the failed request.