@porio/cli
v0.2.0
Published
Porio CLI for editing deployed agents with Claude Code
Readme
@porio/cli
CLI for editing deployed Porio agents from your terminal with Claude Code. Published on npm as @porio/cli; the binary is porio.
Pulls an agent's live source down into a local workspace, installs a project-scoped Claude Code skill, and watches the workspace so every save auto-pushes back to the deployed agent. Live preview is the existing embed at https://app.porio.ai/agents/<id>/embed.
v0, admin-only. Tokens are short-lived JWTs (24h) issued by
app.porio.aiafter an admin clicks Edit in Claude onporio.ai/agent/<id>.
Install
Nothing to install up front — invoke via npx:
npx -y -p @porio/cli porio edit <agentId> --token=<jwt>Or install globally:
npm i -g @porio/cli
porio edit <agentId> --token=<jwt>Requires Node >= 20.
Commands
porio edit <agentId> --token=<jwt> [--endpoint=...] [--dir=./porio-agents]
porio pull <agentId> --token=<jwt>
porio push <agentId> --token=<jwt>
porio watch <agentId> --token=<jwt>
porio whoami --token=<jwt>| Command | What it does |
| -------- | ------------------------------------------------------------------------------------------------------------ |
| edit | Full bootstrap. Pulls files, installs the ./.claude/skills/porio-agent/SKILL.md stub, then starts watch. |
| pull | One-shot fetch: writes the agent's files into ./porio-agents/<id>/files/. |
| push | One-shot full-replace: POSTs every file under ./porio-agents/<id>/files/ back to the server. |
| watch | chokidar watcher with a 500ms debounce that calls push on save. |
| whoami | Locally decodes the JWT payload and round-trips agent.pull to confirm the token still works. |
Flags
--token=<jwt>— required, short-lived edit token. Also readsPORIO_TOKENenv.--endpoint=<url>— defaults tohttps://app.porio.ai. Also readsPORIO_ENDPOINTenv.--dir=<path>— workspace root, defaults to./porio-agents. Each agent lives at<dir>/<agentId>/.
Typical flow
- As an admin, open
https://porio.ai/agent/<id>and click Edit in Claude. - Copy the
npx porio@latest edit ...command, paste it in a terminal inside the project you want to host the workspace from. - The CLI pulls files into
./porio-agents/<id>/files/, drops aCLAUDE.mdnext to them, installs./.claude/skills/porio-agent/SKILL.md, and starts the watcher. - Open Claude Code in the same directory and invoke the
/porio-agentskill. EditApp.tsx,styles.css, orworker.ts— every save auto-pushes. - Reload
https://app.porio.ai/agents/<id>/embedin a browser tab to see your changes.
Workspace layout
.
├── .claude/
│ └── skills/
│ └── porio-agent/
│ └── SKILL.md # project-scoped skill stub installed by `porio edit`
└── porio-agents/
└── <agentId>/
├── CLAUDE.md # primer for Claude Code, written on pull
├── .porio.json # endpoint, token hint, file hashes, timestamps
└── files/
├── App.tsx
├── styles.css
└── worker.tsOnly files under files/ are pushed.
Skill installation
porio edit writes a project-scoped skill at ./.claude/skills/porio-agent/SKILL.md — not the global ~/.claude/skills/ directory. This avoids permission prompts and cross-project pollution. Invoke it as /porio-agent from Claude Code.
The skill body is inlined in the CLI binary (no MCP server in v0).
Auth + revocation
Tokens are HS256 JWTs signed with BETTER_AUTH_SECRET server-side. Payload shape:
{
"sub": "<userId>",
"orgId": "<orgId>",
"agentId": "<agentId>",
"scope": "edit",
"iat": 1735000000,
"exp": 1735086400
}- 24h TTL.
- Stateless — no DB row, no KV entry.
- Per-token revocation is not supported in v0. To revoke every outstanding token, rotate
BETTER_AUTH_SECRET(also nukes every activeapp.porio.aisession — known op perCLAUDE.md). Otherwise wait for expiry. - The token is bound to a single
agentId; the server rejects pulls/pushes for any other agent.
Endpoints used
POST <endpoint>/api/agent.pull—{ agentId }→{ agent, files, embedUrl }POST <endpoint>/api/agent.push—{ agentId, files }→{ agent }
Both expect Authorization: Bearer <jwt> and are gated by the server-side editJwt middleware. The admin.editToken issuer lives on the admin router and is admin-only.
Publishing
Published as @porio/cli (the unscoped porio name was blocked by npm's similarity rules — too close to existing porek / poi). The bin name stays porio, so the user-facing command is npx -y -p @porio/cli porio edit ....
To cut a new version:
cd porio-cli
npm version patch # or minor / major
npm publish # access: public is in package.json publishConfigLicense
UNLICENSED (internal). Make this MIT before the first public publish.
