Getting started - andreaderuvo/argus GitHub Wiki
Three ways in. They end at the same place โ a URL with a token in it โ and none of them needs
sudo.
curl -fsSL https://raw.githubusercontent.com/andreaderuvo/argus/master/install.sh | bash
argus --allow-writeEverything it does, all of it:
~/.local/share/argus |
the code, downloaded as a tarball โ no git needed |
~/.local/share/argus/venv |
a virtual environment with the six runtime dependencies (segno only for --qr) |
~/.local/bin/argus |
a three-line launcher |
~/.local/bin/argus-say |
the command an agent in a session uses to ring, see who is here, and hand a sentence on |
~/.local/bin/argus-mcp |
the same verbs as MCP tools โ registered by you, or by the plugin |
What it does not do: touch anything outside your home, use sudo, install a system
package, add a repository, or start anything in the background unless you ask. There is
nothing to consent to, which is why it does not ask โ a curl | bash that cannot prompt (its
standard input is the script) and asks anyway is theatre.
-
Run the same line again to update. The code is replaced, the virtual environment
refreshed, and
~/.config/argusโ your token, your devices, your journal โ is not touched. -
Copies of the commands go stale; links do not. The installer's
argus-sayandargus-mcpare launchers that run the installed code, and sessions Argus starts get itstools/first on their PATH โ none of that needs updating. A command you copied by hand (cp tools/argus-say ~/bin/) does: a pull moves the repository on and leaves the copy where it was. Argus looks for them โ on the PATH, in~/.local/bin,~/binand beside its own Python โ and says so at start (OLD โฆin the banner), once in a notice, and in Alt+V, each with theln -sfline that replaces it by a link, and Link them to this Argus to do it for all of them (the old file is kept beside it as<name>.argus-old-<time>). Prefer a link from the start:ln -s ~/argus/tools/argus-say ~/.local/bin/argus-say. -
โฆ | bash -s -- --servicealso writes a systemd user service (running Argus with--allow-write, restarted on failure) and starts it. It stops when you log out unless lingering is on:sudo loginctl enable-linger $USER. Without systemd (macOS) it says so and installs the rest. -
โฆ | bash -s -- uninstalltakes the code and the launcher away and leaves your configuration, because a token you may still have on three phones is not the uninstaller's to throw away. -
--dirputs it somewhere else;--version v0.1.0installs one release exactly;--branch nextfollows an unreleased branch (development only โ a release archive is checked against itsSHA256SUMS, a branch is not);--source .installs a checkout. The same as environment variables:ARGUS_DIR,ARGUS_BIN,ARGUS_VERSION,ARGUS_BRANCH,ARGUS_SOURCE.
It is checked on every change, on Linux and macOS, by installing into an empty home, starting it, listing a real tmux session through the API, updating in place, and uninstalling.
For Windows-through-WSL, or for anyone who would rather not install Python:
git clone https://github.com/andreaderuvo/argus && cd argus
ARGUS_UID=$(id -u) ARGUS_GID=$(id -g) docker compose up -d
docker compose logs # the URL with the token is in hereThose two variables are not called UID and GID for a reason worth one sentence: bash makes
UID readonly, so UID=$(id -u) docker compose up fails with "readonly variable" โ which
is what this page said to type until CI pointed at it.
This container is a way to get the runtime, not a sandbox. Argus's whole job is to attach
to the tmux sessions and read the files of the machine it runs on, so it has to be handed that
machine, and docker-compose.yml spells out each thing it needs and why:
pid: host |
the lookups that say which agent is in a pane, and what folder it is really in, read /proc. Without this every session lists and none of them says anything about itself. |
| the same uid as you | or the tmux socket will not talk, and the files it reads are root's |
$HOME at the same path |
a pane reports /home/you/project; mounted at /work that is a path Argus cannot find |
/tmp/tmux-<uid> |
how a tmux client reaches a tmux server. This is what makes it your sessions rather than an empty server in a container. |
One caveat before it bites: tmux's client and server speak a versioned protocol. The image
ships Debian's tmux, and a host running a much older or newer one can be refused โ mount your
own binary over the image's (- /usr/bin/tmux:/usr/bin/tmux:ro) or install natively, which
cannot have the problem at all.
The container listens on 8090, published on 127.0.0.1 only. ARGUS_PORT=8100 docker compose up -d publishes it on another port when 8090 is taken (the link printed in docker compose logs
still says 8090 โ that is the port inside the container). It serves your home (--root $HOME,
which replaces roots) and shares ~/.config/argus โ the token, devices, preferences โ with a
native install on the same machine.
Rather pull than build? Every release is also an image, ghcr.io/andreaderuvo/argus: swap
build: . for the image: line commented out in docker-compose.yml.
git clone https://github.com/andreaderuvo/argus && cd argus
pip install -r requirements.txt
python3 -m app.main --allow-write # prints a URL with a token in itOpen the URL it prints. On first run it writes ~/.config/argus/config.yaml with a fresh
64-character token; that file is the only credential and is never in the repository.
--qr prints a QR code to photograph with a phone. Settings โ Open on another device
shows the same code from inside the app.
Optional, and worth it. The Argus plugin makes Claude Code or Codex say what it is doing (a turn started, finished, waiting for you) and gives it tools to use Argus: ask you something, ring you, start another agent, open a desk.
Claude Code /plugin marketplace add andreaderuvo/argus
/plugin install argus@argus
Codex codex plugin marketplace add andreaderuvo/argus
codex plugin add argus@argus
No plugin? Settings โ Let your agents ring wires the hooks of Claude Code, Codex and Gemini instead.
The thing you look at runs in a browser, so that side is any operating system with one. The server side is a different question, and the honest answer is short: tmux is a Unix program and there is no native Windows build of it.
| Linux | natively, or in the container |
| macOS | natively โ brew install tmux [email protected]. No systemd, so --service says so and installs the rest without a service |
| Windows | inside WSL, which is a Linux machine: the one-line installer works there unchanged. Not in Windows itself, and not because of Argus |
| A phone, a tablet, anything | as the browser, which is the whole point |
Linux and macOS are checked on every change; WSL is Linux and is not separately tested.
argus --help is the authority โ it is on the machine and cannot be out of date, and a test
fails if a flag ever ships without its sentence. The same list, to read here:
--version |
what is installed, without starting anything |
-c, --config PATH |
somewhere other than ~/.config/argus/config.yaml
|
-l, --listen HOST:PORT |
override listen for this run โ usually because a port is taken |
-r, --root PATH |
override roots; repeat it for several |
--socket NAME |
drive a specific tmux server: a socket name (-L), or a path if it contains / (-S). Use a throwaway one when testing โ a crashing tmux server takes every session on its socket with it |
--allow-write |
permit mkdir, rename, move, copy, delete and upload through the API. Off by default: a read-only viewer is a safe thing to leave listening |
--allow-proxy |
permit reverse-proxying one loopback port at a time, and only after you open it. Off by default: a service on 127.0.0.1 is there on purpose |
--mounts |
add every real filesystem on the machine to the browsable roots |
--drop-keep-days N |
delete files in the drop folder after N days, swept at startup and once a day. 0, the default, keeps them for ever |
--print-url |
print the URL with the token and exit |
--qr |
print a QR code of the URL at the address to use (address, else the machine's full name), and exit; --qr all for every address it answers on |
-
Python 3.11+ โ the PTY bridge uses
os.login_tty - tmux โ any recent version
- Optional: pandoc (Word documents), pdftotext from poppler (searching PDFs). Without them those files still open, they are just plainer.
No build step, no database, no bundler: the frontend is plain ES modules and the dependencies are vendored.
Everything is a key in ~/.config/argus/config.yaml (or $XDG_CONFIG_HOME/argus/config.yaml),
made with a fresh token the first time Argus runs. A few also have a flag for one run
(listen, roots, tmux_socket as --socket, allow_write, allow_proxy,
include_mounts as --mounts, drop_keep_days); the rest are only keys.
| Key | Default | What it does |
|---|---|---|
listen |
127.0.0.1:8080 |
address and port |
token |
generated | the only credential |
roots |
~ (written into a new config) |
the only paths that can be read at all. A config with no roots refuses to start |
allow_write |
false |
rename, move, delete, upload, save โ and everything else that writes: starting a team, proposing one, making or removing a git worktree, the drop-retention setting |
allow_proxy |
false |
reverse-proxy a loopback port |
address |
the machine's full name | the one address other devices use: the QR code (--qr, Open on another device) and the invite to move there when Argus is opened at another. A browser remembers the token per address, so the IP, the short name and the full name would each ask for it |
include_mounts |
false |
add every mount point to the roots |
launchers |
Claude Code, Codex, Gemini, a shell | what Start something here may start: a name and a shell line each. Yours replaces the shipped list โ see Starting an agent |
agents |
none | keys for the agents running here: a name and a token each, reaching only a fixed list of routes |
agents_without_asking |
none | actions an agent may have done on request without your tap, added to what is ticked in Settings โ Agents โ see What an agent can do |
launches_a_minute |
12 | the brake on starting things โ a fan-out is a dozen in seconds, a runaway loop is hundreds |
relay_a_minute |
30 | the same, for sentences pushed into other sessions |
ask_outside |
true | whether the System screen may offer to ask a stranger what this machine's public address is. Nothing happens without a press; false removes the button |
tmux_socket |
tmux's default | which tmux server to drive |
resize_policy |
adapt |
who sets a window's size: adapt โ the browser that attaches takes it; preserve โ the browser watches at whatever size the others have (tmux ignore-size); auto โ takes it only when no other client is attached |
max_preview_bytes |
2 MiB | past this a text file arrives as its tail |
viewers |
none | per-kind overrides of the cap above (PDF, mesh, spreadsheet, document, image), and telling the server an extension is really something else โ see Documents |
max_upload_bytes |
2 GiB | per-file upload cap, 0 for none |
drop_keep_days |
0 | delete drops older than this many days, swept at startup and once a day. 0 keeps them for ever. Also --drop-keep-days N, and Keep dropped files for in Settings |
drop_dir |
argus-drops |
where a file dropped on a session lands. Relative means inside the first root, which is what keeps the default inside the jail on a machine serving /data rather than a home directory. An absolute path is taken as written and must sit inside roots. Empty and a session takes no drops |
check_releases |
true |
ask github.com once a day for the latest release. Sends nothing |
tls_cert, tls_key
|
none | serve HTTPS โ both or neither. See Security |
watchers, runnable, report_to, obey_board, board_may_stop_argus
|
none / off | for a board across several machines (a watcher may also carry may_run, may_stop_argus) โ see Security
|
ntfy |
none | optional notifications when the browser is closed: server, an unguessable topic, optional token and the events to send. See Notifications |
The installer's --service does this for you. By hand:
[Unit]
Description=Argus
After=network.target
[Service]
ExecStart=%h/.local/bin/argus --allow-write
Restart=on-failure
RestartSec=3
[Install]
WantedBy=default.target(%h/.local/bin/argus is what the installer puts there; from a checkout use the Python that has
its dependencies โ /path/to/python3 -m app.main with WorkingDirectory=/path/to/argus. Leave
out --allow-write for a read-only Argus.)
Save as ~/.config/systemd/user/argus.service, then:
systemctl --user enable --now argus
sudo loginctl enable-linger $USER # or it stops at your last logoutThe GitHub mark in the top bar opens this wiki, the repository and the landing page. On a phone narrower than 560px it is not in the header: the same links are in Settings โ About Argus. The documentation is meant to be one tap from wherever you are, rather than something to go and look for.