-
Notifications
You must be signed in to change notification settings - Fork 0
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.
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 && claudeis 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.
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.
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:
-bwhen 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-xnext toproject— 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.
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.