Getting started - andreaderuvo/argus GitHub Wiki

Getting started

Three ways in. They end at the same place โ€” a URL with a token in it โ€” and none of them needs sudo.

One line

curl -fsSL https://raw.githubusercontent.com/andreaderuvo/argus/master/install.sh | bash
argus --allow-write

Everything 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-say and argus-mcp are launchers that run the installed code, and sessions Argus starts get its tools/ 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, ~/bin and beside its own Python โ€” and says so at start (OLD โ€ฆ in the banner), once in a notice, and in Alt+V, each with the ln -sf line 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 -- --service also 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 -- uninstall takes 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.
  • --dir puts it somewhere else; --version v0.1.0 installs one release exactly; --branch next follows an unreleased branch (development only โ€” a release archive is checked against its SHA256SUMS, 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.

In a container

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 here

Those 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.

By hand

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 it

Open 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.

Connecting your agents

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.

Which machines it runs on

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.

Every flag

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

Requirements

  • 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.

Configuration

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

Running it as a service

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 logout

Finding your way back here

The 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.

โš ๏ธ **GitHub.com Fallback** โš ๏ธ