@aicommander/agent
v1.0.31
Published
Remote-machine agent for AI Commander — runs on your server/laptop and lets your AI agent execute shell commands on it via the @aicommander/mcp server. An SSH alternative with no exposed SSH, open ports, or VPN; drive it by AIC-… session code.
Downloads
1,490
Maintainers
Readme
@aicommander/agent — remote-machine agent for AI Commander
The on-machine agent for AI Commander. Run it on a
server, laptop, container, or CI box and it dials out to the relay and listens for
commands — letting your AI client execute shell/bash commands on that machine
through the @aicommander/mcp
server (or any MCP client pointed at the relay).
It's an SSH alternative with no exposed SSH, no open inbound ports, and no
VPN: the agent connects outbound, prints an AIC-… session code, and you drive it
from your AI by that code (or a saved alias, with an account API key).
Requires Node ≥ 18 on the target machine.
Install this on the machine you want to manage/control (the server, VM, container, or laptop you want your AI to run commands on) — NOT on the machine running your AI client. The client side is a different package,
@aicommander/mcp(the MCP server your editor/Claude talks to). Install@aicommander/agenton the target,@aicommander/mcpnext to your AI client.
Quick run (ephemeral, foreground)
npx @aicommander/agentRuns in the foreground and prints the full session code (you ran it yourself in your own terminal, so there's nothing to reveal), then listens until you press Ctrl-C. Nothing is installed and no service is created — ideal for containers, CI, dev boxes, or a quick one-off connection.
# Point at a different relay if you self-host:
AICOMMANDER_SERVER=https://relay.example.com npx @aicommander/agentThe printed code is what you give to your AI client: "execute df -h on AIC-…".
(aicommander-agent status --reveal is only for the systemd service below,
where logs/status keep the code masked.)
Persistent service (Linux, systemd)
Install globally and register a systemd unit that starts on boot and restarts on failure:
sudo npm i -g @aicommander/agent
sudo aicommander-agent installinstall writes /etc/systemd/system/aicommander-agent.service, enables it,
(re)starts it, and prints the session code. The unit runs aicommander-agent run
via the absolute path of the installed CLI and the Node binary that performed the
install (so it doesn't depend on PATH).
# Bake a custom relay URL into the unit:
sudo aicommander-agent install --server https://relay.example.comManage the service:
| Command | What it does |
|---|---|
| sudo aicommander-agent status [--reveal] | Show status, uptime, session code (masked unless --reveal) |
| sudo aicommander-agent enable / disable | Start+enable / stop+disable the service |
| sudo aicommander-agent change-code | Mint a new code and revoke all current access |
| sudo aicommander-agent uninstall --force | Stop, disable, and remove everything |
| journalctl -u aicommander-agent -f | Follow service logs |
Service logs are payload-free: journald may receive operation start/end, exit code, duration, and the printable executable basename for secure exec. It never receives the full shell command, secure-exec argv, cwd, env, input, stdout, or stderr. The library controller used by the desktop app is silent; an explicit foreground TTY run uses the same safe summary and does not print command payloads. Remote stdout/stderr still streams to the requesting client.
npm channel vs the signed native installer
| | npx / npm i -g (this package) | verified native release installer |
|---|---|---|
| Runtime | Your Node ≥ 18 | Self-contained native binary (no Node) |
| Best for | Ephemeral / dev / CI / Node-managed hosts | Linux systemd installs |
| Integrity | npm's tarball integrity + registry-side checksums | SHA-256 checksum enforced before install |
| Authenticity | npm registry trust | Installer + binary Ed25519 signatures, when the key fingerprint is independently confirmed |
| Update | npm i -g @aicommander/agent@latest | Repeat the verified download flow |
Security
This npm package relies on npm registry/tarball integrity for trust. The
native release flow verifies a signed, versioned installer before sudo, then
verifies the downloaded binary against the same Ed25519 key and enforces its
SHA-256 checksum. Follow the current steps at
https://aicommander.dev/howto/#install-agent; never pipe /install directly
into sudo bash. The Ed25519 guarantee is meaningful only after confirming the
key fingerprint through a channel independent of the download website.
Prefer this npm package for ephemeral / dev use and Node-managed
environments. In all cases: the session code is a root-exec credential —
anyone who has it can run commands as root on the machine. Keep it secret, don't
paste it into shared chats/screenshots/tickets, and rotate it with
aicommander-agent change-code if it leaks.
The relay connection does not put that code or the reusable agentToken in its
WebSocket URL. The agent authenticates a fixed-URL POST with
Authorization: Bearer, receives a 30-second single-use opaque connection
ticket, then opens the ticket URL with the same Bearer header. Relay errors and
local reconnect output do not include the Authorization value.
Local credential files: the Linux CLI and systemd service persist
session.json (session code + agent token) under /etc/aicommander-agent with
a ~/.config fallback, and stamp live metadata in /var/run/aicommander-agent/state.json.
Both use atomic writes and owner-only 0700/0600 modes; systemd installs set
AICOMMANDER_SERVICE=1 and fail closed if persistence breaks. The desktop app
keeps the session code in session.json but stores the reusable agent token in
OS-protected Electron safeStorage (session.token); it refuses to start when
that encryption is unavailable.
The separate service-token secure exec path is Linux-only and drops every
command to the installer-created aicommander-exec account. New accounts have no
supplementary groups and an owner-only (0700) home. Before any target process
spawns, the agent rejects known shells/interpreters/argument runners and
privilege/container/orchestration clients even if a hostile relay claims they
are allowlisted. It also parses local /etc/passwd and /etc/group without a
shell and refuses privileged primary or supplementary membership (root,
wheel, sudo, docker, podman, lxd, incus, disk, libvirt, or gid
0). Missing, unreadable, malformed, duplicate, or otherwise ambiguous identity
data fails closed.
The command denylist is intentionally not a complete sandbox policy: ordinary tools can gain subprocess features over time. The non-root uid/group boundary, not the basename allowlist or denylist, remains the containment mechanism.
License
MIT
