Skip to content

Latest commit

 

History

History
578 lines (436 loc) · 26.2 KB

File metadata and controls

578 lines (436 loc) · 26.2 KB

agentistics CLI — agentop

agentop is the single binary for everything agentistics does: run the dashboard, the terminal TUI, the OpenTelemetry daemon, host or join a Team Mode central, and manage autostart + updates.

Get the binary from the install instructions (install.sh, the Windows installer, or bun run build:binary from source). From a checkout you can also run it directly with bun run packages/server/bin/cli.ts <command>.

agentop --help       # full usage
agentop --version    # print version (and a notice if an update exists)

Ports: a solo/member instance serves the web dashboard on 47292 (the URL you open) and the api + mcp on 47291 (in dev, Vite serves the web on 47292 and the api runs on 47291 — same split). A Team Mode central runs in Docker on 48080 by default. These are intentionally distinct so a member and a central can coexist on the same host.


Command overview

Command Purpose
start The control center — services, setup, logs, commands, help (same as bare agentop)
setup Interactive first-run wizard (solo / central / member)
server Start the web dashboard + api + Nay + background daemon (non-interactive)
restart Restart a running mode so it picks up new code / config
status At-a-glance: mode, services (server/central/machine) + health
tui Live terminal dashboard (no browser)
watch OpenTelemetry metrics daemon only (headless)
central Manage the Team Mode central (wraps central.sh)
member Join / leave / inspect a Team Mode central from this machine
ci-push One-shot push of a GitHub Actions run's metrics to a central (per repo)
autostart Start a mode with the system (systemd user service)
upgrade Upgrade agentop to the latest release
check-update Print an "update available" banner, else stay silent
doctor Run the exposure preflight before publishing a central
setup-token Reissue a central's one-time owner setup token
reset-password Reset an account's password from the host (locked-out owner)

Running bare agentop on an interactive terminal opens the control center. Without a terminal it prints this help; --help always prints it.


start

The control center — one full-screen application, in the terminal's alternate buffer, so it adds nothing to your scrollback no matter how long you use it. Bare agentop opens the same thing.

agentop                      # the usual way in
agentop start
agentop start --lang pt      # force Portuguese for this run
 ▄▀█ █▀▀ █▀▀ █▄░█ ▀█▀ █ █▀ ▀█▀ █ █▀▀ █▀
 █▀█ █▄█ ██▄ █░▀█ ░█░ █ ▄█ ░█░ █ █▄▄ ▄█                           member · v1.7.3 · ● 1.7.4

  services   setup   logs   commands   help   contribute
 ━━━━━━━━━━
 ╭─ services ─────────────────────────────╮╭─ config ─────────────────────────────────────╮
 │ ❯ agentistics         native ● up      ││   mode     member                            │
 │   agentistics central        ○ stopped ││   endpoint http://198.51.100.199:48080       │
 │                                        ││   history  consolidate                       │
 │                                        ││   language English                           │
 ╰────────────────────────────────────────╯╰──────────────────────────────────────────────╯
 ╭─ agentistics ────────────────────────────────────────────────────────────────── native ╮
 │ native · pid 48213 · up 2h13m                                                          │
 │                                                                                        │
 │ RUNTIMES ───────────────────────────────────────────────────────────────────────────── │
 │ native   ● up · pid 48213 · up 2h13m                                                   │
 │ docker   ○ stopped                                                                     │
 │                                                                                        │
 │ ADDRESSES ──────────────────────────────────────────────────────────────────────────── │
 │ web      http://localhost:47292                                                        │
 │ api      http://localhost:47291                                                        │
 │                                                                                        │
 │ MACHINE ────────────────────────────────────────────────────────────────────────────── │
 │ boot     starts at boot                                                                │
 │ history  consolidate                                                                   │
 │ endpoint http://198.51.100.199:48080                                                   │
 │   Restart   Rebuild & restart   Stop   Open in browser                                 │
 ╰────────────────────────────────────────────────────────────────────────────────────────╯

 q quit  ·  ←→ screens  ·  tab pane  ·  ↑↓ move  ·  enter actions  ·  s stop  ·  R restart

