Give a local AI coding agent a remote hand. The agent's brain β its process, config, and memory β stays on your machine; only a single SSH "arm" reaches into a remote Linux server to read, run, and diagnose, behind tiered safety.
It's the inverse of cloud dev / remote-control tools. Those move the compute to the server and have you steer a remote agent. luffy-arm keeps the agent home and lets it reach out β reverse Remote-SSH: brain local, hand remote.
Built entirely from native parts (SSH keys, ~/.ssh/config, ControlMaster, POSIX
ACLs, ssh-agent). No daemon, no custom protocol, nothing to trust beyond OpenSSH.
π New here? Start with
TUTORIAL.mdβ a complete, zero-assumptions walkthrough (no prior SSH knowledge needed; ~15 minutes from nothing to a working channel).
You write code locally and your data/compute live on a server. You want the agent to go look at the data and run things there β without shipping your brain, memory, or credentials to a shared box. luffy-arm is that channel, with guardrails.
- A shared/institutional HPC or lab server where you can't install an AI agent β no root, no outbound network, or policy forbids it; SSH/SFTP is the only way in. luffy-arm keeps the agent on your laptop and gives it a hand on the server.
- Your data is too big to sync down β the agent explores and filters it in place and pulls back only the results.
- You want AI hands on a box, but with OS-enforced guarantees β a dedicated
unprivileged account, read-only ACLs, no
sudowithout your password. - One setup serves every agent you use β Claude Code, Codex, Cursor, OpenCode.
Tiered safety (details in references/security-model.md):
- π sudo password gate β
ccis non-privileged;sudoneeds a password only you know. - π data read-only (ACL) β
ccreads yourREAD_ROOTS; secrets are carved out. - β» per-project version control β
WORK_DIRSare writable; you snapshot per project. - π local authoritative copy β your local source is the ground truth.
Optional π command auditing (off by default): a server-side sshd wrapper logs every
command the agent runs as cc to the root-owned journal β detect, not prevent. Turn it
on/off with scripts/gen-audit-setup.sh (references/audit-logging.md).
| The agent does (π» local, after you authorize) | You do (π₯ server, with your sudo) |
|---|---|
Generate the SSH key, write ~/.ssh/config, verify the channel, then read/run/diagnose over ssh |
Create the cc account, install the public key, apply the read/write ACLs |
It hands you the exact privileged commands; you run them with your sudo (security model).
- Local: an AI CLI agent (Claude Code / Codex / Cursor / OpenCode) + OpenSSH. Target/session lifecycle commands require Python 3.9+ on macOS/Linux for file locks.
- Remote: Linux with
sshd. The key-basedccsetup additionally needs theaclpackage and a sudo-capable human; existing-account password sessions need neither.
Claude Code β via the plugin marketplace (recommended; gets you one-command updates, and opt-in auto-update):
/plugin marketplace add Ares960826/ares-agent-toolkit
/plugin install luffy-arm@ares-toolkit
Any agent β one command that auto-detects your agent(s) and installs the main skill plus the independent full-power ON/OFF switches into the right skills dir for each (Claude Code, Codex, Cursor, OpenCode):
curl -fsSL https://raw.githubusercontent.com/Ares960826/luffy-arm/main/install.sh | bashFrom a clone instead: git clone https://github.com/Ares960826/luffy-arm && bash luffy-arm/install.sh
Manual install (clone straight into your agent's skills dir)
# Claude Code Β· Cursor Β· OpenCode (all read ~/.claude/skills/):
git clone https://github.com/Ares960826/luffy-arm ~/.claude/skills/luffy-arm
LUFFY_ARM_DIR=~/.claude/skills bash ~/.claude/skills/luffy-arm/install.sh
# Codex (reads ~/.agents/skills/ β NOT ~/.claude):
git clone https://github.com/Ares960826/luffy-arm ~/.agents/skills/luffy-arm
LUFFY_ARM_DIR=~/.agents/skills bash ~/.agents/skills/luffy-arm/install.shThen just tell your agent what you want β e.g. "set up luffy-arm to my GPU box" or
"use luffy-arm to poke around my server" β and it follows SKILL.md.
After full-power setup, "turn on full power" and "turn off full power" route to separate,
purpose-built companion switch skills. Skill hosts do not currently expose true parent/sub-skill
metadata, so the operations remain independently invokable while their UI labels group them as
Luffy Arm βΊ Full Power ON/OFF. ON remains passphrase-gated and must be run by you.
First time? The friendly end-to-end walkthrough is TUTORIAL.md.
Upgrading to 1.7.0: after updating, run
luffy-arm ssh-configonce. This connects the existing admin alias to luffy-arm's stable, user-private agent socket so one interactive ON can be recognized by separate agent conversations. Your key, passphrase, server address, and other SSH connection fields are not changed.
Cursor note: Cursor is a GUI/IDE, not a headless CLI. The skill installs and works inside Cursor's agent chat, but each shell step goes through Cursor's command-approval UI β it can't be driven unattended the way Codex/OpenCode can.
Via the toolkit: it's also referenced from
ares-agent-toolkit as a submodule.
Upgrading from the single-server version: run luffy update, then register your
existing key params with the command below. Keys, SSH configuration and target/session
records live outside the installed skill and remain in place. A key passphrase prompt
and an account password prompt are both normal; type the requested secret only into
the SSH/ssh-add prompt. --password selects account-password authentication and never
takes a secret value. luffy version reports the installed release.
Registered servers: luffy tlist lists target IDs, display names,
login modes and the default. Register an existing key setup with
luffy target add my-lab --params ~/.config/luffy-arm/params.sh --name "My lab".
Both key and password targets accept a duration:
luffy fullpower on my-lab 120000 and
luffy fullpower on my-cluster --password 120000.
See registration, defaults and duration rules.
Existing account with password login: the human runs
luffy fullpower on TARGET --password once in a local terminal. The agent then reuses
the background connection; the terminal may close. Repeating ON reuses the same
connection. Use luffy fullpower status --all to inspect targets and
luffy fullpower off --all to close registered sessions and key gates.
This supports servers where the user cannot install a key
or create a cc account. Local Python 3 is required. See
target setup and session lifecycle.
The easy way β let your agent drive it. After installing, just say:
"Use luffy-arm to set up access to my server."
The agent configures everything local automatically, interviews you for the details, and hands
you one server command to run. You only ever do the parts it can't (type your sudo password
on the server). See SKILL.md for exactly what it does.
By hand (same steps, if you'd rather run them yourself)
# 1. fill in your params (kept OUTSIDE the repo)
mkdir -p ~/.config/luffy-arm && cp scripts/params.example.sh ~/.config/luffy-arm/params.sh
$EDITOR ~/.config/luffy-arm/params.sh
# 2. local: make the key + ssh config
bash scripts/keygen.sh # prints the public key
bash scripts/ssh-config.sh
# 3. generate the filled-in server script, then run it ON THE SERVER (you, with sudo)
bash scripts/gen-server-setup.sh # writes luffy-arm-server-setup.sh
# scp luffy-arm-server-setup.sh you@server:~/ && ssh you@server 'bash luffy-arm-server-setup.sh'
# 4. local: verify the channel + all safety nets
bash scripts/verify.sh # β π all passedFull hand-holding walkthrough: TUTORIAL.md.
luffy-arm tells you when a newer version is published (verify.sh prints a one-line nudge), and
upgrading is one step:
-
Claude Code (plugin marketplace):
/plugin update luffy-arm@ares-toolkit. To keep it automatic, turn on auto-update once:/pluginβ Marketplaces β select ares-toolkit β Enable auto-update. (Third-party marketplaces don't auto-update until you flip that switch β deliberate, for a tool that touches SSH. Prefer to review changes first? Leave it off and run/plugin updatewhen you want.)Org admins: push auto-update to everyone via managed settings
// managed-settings.json (admin/managed scope β NOT user settings.json) { "extraKnownMarketplaces": { "ares-toolkit": { "source": { "source": "github", "repo": "Ares960826/ares-agent-toolkit" }, "autoUpdate": true } } }
-
Codex / Cursor / OpenCode / curl installs:
bash scripts/update.sh(pulls the latest and re-installs into every detected agent).
Pulling server data down to where the brain lives is a core use β anything cc can read
(your READ_ROOTS, minus the READ_EXCLUDES secrets) comes down over the same host alias:
scp mybox:/data/run42/metrics.json ./ # one file
rsync -avz --partial --progress mybox:/data/run42/ ./run42/ # a directory (resumable)
ssh mybox "tar czf - /data/run42" | tar xzf - # stream a whole tree, no temp filesSecrets in READ_EXCLUDES can't be read, so they can't be pulled; uploads land only in
WORK_DIRS.
install.sh also drops a luffy-arm command into ~/.local/bin β a thin wrapper so you can
type short subcommands instead of full script paths:
luffy-arm help # list everything
luffy-arm verify # safe-mode channel + safety-net check
luffy-arm fullpower on|off # opt-in write-as-yourself (you type the passphrase)
luffy-arm fullpower on TARGET --password # selected server, you type the password
luffy-arm fullpower on TARGET 120000 --password # elapsed lifetime in seconds
luffy-arm tlist # discover registered server names
luffy-arm fullpower off|status TARGET # close/check the selected session
luffy-arm fullpower off --all # shut down registered sessions and key gates
luffy-arm fullpower status --all # inspect all registered targets
luffy-arm fullpower-on|off # intent-shaped aliases used by the switch skills
luffy-arm audit-gen # generate the opt-in server audit script
luffy-arm setup | grant | update | β¦It forwards to the same scripts/*.sh and changes no behavior β every passphrase and sudo
prompt is exactly as before. It's a symlink, so it tracks updates; remove it with
rm ~/.local/bin/luffy-arm. The installer also adds a shorter luffy alias (so luffy verify works too) β but only when no other luffy is already on your PATH, since an unrelated
Homebrew CLI ships that name; if it's taken, the installer says so and you keep luffy-arm. The
AI agent doesn't use this; it calls the scripts directly.
TUTORIAL.md # full human walkthrough β start here if you're new
SKILL.md # agent playbook (read first if you're an AI agent)
agents/openai.yaml # UI label for the main skill
skills/ # companion luffy-arm-fullpower-on / -off switch skills + UI labels
scripts/ # dispatcher: luffy-arm (the `luffy-arm <cmd>` command)
# safe mode: keygen.sh Β· ssh-config.sh Β· gen-server-setup.sh Β· verify.sh Β· grant.sh Β· params.example.sh
# full-power: admin-keygen.sh Β· fullpower.sh Β· verify-fullpower.sh
# auditing: gen-audit-setup.sh (opt-in command log)
# upkeep: update.sh Β· check-update.sh
references/ # setup-guide.md Β· server-setup.md Β· security-model.md Β· audit-logging.md
- Safe mode (default):
ccreads your data, writes only inWORK_DIRS. - Full-power mode (opt-in): the dedicated luffy-arm credential is gated by a passphrase only
you type and auto-expires by TTL. Status separately reports the actual remote identity and any
alternate SSH credential that still reaches your user account. How & why:
references/security-model.md. - Layered, sandbox-safe state: status distinguishes the dedicated gate from effective
ADMIN_USERaccess. Gate OFF never implies Safe Mode if another key still authenticates as the same remote user. A sandbox or network failure is never mislabeled as OFF. In a runtime known to sandbox SSH/ssh-agent, the agent should request narrowly scoped host execution from the first probe instead of testing the sandbox first; a normal-terminal user check is only the fallback. The ON command publishes a stable agent socket reference under~/.config/luffy-arm/, so separate conversations do not depend on their inheritedSSH_AUTH_SOCKvalue.
Found a bug or want a feature? Open an issue β templates guide you. Vulnerabilities:
SECURITY.md.
Stuck? Troubleshooting lives in TUTORIAL.md Β§7 and
references/setup-guide.md.
MIT Β© Ares960826

