SSH-like machine access for AI agents through a self-describing, ACL-controlled HTTP entry point.
Give an agent a URL and API key. It reads /SKILL.md, checks /api/acl, and executes through /api/exec.
On a machine that already has Node.js and npm:
npm i -g @to-agent/agent-exec
aexec setup # generate API key
aexec start # start the server
aexec share # generate a prompt for an AI agentaexec is the official command. ae is the short alias for daily use.
aexec share prints a prompt like this:
You have access to a machine through agent-exec.
URL: http://127.0.0.1:3333
API_KEY: <key>
Start here:
http://127.0.0.1:3333/SKILL.md
Paste it into Claude, Gemini, Codex, Hermes, OpenClaw, or any agent that can make HTTP requests. By default this is local-machine handoff. For a trusted LAN or disposable canary machine, bind to a network interface and pass the reachable host explicitly:
aexec start -f --public
aexec share --ip <reachable-host-or-ip>Do not expose agent-exec directly to the public internet. Treat the API key as machine execution capability. Use localhost, VPN, firewall, TLS termination, or another trusted network boundary.
Before sharing:
- agent-exec is not a sandbox.
- agent-exec is not SSH-compatible and is not an SSH replacement.
- Fresh installs only allow
aexec --version. - Do not expose plain HTTP agent-exec to the public internet.
- Run agent-exec as a least-privileged OS user.
You can also paste this prompt into a local AI coding agent and let it install agent-exec for you: The standalone file is agent-exec.install.skill.md.
Install agent-exec on this machine.
Goal:
- Install @to-agent/agent-exec globally.
- Run the first-time setup.
- Start the local server.
- Show me the final aexec share prompt.
Steps:
1. Check that Node.js and npm are available:
node --version
npm --version
2. Install agent-exec:
npm install -g @to-agent/agent-exec
3. Verify the CLI:
aexec --version
4. Run setup:
aexec setup
5. Start the server for local use:
aexec start
6. Generate the handoff prompt:
aexec share
Constraints:
- Do not edit project files unless required for installation.
- Do not expose agent-exec to the public internet.
- Do not use --public unless I explicitly ask for network access.
- Do not add broad ACL rules such as allow "*".
- Fresh installs should only allow: aexec --version.
- If any command fails, stop and show me the error plus the next recommended command.
Optional, when you want agent-exec to expose installed local AI tools as plugin skills:
aexec starterkit
aexec restartaexec starterkit prints each generated settings.json by default so you can review new exec.allow rules before restart. Use --silent or --quiet to suppress that output.
agent-exec gives an AI agent a small, self-describing entry point into a machine.
Agent receives URL + API key
-> GET /SKILL.md read the machine guide
-> GET /api/acl inspect allowed operations
-> GET /api/plugins discover optional plugin docs
-> POST /api/exec execute an allowed command
sequenceDiagram
participant Agent as AI Agent
participant AE as agent-exec
participant Machine as Machine
Agent->>AE: GET /SKILL.md
AE-->>Agent: machine guide
Agent->>AE: GET /api/acl
AE-->>Agent: allowed operations
Agent->>AE: POST /api/exec
AE->>Machine: run allowed command
Machine-->>AE: output
AE-->>Agent: result
The server remains in control. The agent discovers what exists, but the machine decides what is allowed.
Public:
| Path | Purpose |
|---|---|
GET / |
Runtime root guide |
GET /SKILL.md |
Main agent guide |
GET /skills |
Skills index |
GET /skills/:name/SKILL.md |
Public skill docs |
API key required:
| Path | Purpose |
|---|---|
GET /api/acl |
Allowed and denied commands |
GET /api/plugins |
Installed plugin docs |
POST /api/exec |
Execute a command |
GET /private/skills/:name/SKILL.md |
Private plugin docs |
Protected calls should use:
curl -H "X-API-Key: <key>" http://localhost:3333/api/aclAuthorization: Bearer <key> is also supported. Query-string auth is disabled by default and is intended only for explicit compatibility use.
Commands are sent as an argument array:
curl -X POST http://localhost:3333/api/exec \
-H "X-API-Key: <key>" \
-H "Content-Type: application/json" \
-d '{"args": ["aexec", "--version"]}'Example response:
{
"output": "agent-exec v0.1.0\n",
"exitCode": 0,
"status": "done"
}/api/exec accepts command arguments only from the JSON body:
{"args": ["command", "arg1", "arg2"]}agent-exec executes args as argv. It does not run commands through a shell, and it does not accept commands from query-string parameters.
Practical implications:
GET /api/execnever executes. It returns HTTP 405.POST /api/exec?cmd=...andPOST /api/exec?args=...do not execute query-string commands.- Shell metacharacters such as
&&,;,|, redirection, and subshell syntax are not interpreted by agent-exec itself. - ACL matching uses
args.join(' '). exec.denyis evaluated beforeexec.allow.- Plain string ACL rules are exact matches only. Use explicit glob rules with
*or regex rules with/.../when you intentionally want broader matching. - Request body fields other than
argsare rejected.cmd,command,env,cwd, andshellare not accepted by/api/execin v0.1. - If you allow a tool such as
npm test, that tool may run project scripts. agent-exec controls the outer execution boundary; it is not a sandbox for allowed tools.
agent-exec is default-deny for machine operations. Fresh installs allow only aexec --version as a self-test command so agents can verify that /api/exec works.
Edit the host settings file created by aexec setup:
~/.to-agent/agent-exec/settings.json{
"exec": {
"allow": ["aexec --version", "pwd", "echo *"],
"deny": ["/^sudo/", "/rm\\s+-rf/"]
}
}deny is evaluated before allow. Configure ACLs carefully and run agent-exec as a least-privileged OS user.
ACL rule types:
| Rule | Meaning |
|---|---|
"aexec --version" |
Plain string. Exact match against args.join(' '). |
"echo *" |
Glob. Explicit wildcard match; this allows any arguments to echo. |
"/^sudo/" |
Regexp. Explicit /.../ pattern. |
"*" |
Allow-all unless denied. Avoid on shared or public-facing machines. |
A rule like "cmd *" allows any arguments to cmd. Use it only when the command itself is trusted to enforce safe behavior. exec.deny is always evaluated before exec.allow.
aexec setup creates ~/.to-agent/agent-exec/settings.json. This is the normal file to edit.
Settings are split into two groups so the behavior is predictable.
These settings are reloaded automatically, without aexec refresh or restart:
exec.allowexec.denyip.allowip.denytimeoutMsmaxOutputBytesmaxStreamBytesmaxConcurrentExeckillGraceMsaudit.enabledaudit.file
These settings require aexec restart because they are used while the server is starting or while plugins are snapshotted:
.env,API_KEY,HOST,PORTAGENT_EXEC_ENABLED,AGENT_EXEC_ALLOW_QUERY_API_KEYmaxRequestBodyBytes,rateLimit- plugin create / enable / runtime settings edits
- restart is recommended after plugin remove / disable to fully unload runtime code
There is no top-level aexec refresh: policy settings reload automatically, and plugin/runtime changes need a restart. To see exactly which files are used and which settings require restart:
aexec configPlugins add documentation and optional command behavior.
aexec plugin list
aexec plugin create --name=mytool --command=mytool
aexec plugin enable --name=mytool
aexec plugin disable --name=mytool
aexec plugin doctoraexec plugin create prints the generated settings.json by default. Review its exec.allow rules before restart. Use --silent or --quiet to suppress that output.
Plugin changes are restart-aware. After creating or editing plugin runtime behavior, run:
aexec restartPlugin trust boundary:
- Skill-only plugins are documentation only.
- Exec plugins may add hooks and routes, but normal execution still goes through ACL-checked command execution.
- Trusted plugins are trusted host code. A trusted plugin may use direct
api.runbehavior and should be reviewed like code running as the agent-exec OS user. - Do not install unreviewed trusted plugins.
| Command | Purpose |
|---|---|
aexec setup |
Create local config and API key |
aexec start |
Start server in background |
aexec start -f |
Start server in foreground |
aexec start -f --public |
Start in foreground bound to 0.0.0.0 |
aexec share --ip <host> |
Print a prompt using an explicit reachable host |
aexec stop |
Stop server |
aexec stop --force --port 3333 |
Force kill the process bound to a port |
aexec restart |
Restart server |
aexec restart --force -f --public |
Force restart in foreground for canary testing |
aexec status |
Show server status |
aexec config |
Show config files and reload behavior |
aexec share |
Print prompt for another AI agent |
aexec key rotate |
Rotate the local API key |
aexec starterkit |
Optional plugin generation for installed AI tools |
aexec plugin ... |
Manage plugins |
Run aexec <command> --help for command-specific help.
agent-exec is not a sandbox by itself. It is a policy-gated execution surface.
It is SSH-like machine access for AI agents, but it is not SSH-compatible and is not an SSH replacement.
agent-exec provides the mechanism:
- API key authentication
- ACL enforcement
- timeout, output, stream, and concurrency limits
- local JSONL audit log without raw API keys or stdout/stderr bodies
- explicit
AGENT_EXEC_ENABLEDmaster switch - self-hosted operation
You are responsible for:
- what commands you allow
- avoiding direct public-internet exposure
- running behind localhost, VPN, firewall, TLS termination, or a trusted network
- avoiding plain HTTP on public networks
- running as a least-privileged OS user
- firewall/VPN/IP allowlists
- process and filesystem isolation
- rotating the API key if it leaks:
aexec key rotate
Same principle as SSH: the daemon provides the access surface. What you allow through it is the administrator's decision.
Apache License 2.0.
The open-source core is licensed under Apache-2.0. Commercial services and to-agent trademarks may be offered under separate terms.
