Skip to content

Starting an agent

Andrea de Ruvo edited this page Aug 19, 2026 · 1 revision

Starting an agent

Argus used to attach to work you had already begun from a shell, which made a desk a window onto a job rather than the place a job starts. On a phone that gap was the whole story: you could watch an agent and answer it, but you could not begin one, because beginning one meant a shell and a phone has not got one.

The same one button as before — New session on the desk toolbar, and the line at the top of the Sessions sheet — now asks three more things:

what to start a shell, or one of the agents this machine has
the first instruction typed into it once it has finished starting. From the prompt library, filled in for this desk, or written there and then
a worktree when the folder is a git repository: a second checkout on its own branch, so two agents are not editing one tree

Nothing new to find and no new icon: it is the box that used to ask for a name.

What it can start, and why that is a list

A launcher is a name and a shell line, and it lives in your configuration:

launchers:
  - name: Claude Code
    command: claude
  - name: Codex
    command: codex
  - name: Reviewer
    command: conda activate review && claude --model opus
  - name: A shell
    command: ""

With nothing configured you get Claude Code, Codex, Gemini and a plain shell, which is a starting point and not a claim about your machine. Your list replaces that one entirely.

Two things follow from a launcher being a shell line rather than a program:

  • It runs through your login shell, so whatever your shell knows, it knows. "It is on my PATH" usually means "my profile puts it there", and conda activate x && claude is a perfectly good entry.
  • The API can only start a launcher by name from this list. That is what keeps the endpoint from being "run anything" — and worth saying plainly, because the terminal next to it has always been exactly that. This is one of the few places in Argus where a feature narrows what a token can do.

Each row says whether the command can actually be found, asked the way it will be used — through the login shell, not by walking this process's PATH. That distinction is not pedantry: a server started by systemd has a minimal PATH, and Argus greyed out claude on the machine it was written on while a login shell found it instantly.

The first instruction, and the one hard problem

An agent is not ready when its process starts. It prints a banner, works out what is in the folder, and very often asks something first — do you trust the files here? Text delivered into the middle of that lands in the wrong place: at best ignored, at worst answering a question you never read.

There are three ways to know when it has finished starting, and only one of them survives their next release:

  • A marker per agent — "Claude is ready when line X appears" — is precise, and rots. This app has been burnt by exactly that kind of table before, in the agent detection.
  • A fixed sleep is a guess: too short on a cold cache, too long always.
  • Stillness is neither clever nor precise, and it is true of every program there is: when a thing has finished starting, it stops writing.

So Argus watches the pane's cursor and history length — not its text; reading a pane's text has taken a whole tmux server down on one machine this was tested on — and calls it ready when nothing has moved for a second and a half. A first attempt used 0.8s and ended the wait during a launcher's thinking pause, which is precisely the moment this exists to avoid.

And then it still does not press Enter unless you asked. press Enter for me is off, and when the wait runs out with the screen still moving the prompt is left typed in and unsent whatever the switch says. The reply tells you which happened, in those words, because "typed in, not sent" is the case you need to know about — the alternative is waiting on an agent that was never going to answer.

The request is held while it waits, capped at twelve seconds. A script that does not care can ask for longer with wait_seconds.

A worktree, when the folder is a repository

Two agents in one checkout tread on each other. Git's own answer is a second working directory on its own branch, sharing the object store — no copy of the repository, no pair of clones to keep in step. Tick in a new git worktree, give it a branch, and Argus makes it and starts the agent in it.

  • The branch may be new or existing: -b when it does not exist, a plain checkout when it does, because "it already exists" is not a reason to refuse what you asked for.
  • It goes beside the repository — project-feature-x next to project — rather than inside it. A checkout nested in its own parent gets walked by that parent's tooling and counted twice by everything that looks for files.
  • It has to land inside the configured roots, or Argus would make a checkout it cannot then browse, edit, or open a session in.
  • Removing one needs --allow-write, and git refuses while there is uncommitted work in it. That refusal is the only thing standing between an afternoon and a button, so it is not overridden quietly: forcing is a separate, deliberate answer.

Argus is not becoming a git client. It lists worktrees, makes one and removes one — the three things needed to start work where it cannot collide. Committing, merging and resolving are what the agent in the terminal is for.

The three routes

GET /api/launchers the list, with available per row — null when the command is a shell line and the answer is not knowable
POST /api/tmux/launch {launcher, name, path, prompt, run, wait, wait_seconds}{name, ready, seeded, sent}
GET/POST/DELETE /api/git/worktree(s) list for a path, add on a branch, remove one. The last two want --allow-write

See The API for the whole surface.

Clone this wiki locally