Naming: agentistics is the per-machine app; agentistics central is the team aggregator. Both serve a web dashboard, so neither is labelled "the dashboard".

The screens

Move between them with / — there are no digit shortcuts for screens, so the digits always belong to whatever list is drawing them.

Screen What it is for
services The cockpit: start / stop / restart, connect to or leave a central, enable a boot service
setup The same solo / central / member wizard as setup, plus the history-preservation consent
logs A tailing viewer, one source per running service
commands The cheat sheet — every command, without leaving the app
help · contribute What the keys do, and how to contribute

The services screen

The services list is the selection; the pane below is a view of it, so moving the cursor repaints it. tab cycles the panes (services → config → actions) and the actions are focus-scoped: with a service selected they act on that service, which is why there is no "stop which?" submenu.

  • One row per logical service, never per runtime. agentistics run natively and the same program in a container are two runtimes of one service. A running service therefore offers no "start" at all — it offers Restart, Rebuild & restart (only where a rebuild could actually work here), Stop and Open in browser. A stopped one is dimmed and offers only the starts this machine can perform.
  • A service running under BOTH runtimes says so, in colour, with a word — and its verbs split into Stop (native) / Stop (docker). They read the same files and fight over the same port, so the conflict is never normalised away by showing just one.
  • A long action streams into the detail pane, titled with the verb you pressed, while the lists stay standing beside it. esc puts the facts back.
  • The Docker option mounts the host's harness dirs read-only — run the machine in Docker or natively, not both. See Machine in Docker.

The footer always names the keys that work in the current focus; it is the only documentation the screen has, so a hint for a key that does nothing there is a bug.

Non-interactive stdin (a pipe, a systemd unit) skips all of this and behaves exactly like server. q leaves without starting anything.


restart

Restart a running mode so it picks up new code (after an upgrade / git pull) or a changed config. Defaults to server.

agentop restart                      # = restart server
agentop restart server               # bounce the systemd user service (agentop-server)
agentop restart watch                # bounce the watch service
agentop restart central              # bounce the central's container
agentop restart --all                # bounce every service currently up
agentop restart central --rebuild    # rebuild the image first, then restart
agentop restart central --rebuild --cache -n   # …reusing the layer cache, answering the prompt

server/watch bounce the installed systemd user service — if none is installed it tells you to run it in the foreground or enable autostart first. --all bounces everything that is up (local + central + machine), non-interactively.

--rebuild is a FULL rebuild. The Docker paths pass --no-cache, because a cached build can hand you back the very image it was asked to replace — which is the one failure mode a rebuild exists to prevent. That takes several minutes, and the command says so on the way in:

Flag Effect
--cache Reuse Docker's layer cache instead — the fast path
--no-cache The default for a rebuild; stated explicitly
-y / --yes Re-run the central's interactive setup, without being asked
-n / --no Do not re-run it — the default when there is no terminal to ask on

Passing -y with -n (or --cache with --no-cache) is refused, not silently resolved. A plain agentop central up is not a rebuild and keeps its cached build.


status

