Skip to content

Capability Status Line

github-actions[bot] edited this page Jul 25, 2026 · 3 revisions

Status line

A status line is the bar a coding agent renders under (or over) its prompt, filled by running a command and printing its stdout. A host declares one through PluginHost::statusline (the derive exposes it as statusline_fn), returning a StatusLineDecl { command, padding }. Like instructions, and unlike the five tree surfaces, it is not a file in the plugin tree — it is a declaration the host returns at runtime.

4 backends deliver it today, through one shared slot renderer.

harness how it arrives
claude the statusLine key in <config>/settings.json (user) or <project>/.claude/settings.json, as {"type":"command","command":…} plus padding when declared
qwen-code ui.statusLine in the same settings.json its other surfaces use, both scopes. type: "command" is required there: anything else is silently read as a built-in preset and the declared command never runs
antigravity-cli the root statusLine key in ~/.gemini/antigravity-cli/settings.json, user scope only. That harness has an on/off toggle of its own (enabled) which agentgear preserves rather than overrides
droid the root statusLine key in ~/.factory/settings.json (user) or <project>/.factory/settings.json, plus droid's own maxRows cap so a composed two-row line is not clipped to one

copilot-cli has a command-based slot of the same shape and is not wired yet. The remaining twenty harnesses have no slot a host can own. Where they look like they do, the setting is a curated list of built-in widget ids rather than a command.

The slot holds one value

This is the one surface agentgear cannot merge into. Every other write keys on names the plugin owns, so a plugin's entries sit beside the user's. A status-line slot is a single value and last-writer-wins, so writing it necessarily displaces whatever the user had. agentgear handles that by stashing, not by refusing:

  • Install copies the existing value into agentgear's own marker file, verbatim, before writing the host's command. An empty slot stashes nothing.
  • Uninstall restores the stash exactly, or deletes the key when there was nothing to restore. A slot whose command is no longer the host's is left untouched: someone else owns it now.
  • Ownership is the command string. Edit the padding on the host's line and the next self_heal puts it back (that is drift); replace the command and agentgear treats the slot as yours and stops touching it.
  • A harness's own on/off switch is preserved, never overridden. antigravity-cli's enabled is the only one today. If you had switched your status line off before installing, it stays off: agentgear will not flip a preference you set. doctor warns in that state instead of reporting a clean install, so a bar that renders nothing is never silent.
  • Two agentgear hosts that both declare a status line will stack: the second stashes the first's command as "the original". Uninstalling both restores the first host's line, not what you had before either.

Composing with the line you already had

agentgear writes the host's command and nothing else — it never generates a wrapper script. The merge happens inside the host binary, which is what agentgear::statusline is for:

// in the host's own `statusline` subcommand, named by the declared command
let mut session = String::new();
std::io::stdin().read_to_string(&mut session)?;
let line = agentgear::statusline::compose(&MyHost::descriptor(), client, &session, &my_rows)?;
println!("{line}");

compose returns the host's own rows first, then runs the user's original command with the same session JSON on its stdin and appends its rows (the surface is line-oriented: one line is one row). A user command that cannot start, prints nothing, or runs past a 3-second timeout simply contributes nothing, so a broken command of theirs never blanks the host's own bar. user_original returns the stashed declaration directly if a host wants to render it itself.

Declare the command with ${AGENTGEAR_CLIENT} (mytool statusline --client ${AGENTGEAR_CLIENT}) and each backend expands it to its own id, so the host's subcommand knows which harness invoked it. Once two or more of your declared agents can write a slot, leaving the token out is a doctor warning: every harness would receive the same literal command, so your subcommand reads one backend's stashed line from all of them and either drops the user's own row or runs another harness's stashed command.

See also

Clone this wiki locally