xx
minimal unix coding harness
curl -fsSL xx.sh | sh~/.config/xx isn't mounted in the container, so a write there wouldn't reach your machine. I'll stage it under ~/dev for you to move.~/dev/config (executable program command, runs on the host). Move it into place:mkdir -p ~/.config/xx/commands && mv ~/dev/config ~/.config/xx/commands/config/config prints the path and contents of ~/.config/xx/xx.conf (honours $XDG_CONFIG_HOME); exits non-zero with a message if the file doesn't exist. Commands are picked up live, no restart needed.xx (pronounced "kiss kiss") is a unix-flavored coding harness. it starts instantly, runs in a container, ships as a single binary, suppresses thinking and tool output, and extends via programs instead of plugins. it barely has any features and that's the way we like it.
features
small & fast
xx ships on mac and linux as a single <1MB binary that starts instantly - perfect for pipelines or quickly launching sessions:
like other harnesses, -p runs and exits, printing agent output to stdout while tool calls go to stderr. --json is like -p but streams agent actions as json to stdout, tool calls to stderr.
sandboxed
i once had an agent get confused and run rm -rf ~, so... yeah. xx runs every bash call in a long-lived linux container (via container on apple and podman on linux) which can only access specific paths on your host machine. by default it's ~/dev and ~/.rev, but you can change them or add more.
think of it as a safety net, not a security system: the goal is to prevent agents from accidentally running shell commands that impact your host system, not protection against rogue or malicious models.
to run xx directly on your host computer, pass --jailbreak at startup. the prompt turns red so you don't forget:
hooks
hooks are executables in ~/.config/xx/hooks/<event>/ that run on the host in response to an agent event. write them in whatever language you want and update them without restarting xx. session info is passed to a hook via XX_ env variables.
one line of sh turns the tmux window yellow while the agent works:
#!/bin/sh tmux set -t "$XX_TMUX" window-status-style bg=yellow
available hooks:
start: xx started but hasn't done anything yetbusy: agent is workingidle: agent is not workingcd:$ cd <path>changed the current working directoryshutdown: any exit (ctrl-d,/quit,SIGHUP)heartbeat: triggers every five minutes on a long running task
session state:
XX_EVENT: the hook nameXX_TASK: (busyonly) what the agent is doing: the prompt's first line, at most 120 chars, or/compactXX_SESSION: the session's jsonl file; empty before the first messageXX_CWD: current working directoryXX_PROVIDER: anthropic, openai, or openrouterXX_MODEL: model id in useXX_EFFORT: effort level (empty for the model's default)XX_THINKING: thinking mode (empty for the model's default)XX_CONTAINER: whether tools run in the container (true/false)XX_MODE: tui or printXX_TMUX: session:@window_id (empty outside tmux)
commands
slash commands either send markdown directly to the model or run a program and put its output in the scrollback, skipping the model. they live in ~/.config/xx/commands/ and can be edited without restarting xx:
above, review.md is a prompt command. /review the diff sends the file, then "the diff".
fork is a program command. it runs on the host with the arguments you pass to the slash command and the XX_ env vars listed above in the hooks section. the output of fork goes directly into the scrollback, not the model.
to see all available slash commands, including the builtin ones, run /help:
xx -c$ shell commands
run a shell command directly by typing $ on an empty line, then your command. typing $$ on an empty line locks you in "shell mode" where the input assumes shell commands until you ESC, ctrl-c, or backspace on an empty line. $ cd <path> will move xx's current working directory.
the shell commands you run and their output gets sent to the model with your next message:
xx.conf
override default settings with ~/.config/xx/xx.conf:
model claude-fable-5-1
effort high
keep_sessions 14d
container {
mounts ~/dev ~/.rev ~/notes
package jq
package rg apk add --no-cache ripgrep
}
you can also start xx with --model or --effort to override settings for a single session.
docs
docs are markdown files in ~/.config/xx/docs/ or .xx/docs/ explaining concepts. when xx starts, or when it runs the "docs" tool, it sees a list of available docs. running one enlightens it.
you can force xx to read a doc by sending /docs <name> or find out what's available with the /docs command.
besides the docs feature, xx (like all harnesses) sends ~/.config/xx/AGENTS.md and AGENTS.md (if they exist) with every request.
sessions
xx automatically tracks every transcript as an append-only jsonl file in ~/.config/xx/sessions. keyed by the current directory, they're deleted (by default) after 30 days.
you can continue the most recent session for the current directory or any session using -c. list them with -s:
provider-agnostic
xx works with anthropic, openai, or any anthropic/openai-compatible providers like openrouter. big whoop.
the /cost command hits the models.dev API to give you accurate pricing information for your model.
...and more
- queued input: type and hit
enterwhile the agent is working to queue your message for when it finishes. - multi-line input: use
shift-enterto insert a new line - $EDITOR support: hit
ctrl-xwhen writing your prompt or launch xx withxx -eto edit in$EDITOR - input history: use
up/downorctrl-p/ctrl-nto move through your prompt history, even across sessions - /transcript: see exactly what was sent over the wire with
/transcript - /status: see details about the current session with
/status - auto-compaction: when your model's context window is 80% full, xx will compact the session history. run it at any time using
/compact. check the current context with/context. - big pasta: big pastes collapse to one
[paste #1: 40 lines]token - tmux: xx knows when it's running inside tmux and renames the window to the project directory or rev change number
- capped tool output: tool output is capped at 60k chars to help keep things tight and right
get it
xx ships as a single binary for mac and linux:
curl -fsSL xx.sh | sh