Skip to content

Getting started

Andrea de Ruvo edited this page Sep 8, 2026 · 11 revisions

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 five runtime dependencies
~/.local/bin/argus a three-line launcher

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.
  • … | bash -s -- --service also writes a systemd user service and starts it. It stops when you log out unless lingering is on: sudo loginctl enable-linger $USER.
  • … | 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, --branch follows a different branch.

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.

ARGUS_PORT=8100 docker compose up -d when 8090 is taken, which it will be if you already run one natively.

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.

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 python@3.13. No systemd, so the service flag says so and stops rather than pretending
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
--print-url print the URL with the token and exit
--qr print a QR code of the URL for every address this machine answers on, and exit

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 config key and a command-line flag with the same name.

Key Default What it does
listen 127.0.0.1:8080 address and port
token generated the only credential
roots ~ the only paths that can be read at all
allow_write false rename, move, delete, upload, save
allow_proxy false reverse-proxy a loopback port
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, able to do five things and nothing else
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 adapt, preserve, auto — who sets the window size
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
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

[Unit]
Description=Argus
After=network-online.target

[Service]
ExecStart=/usr/bin/python3 -m app.main
WorkingDirectory=/path/to/argus
Restart=always

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. The documentation is meant to be one tap from wherever you are, rather than something to go and look for.

Clone this wiki locally