Non-interactive, at-a-glance report of this machine. Prints three blocks:

  • CONFIG — the team mode (solo / central / member) and, for a member, the central endpoint (from preferences).
  • SERVICES — detected live: the local server (http://localhost:47291/api/health; shows the dashboard URL when up), the central container, and the machine container.
  • HEALTH — a one-line summary from /api/health when the server is up, else n/a.
agentop status

Handy for a quick "is everything up and healthy?" without opening the dashboard.


setup

Interactive first-run wizard. Walks you through picking a mode and wires up the rest for you: solo (local only, nothing leaves the machine), central (host the aggregator on this machine via central.sh init), or member (push this machine's computed metrics to a central via member connect). It then offers to enable autostart.

agentop setup

Needs a TTY. Ctrl-C is non-destructive — it aborts without touching your preferences. For non-interactive/scripted member onboarding, use agentop member connect directly.


server

Starts the web dashboard, api, Nay chat, MCP registration, and the OTel daemon — everything in one process. Binds two ports: the web dashboard on 47292 (open this) and the api + mcp on 47291. They share one request handler, so the dashboard's /api/* calls just work.

agentop server              # web: http://localhost:47292 · api/mcp: http://localhost:47291
agentop server --port 4000  # api on 4000, web on 4001
agentop server --bg         # detached, logging to ~/.agentistics
agentop server --central    # run a central natively, no Docker
Flag Default Description
--port <n> 47291 The api + mcp port; the web dashboard is served on this + 1 (default 47292)
--bg off Start detached in the background; logs go to ~/.agentistics
--central off Run this process as a team central, natively — see below

--central — a central without Docker

Runs the same server with AGENTISTICS_TEAM_CENTRAL=1, loading central.env (searched in $AGENTISTICS_CENTRAL_ENV, ./central.env, then ~/.agentistics/central.env) for the secrets and the database URL.

There is no bundled MongoDB on this path — set MONGO_URL to an external cluster (Atlas, or a mongod you run yourself). For the all-in-one flow with Mongo included, use agentop central up instead.

AGENTISTICS_TEAM_PASSWORD in central.env selects the legacy shared-password login and masks the accounts sign-in. If you want accounts, remove it — the central will otherwise serve the old "team password" screen with no error anywhere.


tui

A live multi-screen dashboard in the terminal — no browser needed. Built with Ink, it updates the instant the web dashboard does, over the same /api/events SSE stream.

agentop tui
agentop tui --lang pt         # force Portuguese for this run
 agentistics  ·  live coding-assistant analytics                          ● live

 1 Overview  2 Projects  3 Sessions  4 Costs  5 Harnesses

 USD 8,364.44        13.3B         262           113.4K        2d
 cost                tokens        sessions      messages      streak

 activity · last 30 days
 ▅▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█▅▁▁▁█▃

 Harnesses
 Claude       ██████████████████████████████ USD 8,363.48  13.3B tok
 Codex        ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ USD 0.01  27.6K tok

 1-5/tab switch screen  ·  f filter  ·  ? help  ·  q quit
Key Does
15, tab Switch screen — Overview, Projects, Sessions, Costs, Harnesses
f Filter by harness
r Force a refresh
? Keyboard help
q, ctrl+c Quit

There is no configuration wizard — it opens straight into Overview and filtering happens in-app. If no server is listening it starts one itself and stops it again on exit; a server that was already running is left alone.

Metrics match the web dashboard exactly: both price through calcCost(), Claude totals come from stats-cache.json and every other harness from per-session sums. A metric a harness cannot produce shows N/A rather than a misleading 0.

Needs an interactive terminal — piping it exits with a message instead of a crash.


watch

Runs only the OpenTelemetry file watcher + OTLP metrics exporter (the same daemon server runs in the background). Use this on a headless box that only needs to feed Grafana/Datadog. See docs/opentelemetry.md.

agentop watch

central

Manage the Team Mode central — the Docker service that aggregates metrics from many members. This is a thin wrapper over the repo's central.sh, so it needs to run from an agentistics checkout (the compiled binary alone doesn't ship the Compose stack). Full deployment details live in docs/DEPLOY.md.

agentop central <up|init|down|logs|status|restart|pull>
Action What it does
init (Re)generate central.env interactively — auto-generates the secrets with openssl, detects your Tailscale IP for the bind, writes the file chmod 600
up Build the image and (re)create the containers (--build --force-recreate); offers init first if central.env is missing
restart Restart the app container without rebuilding
logs Follow the app container logs
status Show container + health status
down Stop and remove the containers — keeps the Mongo data volume
pull Rebuild from a fresh base image (run git pull first)
agentop central init        # generate central.env (interactive)
agentop central up          # build + (re)create — most common
agentop central logs        # tail the app logs
agentop central down        # stop, keep the data volume

From a checkout you can equivalently use the package scripts bun run init:central and bun run up:central, or call ./central.sh directly.


member

Configure this machine as a member that pushes computed metrics to a central. Only aggregated metrics are sent — never chat content or raw transcripts. The machine's display name is assigned by the central (baked into the minted token) and resolved via /api/team/whoami; there is no name field on the machine.

agentop member connect --endpoint <url> --token <token> [--org <org>]
agentop member leave
agentop member status

member connect

Verifies the token against the central's whoami endpoint, then saves the member config. On a bad token it prints an actionable error and writes nothing (no half-configured state).

Flag Required Description
--endpoint <url> yes Central base url, e.g. http://host:48080
--token <token> yes Token minted for this machine in the central's Team Manager
--org <org> no Org override; defaults to the org on the token
agentop member connect --endpoint http://100.64.0.2:48080 --token abc123

member leave

Best-effort notifies the central (so it drops this member's data) and resets this machine back to solo. Succeeds locally even if the central is unreachable.

member status

Prints the current mode / endpoint / org / user plus the live uploader state (last sync timestamp and whether the token/endpoint are healthy).

mode:      member
endpoint:  http://100.64.0.2:48080
org:       default
user:      alice-laptop
last sync: 2026-07-01T12:34:56.000Z
state:     ok

ci-push

One-shot push of a GitHub Actions run's computed metrics to a central, attributed to the repository it ran in. Meant to be the last step of a workflow that already runs Claude Code (it does not run Claude) — the ephemeral runner populates ~/.claude, then ci-push sends that run's session/token/cost aggregates before the runner is torn down. It reads everything from the environment and takes no flags.

Env var Required Description
AGENTISTICS_CENTRAL_URL yes Central base URL, e.g. https://central.example.com
AGENTISTICS_CI_TOKEN no Repo-bound static token (fallback when OIDC is unavailable)

Auth is keyless GitHub OIDC by default: with permissions: id-token: write on the job, ci-push fetches a short-lived GitHub-signed token itself (audience = AGENTISTICS_CENTRAL_URL) and the central verifies it against GitHub's JWKS. No secret needed. If no OIDC token can be fetched it falls back to AGENTISTICS_CI_TOKEN. The repo must first be registered on the central (Settings → Team → Repositories, which allowlists the remote and, for the fallback, mints the token).

# inside a GitHub Actions job, after the Claude Code Action step:
curl -fsSL "https://github.com/blpsoares/agentistics/releases/latest/download/agentop" -o agentop
chmod +x agentop
./agentop ci-push

ci-push never fails your job — a push error (central down, unverifiable token) logs and exits 0. It pushes computed metrics only, never chat. See docs/github-actions.md for the full workflow + registration walkthrough.


autostart

Register a mode to start with the system. On Linux/WSL this installs a systemd user service at ~/.config/systemd/user/agentop-<mode>.service, enables it with systemctl --user enable --now, and runs loginctl enable-linger so it also starts at boot without an active login. enable additionally installs a ~/.bashrc hook that runs agentop check-update on every terminal open. macOS and Windows print the manual step instead.

agentop autostart <mode> <enable|disable|status>
  • modeserver · central · watch
  • enable — register + start the service (and add the terminal update hook)
  • disable — stop and remove the service
  • status — show enabled/active state; omit the mode to list all services
agentop autostart server enable    # start the dashboard at boot
agentop autostart status           # list every autostart service
agentop autostart watch disable    # stop the otel daemon service

upgrade

Download and install the latest agentop release in place. (update is an alias.)

agentop upgrade

On a central you upgrade the Docker stack instead — pull the repo and rebuild:

git pull && bun run up:central    # or: agentop central pull

On a member running as a systemd service, restart it after upgrading:

agentop upgrade && systemctl --user restart agentop-server

check-update

Prints the "new version available" banner only when a newer release exists, and stays completely silent otherwise — so it's safe to run on every shell start. This is exactly what the ~/.bashrc hook installed by agentop autostart … enable runs.

agentop check-update

Update detection

agentistics surfaces available updates in three places, all sourced from the same version check:

  • On command run — most agentop commands print the update banner in parallel with startup (non-blocking); --version appends the notice too.
  • On terminal / boot — the ~/.bashrc hook added by autostart … enable runs agentop check-update when you open a shell (silent when you're current).
  • On the dashboard — a bell notification plus a mode-aware upgrade modal showing the exact command for your role (a central shows bun run up:central; a member shows agentop upgrade then systemctl --user restart agentop-server). A periodic (~6h) server re-check pushes the notification live over SSE.

doctor

Runs the exposure preflight: nine checks that decide whether this instance is safe to publish. Exits non-zero on any failure, so going live can be gated on one command instead of on remembering nine environment variables.

agentop doctor              # check against the current profile
agentop doctor --exposed    # check against the strict public bar

./central.sh doctor --exposed        # from a repo checkout, INSIDE the container
agentop central doctor --exposed     # same, from the standalone binary

On a Docker central, prefer the central.sh / agentop central form. The command evaluates the configuration the deployment will actually run with — it reads central.env when present and prints which file it used — but the owner-MFA and machine-token checks also need MongoDB, which is reachable only from inside the compose network. Run on the host, those two report as unverified, which counts as a failure by design.

--exposed evaluates as if AGENTISTICS_EXPOSURE=public were already set, which is how you verify readiness before flipping it.

What it checks:

Check Fails when
local-shell /api/exec, /api/chat-tty, the host transcript readers or /api/mcp-action are still reachable
session-secret The secret is missing, shorter than 32 chars, or equal to the dashboard password
tls AGENTISTICS_TEAM_TLS is unset on a public profile
bind-ip BIND_IP is not loopback on a public profile — the tunnel connects locally, so anything wider is a way in that bypasses it
trust-proxy (warn) forwarded-IP trust does not match the deployment, so per-IP limits apply to everyone at once
owner-mfa Any owner account has no TOTP enrolled
cors A plaintext origin sits in AGENTISTICS_ALLOWED_ORIGINS
mongo-auth (warn) the database has no credentials — acceptable only while its port stays unpublished
machine-tokens (warn) no machine tokens have been minted yet

A check that could not be verified — the database was unreachable, say — reports a failure, not a reassuring pass. See exposure.md for the full deployment runbook.


setup-token

Reissues a central's one-time owner setup token — the token first boot prints, and which the dashboard asks for when it creates the first owner account.

agentop central setup-token      # from anywhere
./central.sh setup-token         # from a checkout

Use it when the boot that printed the token has scrolled away or its log rotated. It is refused once an owner exists: past that point the way back in is reset-password, not a fresh setup token.

Run it where the central runs — inside the container/host serving it, not on a member.


reset-password

Resets an account's password from the host. This is the only way back in for a locked-out last owner, so it deliberately requires shell access to the machine running the central.

agentop central reset-password                              # list the accounts
agentop central reset-password --email ana@example.com      # prompts for the new password
agentop central reset-password --email ana@example.com --password '<new>' --clear-mfa
Flag Effect
--email <address> Which account. Omit to list them
--password <new> Set it non-interactively (subject to the password policy)
--clear-mfa Also drop the enrolled second factor — for a lost authenticator

Every reset is written to the audit log. --clear-mfa removes a security control, so on a public profile treat it as a break-glass action and re-enrol immediately: owner-mfa is one of the checks doctor --exposed fails on.