{"id":"3a1b84c9-080b-4175-a8c9-5a5ea1aba0c2","entityType":"agent","slug":"clawhub-psyb0t-pibox","name":"pibox","canonicalUrl":"https://www.xpersona.co/agent/clawhub-psyb0t-pibox","canonicalPath":"/agent/clawhub-psyb0t-pibox","generatedAt":"2026-10-10T10:43:20.218Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-10T04:58:14.784Z","emptyReason":null},"description":"Install, configure, or run pi-coding-agent through the pibox wrapper, or connect to its HTTP, MCP, Telegram, or cron surfaces.","descriptionLabel":"Source description","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 1.7K downloads reported by the source. Last updated 10/10/2026.","installCommand":"clawhub skill install s17fq93tmpky791n7516jcn08n83sfn2:pibox","sourceUrl":"https://clawhub.ai/psyb0t/pibox","homepage":"https://clawhub.ai/psyb0t/skills/pibox","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/psyb0t/pibox","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/psyb0t/skills/pibox","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":64,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"pibox technical dossier on Xpersona with agent coverage, OPENCLEW support, and live trust metadata."},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-10T04:58:14.784Z","emptyReason":null},"protocols":[{"protocol":"OPENCLEW","label":"OpenClaw","status":"self-declared","notes":"Declared in the public agent profile."}],"capabilities":[],"verifiedCount":0,"selfDeclaredCount":1,"capabilityMatrix":{"rows":[{"key":"OPENCLEW","type":"protocol","support":"unknown","confidenceSource":"profile","notes":"Listed on profile"}],"flattenedTokens":"protocol:OPENCLEW|unknown|profile"}},"adoption":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-10T04:58:14.784Z","emptyReason":null},"stars":null,"forks":null,"downloads":1670,"packageName":null,"latestVersion":"0.19.0","tractionLabel":"1.7K downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-10T04:58:14.627Z","emptyReason":null},"lastUpdatedAt":"2026-10-10T04:58:14.784Z","lastCrawledAt":"2026-10-10T04:58:14.627Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-11T04:58:14.627Z","lastVerifiedAt":null,"highlights":[{"version":"0.19.0","createdAt":"2026-10-07T17:24:28.183Z","changelog":"pibox 0.19.0 - Updated REST API MCP server route: now mounted at `/mcp/` (with trailing slash); slashless `/mcp` still supported. - Documentation updates in SKILL.md to reflect API path changes and clarify security/safety details. - Removed obsolete skill-card.md file. - Minor clarifications and corrections in setup and usage instructions.","fileCount":4,"zipByteSize":14335},{"version":"0.18.4","createdAt":"2026-09-23T20:22:50.635Z","changelog":"- Removed the file: skill-card.md - No other user-facing feature or documentation changes in this version.","fileCount":4,"zipByteSize":13867},{"version":"0.18.3","createdAt":"2026-09-14T11:52:51.110Z","changelog":"- Rewrote documentation to emphasize use of the pibox wrapper CLI for all interactive and one-shot agent runs, replacing raw docker command examples. - Clarified the wrapper's role: it manages state directories, mounts, image selection, and handles sibling commands, simplifying user workflows. - Removed direct recommendations to assemble manual docker run invocations for frequent tasks; now instruct users to rely on pibox CLI. - Enhanced detail on wrapper-based operations, state preservation, and safe interaction with multiple installed agent wrappers. - Removed skill-card.md file (deprecated or superseded by new doc structure).","fileCount":4,"zipByteSize":13771},{"version":"0.18.2","createdAt":"2026-09-14T00:17:31.584Z","changelog":"## pibox 0.18.2 - Removed the file: skill-card.md. - No changes to core functionality or documentation outside the removal of this file.","fileCount":4,"zipByteSize":13440},{"version":"0.18.1","createdAt":"2026-09-13T09:23:16.566Z","changelog":"pibox 0.18.1 - Updated installation and configuration instructions in references/setup.md - Removed the skill card documentation file (skill-card.md) - No functional or endpoint changes—documentation-only update","fileCount":4,"zipByteSize":13493},{"version":"0.18.0","createdAt":"2026-09-13T08:15:33.194Z","changelog":"- Removed the file: skill-card.md. - No changes to features, APIs, or documented behavior.","fileCount":4,"zipByteSize":13280},{"version":"0.17.0","createdAt":"2026-09-13T02:50:07.843Z","changelog":"- Removed sample file skill-card.md from the project. - No functional or user-facing changes—documentation-only update.","fileCount":4,"zipByteSize":13342},{"version":"0.16.2","createdAt":"2026-09-13T00:32:37.866Z","changelog":"pibox 0.16.2 - Updated installation and configuration instructions (references/setup.md). - Removed outdated skill-card documentation file. - No functional or API changes—documentation update only.","fileCount":4,"zipByteSize":13298}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s17fq93tmpky791n7516jcn08n83sfn2:pibox","setupComplexity":"low","setupSteps":["Install using `clawhub skill install s17fq93tmpky791n7516jcn08n83sfn2:pibox` in an isolated environment before connecting it to live workloads.","No published capability contract is available yet, so validate auth and request/response behavior manually.","Review the upstream CLAWHUB listing at https://clawhub.ai/psyb0t/pibox before using production credentials."],"contract":{"contractStatus":"missing","authModes":[],"requires":[],"forbidden":[],"supportsMcp":false,"supportsA2a":false,"supportsStreaming":false,"inputSchemaRef":null,"outputSchemaRef":null,"dataRegion":null,"contractUpdatedAt":null,"sourceUpdatedAt":null,"freshnessSeconds":null},"invocationGuide":{"preferredApi":{"snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-psyb0t-pibox/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-psyb0t-pibox/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-psyb0t-pibox/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-psyb0t-pibox/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-psyb0t-pibox/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-psyb0t-pibox/trust\""],"jsonRequestTemplate":{"query":"summarize this repo","constraints":{"maxLatencyMs":2000,"protocolPreference":["OPENCLEW"]}},"jsonResponseTemplate":{"ok":true,"result":{"summary":"...","confidence":0.9},"meta":{"source":"CLAWHUB","generatedAt":"2026-10-10T10:43:20.214Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-psyb0t-pibox/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-psyb0t-pibox/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-psyb0t-pibox/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-psyb0t-pibox/trust"}},"reliability":{"evidence":{"source":"runtime-metrics","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No trust, reliability, or runtime telemetry is available."},"trust":{"status":"unavailable","handshakeStatus":"UNKNOWN","verificationFreshnessHours":null,"reputationScore":null,"p95LatencyMs":null,"successRate30d":null,"fallbackRate":null,"attempts30d":null,"trustUpdatedAt":null,"trustConfidence":"unknown","sourceUpdatedAt":null,"freshnessSeconds":null},"decisionGuardrails":{"doNotUseIf":["Contract metadata is missing or unavailable for deterministic execution."],"safeUseWhen":[],"riskFlags":["missing_or_unavailable_contract","trust_data_unavailable","schema_references_missing"],"operationalConfidence":"low"},"executionMetrics":{"observedLatencyMsP50":null,"observedLatencyMsP95":null,"estimatedCostUsd":null,"uptime30d":null,"rateLimitRpm":null,"rateLimitBurst":null,"lastVerifiedAt":null,"verificationSource":null},"runtimeMetrics":{"successRate":null,"avgLatencyMs":null,"avgCostUsd":null,"hallucinationRate":null,"retryRate":null,"disputeRate":null,"p50Latency":null,"p95Latency":null,"lastUpdated":null}},"benchmarks":{"evidence":{"source":"no-benchmark-data","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No benchmark suites or observed failure patterns are available."},"suites":[],"failurePatterns":[]},"artifacts":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-10T04:58:14.784Z","emptyReason":null},"readme":"Skill: pibox\n\nOwner: psyb0t\n\nSummary: Install, configure, or run pi-coding-agent through the pibox wrapper, or connect to its HTTP, MCP, Telegram, or cron surfaces.\n\nTags: latest:0.19.0\n\nVersion history:\n\nv0.19.0 | 2026-10-07T17:24:28.183Z | auto\n\npibox 0.19.0\n\n- Updated REST API MCP server route: now mounted at `/mcp/` (with trailing slash); slashless `/mcp` still supported.\n- Documentation updates in SKILL.md to reflect API path changes and clarify security/safety details.\n- Removed obsolete skill-card.md file.\n- Minor clarifications and corrections in setup and usage instructions.\n\nv0.18.4 | 2026-09-23T20:22:50.635Z | auto\n\n- Removed the file: skill-card.md\n- No other user-facing feature or documentation changes in this version.\n\nv0.18.3 | 2026-09-14T11:52:51.110Z | auto\n\n- Rewrote documentation to emphasize use of the pibox wrapper CLI for all interactive and one-shot agent runs, replacing raw docker command examples.\n- Clarified the wrapper's role: it manages state directories, mounts, image selection, and handles sibling commands, simplifying user workflows.\n- Removed direct recommendations to assemble manual docker run invocations for frequent tasks; now instruct users to rely on pibox CLI.\n- Enhanced detail on wrapper-based operations, state preservation, and safe interaction with multiple installed agent wrappers.\n- Removed skill-card.md file (deprecated or superseded by new doc structure).\n\nv0.18.2 | 2026-09-14T00:17:31.584Z | auto\n\n## pibox 0.18.2\n\n- Removed the file: skill-card.md.\n- No changes to core functionality or documentation outside the removal of this file.\n\nv0.18.1 | 2026-09-13T09:23:16.566Z | auto\n\npibox 0.18.1\n\n- Updated installation and configuration instructions in references/setup.md\n- Removed the skill card documentation file (skill-card.md)\n- No functional or endpoint changes—documentation-only update\n\nv0.18.0 | 2026-09-13T08:15:33.194Z | auto\n\n- Removed the file: skill-card.md.\n- No changes to features, APIs, or documented behavior.\n\nv0.17.0 | 2026-09-13T02:50:07.843Z | auto\n\n- Removed sample file skill-card.md from the project.\n- No functional or user-facing changes—documentation-only update.\n\nv0.16.2 | 2026-09-13T00:32:37.866Z | auto\n\npibox 0.16.2\n\n- Updated installation and configuration instructions (references/setup.md).\n- Removed outdated skill-card documentation file.\n- No functional or API changes—documentation update only.\n\nv0.16.1 | 2026-09-09T13:49:36.632Z | auto\n\n- Removed the file: skill-card.md.\n- No changes made to functionality or documentation, just a minor cleanup by deleting an unused file.\n\nv0.16.0 | 2026-09-09T12:03:12.668Z | auto\n\npibox 0.16.0\n\n- Added support for Pi's documented provider selection via `PIBOX_PROVIDER_*` for LLM upstreams; `ANTHROPIC_*` now noted as an optional shortcut.\n- Updated documentation to reference new provider env vars and clarified the recommended configuration method for upstream LLM APIs.\n- Removed deprecated or redundant references to Anthropic-specific environments in sample usage and instructions.\n- Deleted the obsolete `skill-card.md` documentation file.\n\nv0.15.13 | 2026-09-06T19:43:55.267Z | auto\n\n- Removed the file skill-card.md.\n- No changes to functionality or API; documentation cleanup only.\n\nv0.15.12 | 2026-09-04T14:19:06.888Z | auto\n\n- Removed the documentation file skill-card.md.\n- No feature or functionality changes; this update is documentation-only.\n- All user and programmatic interfaces remain unchanged.\n\nv0.15.11 | 2026-08-13T18:54:50.757Z | auto\n\nNo user-visible changes in this version.\n\n- Version bump with no detected file changes.\n- Existing features and behavior remain unchanged.\n\nv0.15.10 | 2026-08-13T17:03:05.809Z | auto\n\n- Removed the file skill-card.md.\n- No functional changes to logic, interfaces, or documentation apart from the file removal.\n\nv0.15.9 | 2026-08-09T14:20:44.069Z | auto\n\n- Removed the file: skill-card.md.\n- No changes to features, code, or configuration in this version.\n- Documentation/content in SKILL.md remains unchanged.\n\nv0.15.8 | 2026-08-01T20:29:50.904Z | auto\n\n- Removed the file: skill-card.md\n- No functional or user-facing changes; documentation update only.\n\nv0.15.7 | 2026-07-27T23:31:27.705Z | auto\n\n- Removed the file skill-card.md from the repository.\n- No changes to user-facing functionality.\n\nv0.15.6 | 2026-07-27T23:07:34.046Z | auto\n\npibox 0.15.6\n\n- Removed the file: skill-card.md\n- No functional or behavioral changes to the codebase are indicated.\n- Documentation and feature references remain unchanged.\n\nv0.15.5 | 2026-07-27T15:18:51.040Z | auto\n\n- Removed the file: skill-card.md.\n- No other feature or functional changes in this version.\n\nv0.15.4 | 2026-07-27T13:26:03.296Z | auto\n\n## pibox 0.15.4\n\n- Removed the file: `skill-card.md`\n- No other functional or documentation changes.\n\nv0.15.3 | 2026-07-26T12:07:41.560Z | auto\n\n- Removed the sample file skill-card.md.\n- No user-facing functionality changes. \n- Documentation and codebase are now cleaner without the unused skill-card.md file.\n\nv0.15.2 | 2026-07-26T09:24:10.023Z | auto\n\n- Removed the skill-card.md file.\n- No changes to functionality or features. \n- This update is documentation/metadata only.\n\nv0.15.1 | 2026-07-26T01:32:34.898Z | auto\n\n## pibox 0.15.1\n\n- Added explicit security and safety warnings to documentation, highlighting authentication requirements and destruction risks.\n- Clarified that unauthenticated API/MCP surfaces allow full destructive access when tokens are unset or empty.\n- Emphasized that destructive actions like DELETE have no undo, and must be used only with explicit user intent.\n- Removed legacy `skill-card.md` file.\n- Updated setup references and mode documentation for improved clarity.\n\nv0.15.0 | 2026-07-25T21:53:09.879Z | auto\n\n**Expanded multi-surface agent container for pi-coding-agent.**\n\n- Added support for seven distinct access methods: interactive shell, one-shot exec, REST API, OpenAI-compatible endpoint, MCP server, Telegram bot, and cron scheduler—all in a single image.\n- Introduced bearer-token authentication per surface (configurable via environment variables).\n- Detailed setup instructions and usage guidance for each mode, including restrictions and mutual exclusivity of foreground modes.\n- Documented API endpoints, file operations, auth model, and integration tips for scripting and agent interop.\n- Clarified workspace isolation, streaming behavior, and model override options.\n- Improved documentation for installation, configuration, and integration scenarios.\n\nArchive index:\n\nArchive v0.19.0: 4 files, 14335 bytes\n\nFiles: references/setup.md (12163b), skill-card.md (2288b), SKILL.md (21026b), _meta.json (125b)\n\nFile v0.19.0:SKILL.md\n\n---\nname: pibox\ndescription: \"Install, configure, or run pi-coding-agent through the pibox wrapper, or connect to its HTTP, MCP, Telegram, or cron surfaces.\"\nhomepage: https://github.com/psyb0t/docker-pibox\nuser-invocable: true\nmetadata:\n  { \"openclaw\": { \"emoji\": \"🥧\", \"primaryEnv\": \"PIBOX_URL\", \"requires\": { \"bins\": [\"docker\", \"curl\"] } } }\n---\n\n# pibox\n\n[pi-coding-agent](https://github.com/earendil-works/pi-mono/tree/main/packages/coding-agent) inside an [aicodebox](https://github.com/psyb0t/docker-aicodebox) container. One image, seven ways in: interactive shell, one-shot exec, HTTP REST API, OpenAI-compatible endpoint, MCP server, Telegram bot, cron scheduler.\n\nYou talk to pibox, pibox talks to pi, and Pi talks to the configured upstream LLM. Use `PIBOX_PROVIDER_*` for Pi's documented custom HTTP APIs, including LiteLLM and Anthropic-compatible endpoints. `ANTHROPIC_*` remains a compatibility shortcut for existing Anthropic Messages deployments.\n\nFor installation and configuration, see [references/setup.md](references/setup.md).\n\n## Agent execution\n\nUse `pibox` when it is on `PATH`. Run it from the workspace the user named.\nDo not assemble a new `docker run` command for routine interactive or one-shot\nwork. The wrapper owns the workspace mount, `~/.pi`, aicodebox state, SSH\nstate, image selection, and container lifecycle.\n\n```bash\npibox                                      # interactive Pi\npibox -p \"inspect this workspace\"           # one-shot work\npibox -p \"review this change\" --thinking high\nPIBOX_FULL=1 pibox -p \"run the full suite\"\n```\n\nConfigure the Pi upstream before the first run with `PIBOX_PROVIDER_*` or the\nsupported `ANTHROPIC_*` compatibility variables. Use an HTTP or MCP endpoint\nonly when the user asks for a service or provides an already-running remote\nURL. MCP plugins connect to a server. They do not replace the local wrapper.\n\nStart a local API and MCP server only when the user asks for one. Set the\nactual model identifiers and distinct bearer tokens:\n\n```bash\nPIBOX_DETACH=1 \\\nPIBOX_API_MODE=1 \\\nPIBOX_MCP_MODE=1 \\\nPIBOX_AVAILABLE_MODELS=your-model-id \\\nPIBOX_API_MODE_TOKEN=your-api-token \\\nPIBOX_MCP_MODE_TOKEN=your-mcp-token \\\npibox\n```\n\nIf `pibox`, `codexbox`, and `claudebox` were installed in the same command\ndirectory, a box can invoke a sibling command directly. The parent wrapper\npasses the real host paths and the sibling wrapper file. Do not set\n`AICODEBOX_HOST_*`, copy wrapper files, or manually mount another box's state\ndirectory. If the sibling command is absent, ask the user to install it or to\nchoose another approach.\n\n## Security & safety\n\n- **No auth when `PIBOX_API_MODE_TOKEN` is unset.** With it empty the REST/OpenAI-compatible API surface is UNAUTHENTICATED — anyone who can reach it gets full agent-execution and workspace file-read/write/delete access. NEVER expose such an instance on a network or to untrusted agents; set the token and bind to loopback / behind an authenticating proxy.\n- **No auth when `PIBOX_MCP_MODE_TOKEN` is unset.** Same story for the MCP surface (`/mcp/` or the sidecar) — empty token means unauthenticated `run_prompt`/file-tool access, and it does not fall back to `PIBOX_API_MODE_TOKEN`. Set it explicitly.\n- **Destructive & irreversible.** `DELETE /run/{id}`, `DELETE /files/{path}`, and the MCP `delete_file` tool remove state with no undo (canceled runs can't be resumed; deleted files are gone). An agent must NEVER call these unless the user explicitly asked for that exact action; confirm the specific target first, scope it to the current task, and never enumerate-then-bulk-delete. On a shared/multi-tenant instance a deletion can destroy another caller's in-flight run or workspace file — treat these routes as admin-only.\n\n## When To Use\n\n- Drive pi-coding-agent from a script/service instead of an interactive terminal (`/run`, `/openai/v1/chat/completions`, or MCP tools).\n- Wire pi into an OpenAI-SDK-compatible client (LangChain, openai-python) via the `/openai/v1/*` surface.\n- Give an MCP-aware agent (Claude, Cursor, OpenClaw) remote tool access to a pi-driven workspace.\n- Chat with pi from Telegram, with per-chat model/effort overrides and file transfer.\n- Schedule recurring pi runs (standups, digests, periodic maintenance) via cron mode.\n- One-off container run for a single prompt (CI step, quick script) via one-shot exec.\n\n## When NOT To Use\n\n- Don't run two foreground modes together except Telegram+Cron (cron runs in-thread inside telegram) — API set alongside anything else wins and the others don't start.\n- Don't expect `/openai/v1/chat/completions` to stream token-by-token when `tools` or a JSON schema is in play — those modes compute the full answer first and replay it as a single-shot SSE stream (still a valid stream, just not incremental). Plain chat streams incrementally.\n- Don't rely on `PIBOX_MCP_MODE_TOKEN` falling back to `PIBOX_API_MODE_TOKEN` — MCP has its own bearer, no fallback.\n- Don't point multiple concurrent runs at the same workspace — the API/OAI layer returns 409 \"workspace busy\" while a run is in flight in that workspace.\n\n## Interactive shell mode\n\nRun `pibox` with no mode variables or arguments. The wrapper starts Pi in the\ncurrent workspace and preserves its host state.\n\n```bash\npibox\n```\n\nAuth: none at the container boundary. Pi uses the upstream provider variables in [references/setup.md](references/setup.md#llm-upstream).\n\n## One-shot exec mode\n\n`pibox -p \"<prompt>\"` runs Pi non-interactively and writes the result to\nstdout, then exits. The wrapper forwards Pi flags unchanged.\n\n```bash\npibox -p \"list the files in this workspace\"\n```\n\nAny Pi CLI flag works here (`--model`, `--thinking`, `--session`, etc.). Auth: none at the container boundary. Pi uses the upstream provider variables in [references/setup.md](references/setup.md#llm-upstream).\n\n## REST API mode\n\n`PIBOX_API_MODE=1`. FastAPI server on `:8080` (override `PIBOX_API_MODE_PORT`). **Requires `PIBOX_AVAILABLE_MODELS=<csv>`** — the server refuses to boot without it (no sensible default; pi can drive any provider's models).\n\n```bash\ndocker run -d --network host \\\n  -e PIBOX_API_MODE=1 \\\n  -e PIBOX_API_MODE_TOKEN=your-secret \\\n  -e PIBOX_AVAILABLE_MODELS=glm-4.6,glm-4.5-air \\\n  -e ANTHROPIC_AUTH_TOKEN=your-token \\\n  -e ANTHROPIC_BASE_URL=https://api.z.ai/api/anthropic \\\n  -e ANTHROPIC_MODEL=glm-4.6 \\\n  -v \"$PWD/workspace:/workspace\" \\\n  psyb0t/pibox:latest\n```\n\n| Method | Path | What it does |\n|--------|------|--------------|\n| `GET` | `/healthz` | liveness — `{ok, adapter}`, unauthenticated |\n| `GET` | `/status` | in-flight runs + busy workspaces |\n| `POST` | `/run` | run the agent — sync by default; body `async` or `fireAndForget` makes it fire-and-poll |\n| `GET` | `/run/result?runId=<id>` | poll a run started with `async`/`fireAndForget` |\n| `DELETE` | `/run/{id}` | cancel an in-flight run (kills the subprocess) |\n| `GET` | `/files` | list the workspace root — `{entries: [{name, type, size?}, ...]}` |\n| `GET` | `/files/{path}` | list a sub-directory, or stream a file's bytes |\n| `PUT` | `/files/{path}` | upload — raw request body becomes the file contents; parent dirs auto-created |\n| `DELETE` | `/files/{path}` | delete a file (refuses directories — 400) |\n| `POST` | `/openai/v1/chat/completions` | OpenAI-compatible chat (see below) |\n| `GET` | `/openai/v1/models` | model list, from `PIBOX_AVAILABLE_MODELS` |\n| `POST` | `/mcp/` | MCP server (streamable HTTP) — mounted only when `PIBOX_MCP_MODE=1`. Slashless `/mcp` reaches the same handler |\n\nAll `/files/*` paths resolve against the workspace root with traversal checking — `..` segments that escape the root return 400. Every route except `/healthz` is gated by `Authorization: Bearer <PIBOX_API_MODE_TOKEN>` when that var is set; empty/unset token = no auth.\n\n**No auth when `PIBOX_API_MODE_TOKEN` is unset.** With it empty the API is UNAUTHENTICATED — anyone who can reach it gets run-the-agent and workspace file-read/write/delete access. NEVER expose such an instance on a network or to untrusted agents; set the token and bind to loopback / behind an authenticating proxy.\n\n**Destructive & irreversible.** `DELETE /run/{id}` kills the in-flight subprocess with no undo, and `DELETE /files/{path}` deletes a workspace file with no undo. An agent must NEVER call either unless the user explicitly asked for that exact action; confirm the specific target first; scope it to the current task; never enumerate-then-bulk-delete. On a shared/multi-tenant instance this can disrupt or destroy another caller's run or data — treat these routes as admin-only.\n\n```bash\n# sync run\ncurl -s http://localhost:8080/run \\\n  -H \"Authorization: Bearer your-secret\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"prompt\": \"say HELLO\", \"workspace\": \"/workspace\"}'\n\n# async run, then poll\nRUN_ID=$(curl -s http://localhost:8080/run \\\n  -H \"Authorization: Bearer your-secret\" -H \"Content-Type: application/json\" \\\n  -d '{\"prompt\": \"long task\", \"async\": true}' | jq -r .runId)\ncurl -s \"http://localhost:8080/run/result?runId=$RUN_ID\" \\\n  -H \"Authorization: Bearer your-secret\"\n\n# cancel it\ncurl -s -X DELETE \"http://localhost:8080/run/$RUN_ID\" \\\n  -H \"Authorization: Bearer your-secret\"\n\n# upload / download / list / delete a workspace file\ncurl -sS -X PUT -H \"Authorization: Bearer your-secret\" \\\n  --data-binary @local.txt http://localhost:8080/files/notes/hello.txt\ncurl -sS -H \"Authorization: Bearer your-secret\" \\\n  http://localhost:8080/files/notes/hello.txt\ncurl -sS -H \"Authorization: Bearer your-secret\" \\\n  http://localhost:8080/files/notes | jq\ncurl -sS -X DELETE -H \"Authorization: Bearer your-secret\" \\\n  http://localhost:8080/files/notes/hello.txt\n```\n\n**`POST /run`** body fields: `prompt` (required), `workspace`, `model`, `systemPrompt`, `appendSystemPrompt`, `jsonSchema`, `noContinue`, `resume`, `timeoutSeconds`, `thinking`, `noTools`, `toolsAllowlist`, `extraArgs`, `async`, `fireAndForget`, `includeRaw`. With `jsonSchema` set the response is verbose: `text`, `json` (schema-validated), `events`, `sessionId`, `usage`, `attempts` (per-retry breakdown, up to 3 self-correction retries on parse/validation failure). Without `jsonSchema` the response is lean: `{runId, workspace, exitCode, text}`.\n\n## OpenAI-compatible endpoint mode\n\nSame `PIBOX_API_MODE=1` server, `POST /openai/v1/chat/completions` and `GET /openai/v1/models`. Drop-in for any OpenAI-SDK client — point the base URL at `http://host:8080/openai/v1` and set the model to one of `PIBOX_AVAILABLE_MODELS`.\n\n```bash\ncurl -s http://localhost:8080/openai/v1/chat/completions \\\n  -H \"Authorization: Bearer your-secret\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"model\": \"glm-4.6\",\n    \"messages\": [{\"role\": \"user\", \"content\": \"say HELLO\"}]\n  }'\n```\n\n**Streaming** (`\"stream\": true`): plain chat streams incrementally, one SSE chunk per token delta. Requests carrying `tools` or a JSON-schema constraint can't stream token-by-token (the answer only exists once fully computed) — they're **buffered**: the whole response is computed, then replayed as a single-shot SSE stream (role chunk → one content/tool_calls delta → finish chunk → `[DONE]`). The client's streaming parser is satisfied either way.\n\n**Tools / `tool_choice`** (OpenAI client-executed tool calling): send `tools` (OpenAI function-schema array) and optionally `tool_choice` (`auto`/`none`/`required`/`{\"type\":\"function\",\"function\":{\"name\":...}}`). pibox's own internal tools (bash, file edits) default OFF while in tool mode so the model behaves as a pure function-calling LLM — override with header `x-aicodebox-no-tools: 0` to re-enable the hybrid. The response comes back as `tool_calls` + `finish_reason: \"tool_calls\"`, exactly like OpenAI; you execute the tool client-side and send the result back in the next message round.\n\n**`response_format` / JSON-schema**: standard OpenAI `response_format` body field —`{\"type\": \"text\"}` (default), `{\"type\": \"json_object\"}` (force parseable JSON, no shape constraint), or `{\"type\": \"json_schema\", \"json_schema\": {\"name\": ..., \"schema\": {...}}}` (schema-validated, with up to 3 self-correction retries on failure → 422 if still invalid). `tools` and `response_format` **compose** in one request: a tool-call turn returns `tool_calls` (not schema-checked); the model's final answer (no more tool calls) is what gets schema-validated.\n\nExtra `x-aicodebox-*` headers (workspace pinning, session continuation, extra args, timeout, tools allowlist) are documented in [references/setup.md](references/setup.md#openai-endpoint-headers). Upstream provider errors (auth failure, rate limit, content-safety rejection) surface as HTTP 400, not a silent empty response.\n\n## MCP server mode\n\n`PIBOX_MCP_MODE=1`. Exposes an [MCP](https://modelcontextprotocol.io) (streamable HTTP) surface with 5 tools: `run_prompt`, `list_files`, `read_file`, `write_file`, `delete_file`. Coexists with any foreground mode:\n\n| Foreground | MCP placement |\n|---|---|\n| API mode (`PIBOX_API_MODE=1`) | mounted at `/mcp/` on the API port — no extra process |\n| Telegram / Cron / passthrough / none | sidecar uvicorn on its own port, `PIBOX_MCP_MODE_PORT` (default `8081`), mounted at the port root |\n\n```bash\nclaude mcp add --transport http pibox http://localhost:8080/mcp/ \\\n  --header \"Authorization: Bearer your-mcp-token\"\n```\n\nRaw JSON-RPC (debugging, non-MCP-aware callers):\n\n```bash\ncurl -s http://localhost:8080/mcp/ \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Accept: application/json, text/event-stream\" \\\n  -H \"Authorization: Bearer your-mcp-token\" \\\n  -d '{\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"tools/list\"}'\n```\n\n`run_prompt(prompt, workspace?, model?, system_prompt?, append_system_prompt?, no_continue=true, resume?, thinking?, json_schema?)` invokes the agent and returns its text. `list_files`/`read_file`/`write_file`/`delete_file` operate on workspace-relative paths with the same traversal guard as the REST `/files` endpoints.\n\n**Destructive & irreversible.** `delete_file` removes a workspace file with no undo. An agent must NEVER call it unless the user explicitly asked for that exact action; confirm the specific target first; scope it to the current task; never enumerate-then-bulk-delete. On a shared/multi-tenant instance this can destroy another caller's workspace data — treat it as admin-only.\n\nAuth: `PIBOX_MCP_MODE_TOKEN=<token>` — bearer via `Authorization: Bearer …`, or `?apiToken=…` query param for clients that can't set headers. Empty = no auth. **No fallback to `PIBOX_API_MODE_TOKEN`.**\n\n**No auth when `PIBOX_MCP_MODE_TOKEN` is unset.** With it empty the MCP surface is UNAUTHENTICATED — anyone who can reach it gets `run_prompt` (arbitrary agent execution) and workspace file read/write/delete access. NEVER expose such an instance on a network or to untrusted agents; set the token and bind to loopback / behind an authenticating proxy.\n\nMCP keeps DNS rebinding protection enabled. Loopback hosts and origins work by default; a reverse proxy, tunnel, or public DNS name needs its exact `Host` and browser `Origin` values allowed with `PIBOX_MCP_MODE_ALLOWED_HOSTS` and `PIBOX_MCP_MODE_ALLOWED_ORIGINS`, or MCP calls through it fail.\n\n## Telegram bot mode\n\n`PIBOX_TELEGRAM_MODE=1` + `PIBOX_TELEGRAM_MODE_TOKEN=<token from @BotFather>`.\n\n- Text in → pi runs → Markdown→HTML rendered response back.\n- File uploads land in the chat's workspace. `[SEND_FILE: path]` in pi's output delivers workspace files as Telegram attachments.\n- Per-chat overrides: `/model`, `/effort` (maps to pi's `--thinking` levels), `/system_prompt`, `/append_system_prompt`. Persisted across restarts.\n- `/cancel` kills the in-flight run. `/reload` re-reads config. `/config` dumps merged settings. `/status` shows in-flight state. `/fetch <path>` downloads a file. `/start`, `/help` for basics.\n- Replies to cron messages inject the job's instruction + result so pi has full context for follow-ups.\n\nConfig at `$HOME/.aicodebox/telegram.yml` (override via `PIBOX_TELEGRAM_MODE_CONFIG`):\n\n```yaml\nallowed_chats: [-100123, 42]\ndefault:\n  model: glm-4.6\n  workspace: shared\nchats:\n  -100123:\n    workspace: alpha\n    allowed_users: [10, 20]\n```\n\nAuth: chat/user allowlisting via the config yaml (`allowed_chats`, per-chat `allowed_users`) — no separate bearer token, the bot token itself gates who can even message it.\n\n## Cron scheduler mode\n\n`PIBOX_CRON_MODE=1` + `PIBOX_CRON_MODE_FILE=/path/to/cron.yaml`. 6-field cron schedules via croniter. Each job fires pi with the given instruction on schedule.\n\n```yaml\njobs:\n  - name: morning-standup\n    schedule: \"0 0 9 * * 1-5\"\n    instruction: |\n      Summarize what changed in /workspace since yesterday.\n      Be brief. One paragraph max.\n    workspace: myproject\n    telegram_chat_id: -100123\n    model: glm-4.6\n    thinking: low\n```\n\n`PIBOX_CRON_MODE_HISTORY_DIR` (default `$HOME/.aicodebox/cron`) is the whole cron state root. Each run gets a history dir at `<root>/history/<workspace>/<timestamp>-<job>/` with `meta.json`, `stdout.log`, `stderr.log`, `result.txt`. If telegram is also configured, `telegram.json` lands there too and the next run's prompt gets a \"prior run\" hint so pi can reference its own history without you wiring it up. A per-job summary jsonl is appended at `<root>/<job>.jsonl`. Running alongside Telegram mode (`PIBOX_TELEGRAM_MODE=1` + `PIBOX_CRON_MODE=1`) runs cron in-thread inside the telegram process — the only foreground-mode pairing allowed.\n\nAuth: none — this is a scheduled background job, not a request-driven surface. `telegram_chat_id` on a job routes its result through the (already-authenticated) Telegram bot if set; setting it to `0` opts that job out of an inherited default. A successful job with an explicit recipient notifies even when its result text is empty; a failed job sends a failure notice.\n\n## Auth (LLM upstream)\n\nUse `PIBOX_PROVIDER_*` for Pi's documented custom HTTP APIs, including LiteLLM and Anthropic-compatible endpoints. `ANTHROPIC_*` remains a compatibility path for existing Anthropic Messages endpoints. The full configuration matrix and examples are in [references/setup.md](references/setup.md#llm-upstream).\n\n| Var | Purpose |\n|-----|---------|\n| `ANTHROPIC_AUTH_TOKEN` | Bearer token (Z.AI, direct Anthropic, etc.) |\n| `ANTHROPIC_API_KEY` | Same thing — pi reads both |\n| `ANTHROPIC_BASE_URL` | Endpoint override (default `https://api.anthropic.com`) |\n| `ANTHROPIC_MODEL` | Default model when the caller doesn't specify one |\n\nZ.AI's GLM models are a fast/cheap default: `ANTHROPIC_BASE_URL=https://api.z.ai/api/anthropic` + `ANTHROPIC_MODEL=glm-4.6`.\n\npi's thinking levels (`--thinking`): `off`, `minimal`, `low`, `medium`, `high`, `xhigh`. Exposed as `/effort` in Telegram mode and `thinking` in API/OAI requests.\n\n**Surface-level auth** (separate from the LLM upstream) is per-mode: `PIBOX_API_MODE_TOKEN` gates the REST + OAI routes, `PIBOX_MCP_MODE_TOKEN` gates MCP (no fallback between the two), Telegram gates by bot-token possession + chat/user allowlist, cron and interactive/exec modes have no surface auth (container-boundary trust). Both `PIBOX_API_MODE_TOKEN` and `PIBOX_MCP_MODE_TOKEN` default to empty, which means no auth — see [Security & safety](#security--safety) above before exposing either surface beyond localhost.\n\n## Typical Workflows\n\n**One-off task from a script, no server:**\n\n```bash\ndocker run --rm -e ANTHROPIC_AUTH_TOKEN=$TOKEN -e ANTHROPIC_BASE_URL=$BASE_URL \\\n  -e ANTHROPIC_MODEL=glm-4.6 -v \"$PWD:/workspace\" \\\n  psyb0t/pibox:latest -p \"summarize the diff in /workspace\"\n```\n\n**Long-running server, drive it with curl:**\n\n```bash\ndocker run -d --network host -e PIBOX_API_MODE=1 -e PIBOX_API_MODE_TOKEN=$SECRET \\\n  -e PIBOX_AVAILABLE_MODELS=glm-4.6 -e ANTHROPIC_AUTH_TOKEN=$TOKEN \\\n  -e ANTHROPIC_BASE_URL=$BASE_URL -v \"$PWD/workspace:/workspace\" psyb0t/pibox:latest\ncurl -s http://localhost:8080/run -H \"Authorization: Bearer $SECRET\" \\\n  -H \"Content-Type: application/json\" -d '{\"prompt\": \"run the tests and report failures\"}'\n```\n\n**Structured extraction via JSON schema:**\n\n```bash\ncurl -s http://localhost:8080/run -H \"Authorization: Bearer $SECRET\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"prompt\": \"extract TODOs from /workspace\", \"jsonSchema\": {\"type\":\"object\",\"properties\":{\"todos\":{\"type\":\"array\",\"items\":{\"type\":\"string\"}}},\"required\":[\"todos\"]}}'\n```\n\n**Wire an MCP-aware agent (Claude Code, OpenClaw) to a running pibox:**\n\n```bash\nclaude mcp add --transport http pibox http://localhost:8080/mcp/ \\\n  --header \"Authorization: Bearer $MCP_TOKEN\"\n```\n\n**Chat + Telegram + scheduled digest, all on one box:**\n\n```bash\ndocker run -d --network host \\\n  -e PIBOX_TELEGRAM_MODE=1 -e PIBOX_TELEGRAM_MODE_TOKEN=$BOT_TOKEN \\\n  -e PIBOX_CRON_MODE=1 -e PIBOX_CRON_MODE_FILE=/config/cron.yaml \\\n  -e ANTHROPIC_AUTH_TOKEN=$TOKEN -e ANTHROPIC_BASE_URL=$BASE_URL \\\n  -v \"$PWD/workspace:/workspace\" -v \"$PWD/cron.yaml:/config/cron.yaml:ro\" \\\n  psyb0t/pibox:latest\n```\n\nFile v0.19.0:_meta.json\n\n{\n  \"ownerId\": \"kn79dhvmpjng4rp2jjk8k0v5xx80ccbk\",\n  \"slug\": \"pibox\",\n  \"version\": \"0.19.0\",\n  \"publishedAt\": 1791393868183\n}\n\nFile v0.19.0:references/setup.md\n\n# pibox setup\n\n## Requirements\n\n- Docker\n- An LLM endpoint supported by Pi's custom HTTP provider configuration. `PIBOX_PROVIDER_*` accepts an endpoint URL, protocol, API key or token, and model. It covers LiteLLM, Anthropic Messages endpoints, and Google Generative AI. `ANTHROPIC_*` remains available for existing Anthropic-compatible deployments. Pi drives the model; pibox drives Pi.\n- A target workspace. Run the wrapper from that directory so it mounts the path and preserves Pi state.\n\n## Quick Install\n\n### Host wrapper\n\nInstall the wrapper for interactive and one-shot use:\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/psyb0t/docker-pibox/main/install.sh | bash\n```\n\nInstall `pibox`, `codexbox`, and `claudebox` in the same command directory,\nnormally `/usr/local/bin`, when a box needs to launch another. Each wrapper\nmounts sibling wrapper files read-only. The sibling wrapper then asks the host\nDocker daemon to mount its own data directory.\n\n### Interactive / one-shot (no server)\n\n```bash\npibox\npibox -p \"inspect this workspace\"\nPIBOX_FULL=1 pibox -p \"run the full test suite\"\n```\n\nUse the wrapper for normal interactive and one-shot work. It handles the\nworkspace mount, Pi state, aicodebox state, SSH state, image selection, and\nnested launch context. Do not construct a `docker run` command unless the user\nexplicitly asks for a direct container deployment.\n\n### REST / OpenAI-compatible / MCP server\n\n```bash\ndocker run -d --name pibox --network host \\\n  -e PIBOX_API_MODE=1 \\\n  -e PIBOX_API_MODE_TOKEN=your-secret \\\n  -e PIBOX_AVAILABLE_MODELS=glm-4.6,glm-4.5-air \\\n  -e PIBOX_MCP_MODE=1 \\\n  -e PIBOX_MCP_MODE_TOKEN=your-mcp-secret \\\n  -e ANTHROPIC_AUTH_TOKEN=your-token \\\n  -e ANTHROPIC_BASE_URL=https://api.z.ai/api/anthropic \\\n  -e ANTHROPIC_MODEL=glm-4.6 \\\n  -v \"$PWD/workspace:/workspace\" \\\n  psyb0t/pibox:latest\n```\n\n`--network host` is convenient for local use; for anything else publish the port explicitly (`-p 8080:8080`) instead.\n\n**Verify:** `curl http://localhost:8080/healthz` returns `{\"ok\": true, \"adapter\": \"pi\"}`.\n\n### Telegram bot\n\n```bash\ndocker run -d --name pibox-tg \\\n  -e PIBOX_TELEGRAM_MODE=1 \\\n  -e PIBOX_TELEGRAM_MODE_TOKEN=your-bot-token \\\n  -e ANTHROPIC_AUTH_TOKEN=your-token \\\n  -e ANTHROPIC_BASE_URL=https://api.z.ai/api/anthropic \\\n  -e ANTHROPIC_MODEL=glm-4.6 \\\n  -v \"$PWD/workspace:/workspace\" \\\n  -v \"$PWD/telegram.yml:/home/aicode/.aicodebox/telegram.yml:ro\" \\\n  psyb0t/pibox:latest\n```\n\nRequires a `telegram.yml` with at least `allowed_chats` set (see [Telegram bot mode](../SKILL.md#telegram-bot-mode)) — the bot ignores messages from chats not on the allowlist.\n\n### Cron scheduler\n\n```bash\ndocker run -d --name pibox-cron \\\n  -e PIBOX_CRON_MODE=1 \\\n  -e PIBOX_CRON_MODE_FILE=/config/cron.yaml \\\n  -e ANTHROPIC_AUTH_TOKEN=your-token \\\n  -e ANTHROPIC_BASE_URL=https://api.z.ai/api/anthropic \\\n  -e ANTHROPIC_MODEL=glm-4.6 \\\n  -v \"$PWD/workspace:/workspace\" \\\n  -v \"$PWD/cron.yaml:/config/cron.yaml:ro\" \\\n  psyb0t/pibox:latest\n```\n\n### docker-compose (API + MCP)\n\n```yaml\nservices:\n  pibox:\n    image: psyb0t/pibox:latest\n    environment:\n      PIBOX_API_MODE: \"1\"\n      PIBOX_API_MODE_TOKEN: your-secret\n      PIBOX_AVAILABLE_MODELS: glm-4.6,glm-4.5-air\n      PIBOX_MCP_MODE: \"1\"\n      PIBOX_MCP_MODE_TOKEN: your-mcp-secret\n      ANTHROPIC_AUTH_TOKEN: your-token\n      ANTHROPIC_BASE_URL: https://api.z.ai/api/anthropic\n      ANTHROPIC_MODEL: glm-4.6\n    ports:\n      - \"8080:8080\"\n    volumes:\n      - ./workspace:/workspace\n    restart: unless-stopped\n```\n\n## Foreground Mode Rules\n\n`PIBOX_API_MODE`, `PIBOX_TELEGRAM_MODE`, `PIBOX_CRON_MODE` are the foreground modes. Priority order if multiple are set: API wins over everything. Telegram + Cron together is the one allowed pairing (cron runs in-thread inside the telegram process). If none are set, the container falls through to pi's own CLI (interactive shell, or one-shot exec if args are passed).\n\n`PIBOX_MCP_MODE` is independent of the above — it coexists with any foreground mode (mounted at `/mcp/` in API mode, sidecar elsewhere) or with none at all (sidecar only, no other surface reachable). The slashless `/mcp` spelling reaches the same handler; a standalone sidecar serves at its port root `/`.\n\n## Environment Variables\n\nNaming convention: `PIBOX_<MODE>_MODE=1` is the on/off flag, `PIBOX_<MODE>_MODE_<KNOB>=...` is its config. Non-mode-scoped vars (workspace, container name, available models) are bare `PIBOX_*`.\n\nThe image is built on [aicodebox](https://github.com/psyb0t/docker-aicodebox); the equivalent `AICODEBOX_*` names also work — the entrypoint translates `PIBOX_X` to `AICODEBOX_X` when only the pibox-prefixed one is set. If both are set, `AICODEBOX_*` wins.\n\n### Mode flags\n\n| Var | Default | What it does |\n|-----|---------|---------------|\n| `PIBOX_API_MODE` | `0` | Boot the HTTP API server (foreground) |\n| `PIBOX_TELEGRAM_MODE` | `0` | Boot the Telegram bot (foreground) |\n| `PIBOX_CRON_MODE` | `0` | Boot the cron scheduler (foreground; in-thread when telegram is also on) |\n| `PIBOX_MCP_MODE` | `0` | Expose MCP — mounted at `/mcp/` in API mode, or as a sidecar elsewhere |\n\n### API mode config\n\n| Var | Default | What it does |\n|-----|---------|---------------|\n| `PIBOX_API_MODE_PORT` | `8080` | Port the API server binds to |\n| `PIBOX_API_MODE_TOKEN` | empty | Bearer token for the REST + OpenAI-compatible surface. Empty = no auth — see [Security & safety](../SKILL.md#security--safety) |\n\n### Telegram mode config\n\n| Var | Default | What it does |\n|-----|---------|---------------|\n| `PIBOX_TELEGRAM_MODE_TOKEN` | — | Bot token from @BotFather (required) |\n| `PIBOX_TELEGRAM_MODE_CONFIG` | `~/.aicodebox/telegram.yml` | Path to the telegram config yaml |\n| `PIBOX_TELEGRAM_MODE_OVERRIDES` | `~/.aicodebox/telegram_overrides.json` | Per-chat override store (model/effort/system prompts) |\n\n### Cron mode config\n\n| Var | Default | What it does |\n|-----|---------|---------------|\n| `PIBOX_CRON_MODE_FILE` | — | Path to the cron yaml (required) |\n| `PIBOX_CRON_MODE_HISTORY_DIR` | `~/.aicodebox/cron` | Cron state root. Per-run history dirs live under `<root>/history/<workspace>/<timestamp>-<job>/` (`meta.json`, `stdout.log`, `stderr.log`, `result.txt`, `telegram.json`); per-job summaries append to `<root>/<job>.jsonl` |\n\n### MCP mode config\n\n| Var | Default | What it does |\n|-----|---------|---------------|\n| `PIBOX_MCP_MODE_PORT` | `8081` | Port the sidecar MCP server binds to (ignored when mounted inside API mode) |\n| `PIBOX_MCP_MODE_TOKEN` | empty | Bearer token for MCP. Empty = no auth — see [Security & safety](../SKILL.md#security--safety). No fallback to `PIBOX_API_MODE_TOKEN` |\n| `PIBOX_MCP_MODE_ALLOWED_HOSTS` | loopback hosts | Comma-separated MCP `Host` allowlist for DNS-rebinding protection. Add each reverse-proxy host name |\n| `PIBOX_MCP_MODE_ALLOWED_ORIGINS` | loopback HTTP origins | Comma-separated MCP browser Origin allowlist. Add each reverse-proxy origin |\n\n### Workspace & runtime\n\n| Var | Default | What it does |\n|-----|---------|---------------|\n| `PIBOX_WORKSPACE` | `/workspace` | Root workspace dir inside the container |\n| `PIBOX_CONTAINER_NAME` | `aicodebox` | Used to scope per-container state files in direct Docker runs. The host wrapper derives a per-workspace name. |\n| `PIBOX_AVAILABLE_MODELS` | — | **Required for API mode.** CSV list returned by `/openai/v1/models` and shown in the telegram `/model` picker. pibox registers every listed model with the upstream provider under `PIBOX_PROVIDER_API` |\n| `PIBOX_AVAILABLE_EFFORTS` | adapter list (`off,minimal,low,medium,high,xhigh`) | Override the effort/`--thinking` list shown by the telegram `/effort` picker (comma-separated) |\n\nUnder the aicodebox state directory (`$HOME/.aicodebox`, mounted from `PIBOX_STATE_DIR` by the wrapper): executables in `bin/` are on `PATH` ahead of everything else, for pi in every mode, for init scripts, and for `docker exec` shells; scripts in `init.d/*.sh` run once per container, after the image's own `/aicodebox-init.d/*.sh`, as `aicode` with passwordless sudo, with a failing script logged and the rest still run.\n\n### LLM upstream\n\n#### Generic custom HTTP provider\n\nUse these variables for Pi's documented custom HTTP APIs. They configure the upstream model Pi uses, not pibox's own OpenAI-compatible `/openai/v1` endpoint.\n\n| Var | Default | What it does |\n|-----|---------|--------------|\n| `PIBOX_PROVIDER_NAME` | `pibox` | Provider identifier. Lowercase letters, numbers, and `-` only. |\n| `PIBOX_PROVIDER_API` | `openai-completions` | `openai-completions`, `openai-responses`, `anthropic-messages`, or `google-generative-ai` |\n| `PIBOX_PROVIDER_BASE_URL` | none | Required upstream HTTP base URL |\n| `PIBOX_PROVIDER_API_KEY` | none | Required upstream API key or token |\n| `PIBOX_PROVIDER_MODEL` | none | Required default upstream model ID |\n\nLiteLLM example:\n\n```bash\ndocker run --rm --network host \\\n  -e PIBOX_PROVIDER_BASE_URL=http://127.0.0.1:4000/v1 \\\n  -e PIBOX_PROVIDER_API=openai-completions \\\n  -e PIBOX_PROVIDER_API_KEY=your-litellm-virtual-key \\\n  -e PIBOX_PROVIDER_MODEL=your-model-id \\\n  -v \"$PWD/workspace:/workspace\" \\\n  psyb0t/pibox:latest \\\n  -p \"list the files in /workspace\"\n```\n\nFor API mode, set `PIBOX_AVAILABLE_MODELS=your-model-id` too. Do not combine `PIBOX_PROVIDER_*` with `ANTHROPIC_BASE_URL`. pibox rejects the ambiguous configuration. The generic variables cover Pi's documented custom HTTP APIs, not every cloud-specific built-in provider.\n\n#### Anthropic compatibility\n\n| Var | Purpose |\n|-----|---------|\n| `ANTHROPIC_AUTH_TOKEN` | Bearer token (Z.AI, direct Anthropic, etc.) |\n| `ANTHROPIC_API_KEY` | Same thing — pi reads both |\n| `ANTHROPIC_BASE_URL` | Endpoint override (default `https://api.anthropic.com`) |\n| `ANTHROPIC_MODEL` | Default model when the caller doesn't specify one |\n\n## OpenAI endpoint headers\n\nNon-standard `x-aicodebox-*` request headers extend `POST /openai/v1/chat/completions` beyond stock OpenAI fields (legacy `x-claude-*` aliases also work for `workspace`/`continue`/`append-system-prompt`):\n\n| Header | Purpose |\n|---|---|\n| `x-aicodebox-workspace` | Pin the run to a workspace subpath instead of the ephemeral/default one |\n| `x-aicodebox-continue` | `1`/`true`/`yes` to continue the most recent session in that workspace instead of starting fresh |\n| `x-aicodebox-append-system-prompt` | Append text to the system prompt |\n| `x-aicodebox-json-schema` | JSON-encoded schema — fallback for clients that can't set the standard `response_format` body field (body field wins if both are set) |\n| `x-aicodebox-resume` | Resume a specific session id |\n| `x-aicodebox-extra-args` | Extra pi CLI args — JSON array or comma-separated string |\n| `x-aicodebox-timeout-seconds` | Per-request run timeout |\n| `x-aicodebox-tools-allowlist` | Restrict pi's own internal tools — JSON array or comma-separated string |\n| `x-aicodebox-no-tools` | `1`/`true`/`yes` to disable pi's internal tools; in OpenAI-tools mode this is the override to re-enable them (send `0`) |\n\n## Ports\n\n| Port | Default | Service |\n|---|---|---|\n| API/OAI/MCP-in-API | `8080` (`PIBOX_API_MODE_PORT`) | REST, `/openai/v1/*`, `/mcp/` (when `PIBOX_MCP_MODE=1`) |\n| MCP sidecar | `8081` (`PIBOX_MCP_MODE_PORT`) | MCP only, used when API mode is not the foreground |\n\nNo ports are opened for Telegram, cron, interactive, or one-shot exec modes — they're outbound-only or container-boundary-trusted.\n\n## Management\n\n```bash\ndocker logs -f pibox    # tail logs\ndocker stop pibox       # stop\ndocker rm pibox          # remove\ndocker pull psyb0t/pibox:latest  # update\n```\n\nCheck what's running inside a live API-mode container:\n\n```bash\ncurl -s http://localhost:8080/status -H \"Authorization: Bearer your-secret\" | jq\n```\n\n## OpenClaw / ClawHub Config\n\n```bash\nexport PIBOX_URL=http://localhost:8080\nexport PIBOX_API_MODE_TOKEN=<token>  # only if the server requires it\n```\n\nOr via `~/.openclaw/openclaw.json`:\n\n```json\n{\n  \"skills\": {\n    \"entries\": {\n      \"pibox\": {\n        \"env\": {\n          \"PIBOX_URL\": \"http://localhost:8080\",\n          \"PIBOX_API_MODE_TOKEN\": \"<token>\"\n        }\n      }\n    }\n  }\n}\n```\n\nFile v0.19.0:skill-card.md\n\n## Description:\n\nInstall, configure, or run pi-coding-agent through the pibox wrapper, or connect to its HTTP, MCP, Telegram, or cron surfaces.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[psyb0t](https://clawhub.ai/user/psyb0t)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers use pibox to run pi-coding-agent against selected workspaces and connect it to scripts, HTTP clients, MCP tools, Telegram, or scheduled jobs.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: An exposed API or MCP service without its own bearer token can grant agent execution and workspace file access to anyone who can reach it.\n\nMitigation: Set distinct API and MCP tokens and bind ports to loopback; add stronger access controls before any shared or public exposure.\n\nRisk: Piping an installer into a shell, using an unpinned image, or deploying with host networking increases installation and exposure risks.\n\nMitigation: Inspect the installer first, pin the Docker image by digest, and prefer explicit loopback port bindings to host networking.\n\nRisk: Agent access to broad workspace mounts and destructive file or run operations can cause irrecoverable data loss.\n\nMitigation: Mount only necessary workspaces, back up important data, and require explicit confirmation of a specific target before deletion.\n\n## Reference(s):\n\n- [pibox setup guide](artifact/references/setup.md)\n- [pibox project homepage](https://github.com/psyb0t/docker-pibox)\n- [pi-coding-agent](https://github.com/earendil-works/pi-mono/tree/main/packages/coding-agent)\n- [pibox on ClawHub](https://clawhub.ai/psyb0t/skills/pibox)\n\n## Skill Output:\n\n**Output Type(s):** [Text, Code, Shell commands, Configuration instructions]\n\n**Output Format:** [Markdown with code and shell examples]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [May run an agent that reads and changes files in a selected workspace.]\n\n## Skill Version(s):\n\n0.19.0 (source: ClawHub release metadata)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nArchive v0.18.4: 4 files, 13867 bytes\n\nFiles: references/setup.md (11237b), skill-card.md (2960b), SKILL.md (20404b), _meta.json (125b)\n\nFile v0.18.4:SKILL.md\n\n---\nname: pibox\ndescription: \"Install, configure, or run pi-coding-agent through the pibox wrapper, or connect to its HTTP, MCP, Telegram, or cron surfaces.\"\nhomepage: https://github.com/psyb0t/docker-pibox\nuser-invocable: true\nmetadata:\n  { \"openclaw\": { \"emoji\": \"🥧\", \"primaryEnv\": \"PIBOX_URL\", \"requires\": { \"bins\": [\"docker\", \"curl\"] } } }\n---\n\n# pibox\n\n[pi-coding-agent](https://github.com/earendil-works/pi-mono/tree/main/packages/coding-agent) inside an [aicodebox](https://github.com/psyb0t/docker-aicodebox) container. One image, seven ways in: interactive shell, one-shot exec, HTTP REST API, OpenAI-compatible endpoint, MCP server, Telegram bot, cron scheduler.\n\nYou talk to pibox, pibox talks to pi, and Pi talks to the configured upstream LLM. Use `PIBOX_PROVIDER_*` for Pi's documented custom HTTP APIs, including LiteLLM and Anthropic-compatible endpoints. `ANTHROPIC_*` remains a compatibility shortcut for existing Anthropic Messages deployments.\n\nFor installation and configuration, see [references/setup.md](references/setup.md).\n\n## Agent execution\n\nUse `pibox` when it is on `PATH`. Run it from the workspace the user named.\nDo not assemble a new `docker run` command for routine interactive or one-shot\nwork. The wrapper owns the workspace mount, `~/.pi`, aicodebox state, SSH\nstate, image selection, and container lifecycle.\n\n```bash\npibox                                      # interactive Pi\npibox -p \"inspect this workspace\"           # one-shot work\npibox -p \"review this change\" --thinking high\nPIBOX_FULL=1 pibox -p \"run the full suite\"\n```\n\nConfigure the Pi upstream before the first run with `PIBOX_PROVIDER_*` or the\nsupported `ANTHROPIC_*` compatibility variables. Use an HTTP or MCP endpoint\nonly when the user asks for a service or provides an already-running remote\nURL. MCP plugins connect to a server. They do not replace the local wrapper.\n\nStart a local API and MCP server only when the user asks for one. Set the\nactual model identifiers and distinct bearer tokens:\n\n```bash\nPIBOX_DETACH=1 \\\nPIBOX_API_MODE=1 \\\nPIBOX_MCP_MODE=1 \\\nPIBOX_AVAILABLE_MODELS=your-model-id \\\nPIBOX_API_MODE_TOKEN=your-api-token \\\nPIBOX_MCP_MODE_TOKEN=your-mcp-token \\\npibox\n```\n\nIf `pibox`, `codexbox`, and `claudebox` were installed in the same command\ndirectory, a box can invoke a sibling command directly. The parent wrapper\npasses the real host paths and the sibling wrapper file. Do not set\n`AICODEBOX_HOST_*`, copy wrapper files, or manually mount another box's state\ndirectory. If the sibling command is absent, ask the user to install it or to\nchoose another approach.\n\n## Security & safety\n\n- **No auth when `PIBOX_API_MODE_TOKEN` is unset.** With it empty the REST/OpenAI-compatible API surface is UNAUTHENTICATED — anyone who can reach it gets full agent-execution and workspace file-read/write/delete access. NEVER expose such an instance on a network or to untrusted agents; set the token and bind to loopback / behind an authenticating proxy.\n- **No auth when `PIBOX_MCP_MODE_TOKEN` is unset.** Same story for the MCP surface (`/mcp` or the sidecar) — empty token means unauthenticated `run_prompt`/file-tool access, and it does not fall back to `PIBOX_API_MODE_TOKEN`. Set it explicitly.\n- **Destructive & irreversible.** `DELETE /run/{id}`, `DELETE /files/{path}`, and the MCP `delete_file` tool remove state with no undo (canceled runs can't be resumed; deleted files are gone). An agent must NEVER call these unless the user explicitly asked for that exact action; confirm the specific target first, scope it to the current task, and never enumerate-then-bulk-delete. On a shared/multi-tenant instance a deletion can destroy another caller's in-flight run or workspace file — treat these routes as admin-only.\n\n## When To Use\n\n- Drive pi-coding-agent from a script/service instead of an interactive terminal (`/run`, `/openai/v1/chat/completions`, or MCP tools).\n- Wire pi into an OpenAI-SDK-compatible client (LangChain, openai-python) via the `/openai/v1/*` surface.\n- Give an MCP-aware agent (Claude, Cursor, OpenClaw) remote tool access to a pi-driven workspace.\n- Chat with pi from Telegram, with per-chat model/effort overrides and file transfer.\n- Schedule recurring pi runs (standups, digests, periodic maintenance) via cron mode.\n- One-off container run for a single prompt (CI step, quick script) via one-shot exec.\n\n## When NOT To Use\n\n- Don't run two foreground modes together except Telegram+Cron (cron runs in-thread inside telegram) — API set alongside anything else wins and the others don't start.\n- Don't expect `/openai/v1/chat/completions` to stream token-by-token when `tools` or a JSON schema is in play — those modes compute the full answer first and replay it as a single-shot SSE stream (still a valid stream, just not incremental). Plain chat streams incrementally.\n- Don't rely on `PIBOX_MCP_MODE_TOKEN` falling back to `PIBOX_API_MODE_TOKEN` — MCP has its own bearer, no fallback.\n- Don't point multiple concurrent runs at the same workspace — the API/OAI layer returns 409 \"workspace busy\" while a run is in flight in that workspace.\n\n## Interactive shell mode\n\nRun `pibox` with no mode variables or arguments. The wrapper starts Pi in the\ncurrent workspace and preserves its host state.\n\n```bash\npibox\n```\n\nAuth: none at the container boundary. Pi uses the upstream provider variables in [references/setup.md](references/setup.md#llm-upstream).\n\n## One-shot exec mode\n\n`pibox -p \"<prompt>\"` runs Pi non-interactively and writes the result to\nstdout, then exits. The wrapper forwards Pi flags unchanged.\n\n```bash\npibox -p \"list the files in this workspace\"\n```\n\nAny Pi CLI flag works here (`--model`, `--thinking`, `--session`, etc.). Auth: none at the container boundary. Pi uses the upstream provider variables in [references/setup.md](references/setup.md#llm-upstream).\n\n## REST API mode\n\n`PIBOX_API_MODE=1`. FastAPI server on `:8080` (override `PIBOX_API_MODE_PORT`). **Requires `PIBOX_AVAILABLE_MODELS=<csv>`** — the server refuses to boot without it (no sensible default; pi can drive any provider's models).\n\n```bash\ndocker run -d --network host \\\n  -e PIBOX_API_MODE=1 \\\n  -e PIBOX_API_MODE_TOKEN=your-secret \\\n  -e PIBOX_AVAILABLE_MODELS=glm-4.6,glm-4.5-air \\\n  -e ANTHROPIC_AUTH_TOKEN=your-token \\\n  -e ANTHROPIC_BASE_URL=https://api.z.ai/api/anthropic \\\n  -e ANTHROPIC_MODEL=glm-4.6 \\\n  -v \"$PWD/workspace:/workspace\" \\\n  psyb0t/pibox:latest\n```\n\n| Method | Path | What it does |\n|--------|------|--------------|\n| `GET` | `/healthz` | liveness — `{ok, adapter}`, unauthenticated |\n| `GET` | `/status` | in-flight runs + busy workspaces |\n| `POST` | `/run` | run the agent — sync by default; body `async` or `fireAndForget` makes it fire-and-poll |\n| `GET` | `/run/result?runId=<id>` | poll a run started with `async`/`fireAndForget` |\n| `DELETE` | `/run/{id}` | cancel an in-flight run (kills the subprocess) |\n| `GET` | `/files` | list the workspace root — `{entries: [{name, type, size?}, ...]}` |\n| `GET` | `/files/{path}` | list a sub-directory, or stream a file's bytes |\n| `PUT` | `/files/{path}` | upload — raw request body becomes the file contents; parent dirs auto-created |\n| `DELETE` | `/files/{path}` | delete a file (refuses directories — 400) |\n| `POST` | `/openai/v1/chat/completions` | OpenAI-compatible chat (see below) |\n| `GET` | `/openai/v1/models` | model list, from `PIBOX_AVAILABLE_MODELS` |\n| `POST` | `/mcp` | MCP server (streamable HTTP) — mounted only when `PIBOX_MCP_MODE=1` |\n\nAll `/files/*` paths resolve against the workspace root with traversal checking — `..` segments that escape the root return 400. Every route except `/healthz` is gated by `Authorization: Bearer <PIBOX_API_MODE_TOKEN>` when that var is set; empty/unset token = no auth.\n\n**No auth when `PIBOX_API_MODE_TOKEN` is unset.** With it empty the API is UNAUTHENTICATED — anyone who can reach it gets run-the-agent and workspace file-read/write/delete access. NEVER expose such an instance on a network or to untrusted agents; set the token and bind to loopback / behind an authenticating proxy.\n\n**Destructive & irreversible.** `DELETE /run/{id}` kills the in-flight subprocess with no undo, and `DELETE /files/{path}` deletes a workspace file with no undo. An agent must NEVER call either unless the user explicitly asked for that exact action; confirm the specific target first; scope it to the current task; never enumerate-then-bulk-delete. On a shared/multi-tenant instance this can disrupt or destroy another caller's run or data — treat these routes as admin-only.\n\n```bash\n# sync run\ncurl -s http://localhost:8080/run \\\n  -H \"Authorization: Bearer your-secret\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"prompt\": \"say HELLO\", \"workspace\": \"/workspace\"}'\n\n# async run, then poll\nRUN_ID=$(curl -s http://localhost:8080/run \\\n  -H \"Authorization: Bearer your-secret\" -H \"Content-Type: application/json\" \\\n  -d '{\"prompt\": \"long task\", \"async\": true}' | jq -r .runId)\ncurl -s \"http://localhost:8080/run/result?runId=$RUN_ID\" \\\n  -H \"Authorization: Bearer your-secret\"\n\n# cancel it\ncurl -s -X DELETE \"http://localhost:8080/run/$RUN_ID\" \\\n  -H \"Authorization: Bearer your-secret\"\n\n# upload / download / list / delete a workspace file\ncurl -sS -X PUT -H \"Authorization: Bearer your-secret\" \\\n  --data-binary @local.txt http://localhost:8080/files/notes/hello.txt\ncurl -sS -H \"Authorization: Bearer your-secret\" \\\n  http://localhost:8080/files/notes/hello.txt\ncurl -sS -H \"Authorization: Bearer your-secret\" \\\n  http://localhost:8080/files/notes | jq\ncurl -sS -X DELETE -H \"Authorization: Bearer your-secret\" \\\n  http://localhost:8080/files/notes/hello.txt\n```\n\n**`POST /run`** body fields: `prompt` (required), `workspace`, `model`, `systemPrompt`, `appendSystemPrompt`, `jsonSchema`, `noContinue`, `resume`, `timeoutSeconds`, `thinking`, `noTools`, `toolsAllowlist`, `extraArgs`, `async`, `fireAndForget`, `includeRaw`. With `jsonSchema` set the response is verbose: `text`, `json` (schema-validated), `events`, `sessionId`, `usage`, `attempts` (per-retry breakdown, up to 3 self-correction retries on parse/validation failure). Without `jsonSchema` the response is lean: `{runId, workspace, exitCode, text}`.\n\n## OpenAI-compatible endpoint mode\n\nSame `PIBOX_API_MODE=1` server, `POST /openai/v1/chat/completions` and `GET /openai/v1/models`. Drop-in for any OpenAI-SDK client — point the base URL at `http://host:8080/openai/v1` and set the model to one of `PIBOX_AVAILABLE_MODELS`.\n\n```bash\ncurl -s http://localhost:8080/openai/v1/chat/completions \\\n  -H \"Authorization: Bearer your-secret\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"model\": \"glm-4.6\",\n    \"messages\": [{\"role\": \"user\", \"content\": \"say HELLO\"}]\n  }'\n```\n\n**Streaming** (`\"stream\": true`): plain chat streams incrementally, one SSE chunk per token delta. Requests carrying `tools` or a JSON-schema constraint can't stream token-by-token (the answer only exists once fully computed) — they're **buffered**: the whole response is computed, then replayed as a single-shot SSE stream (role chunk → one content/tool_calls delta → finish chunk → `[DONE]`). The client's streaming parser is satisfied either way.\n\n**Tools / `tool_choice`** (OpenAI client-executed tool calling): send `tools` (OpenAI function-schema array) and optionally `tool_choice` (`auto`/`none`/`required`/`{\"type\":\"function\",\"function\":{\"name\":...}}`). pibox's own internal tools (bash, file edits) default OFF while in tool mode so the model behaves as a pure function-calling LLM — override with header `x-aicodebox-no-tools: 0` to re-enable the hybrid. The response comes back as `tool_calls` + `finish_reason: \"tool_calls\"`, exactly like OpenAI; you execute the tool client-side and send the result back in the next message round.\n\n**`response_format` / JSON-schema**: standard OpenAI `response_format` body field —`{\"type\": \"text\"}` (default), `{\"type\": \"json_object\"}` (force parseable JSON, no shape constraint), or `{\"type\": \"json_schema\", \"json_schema\": {\"name\": ..., \"schema\": {...}}}` (schema-validated, with up to 3 self-correction retries on failure → 422 if still invalid). `tools` and `response_format` **compose** in one request: a tool-call turn returns `tool_calls` (not schema-checked); the model's final answer (no more tool calls) is what gets schema-validated.\n\nExtra `x-aicodebox-*` headers (workspace pinning, session continuation, extra args, timeout, tools allowlist) are documented in [references/setup.md](references/setup.md#openai-endpoint-headers). Upstream provider errors (auth failure, rate limit, content-safety rejection) surface as HTTP 400, not a silent empty response.\n\n## MCP server mode\n\n`PIBOX_MCP_MODE=1`. Exposes an [MCP](https://modelcontextprotocol.io) (streamable HTTP) surface with 5 tools: `run_prompt`, `list_files`, `read_file`, `write_file`, `delete_file`. Coexists with any foreground mode:\n\n| Foreground | MCP placement |\n|---|---|\n| API mode (`PIBOX_API_MODE=1`) | mounted at `/mcp` on the API port — no extra process |\n| Telegram / Cron / passthrough / none | sidecar uvicorn on its own port, `PIBOX_MCP_MODE_PORT` (default `8081`), mounted at the port root |\n\n```bash\nclaude mcp add --transport http pibox http://localhost:8080/mcp \\\n  --header \"Authorization: Bearer your-mcp-token\"\n```\n\nRaw JSON-RPC (debugging, non-MCP-aware callers):\n\n```bash\ncurl -s http://localhost:8080/mcp \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Accept: application/json, text/event-stream\" \\\n  -H \"Authorization: Bearer your-mcp-token\" \\\n  -d '{\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"tools/list\"}'\n```\n\n`run_prompt(prompt, workspace?, model?, system_prompt?, append_system_prompt?, no_continue=true, resume?, thinking?, json_schema?)` invokes the agent and returns its text. `list_files`/`read_file`/`write_file`/`delete_file` operate on workspace-relative paths with the same traversal guard as the REST `/files` endpoints.\n\n**Destructive & irreversible.** `delete_file` removes a workspace file with no undo. An agent must NEVER call it unless the user explicitly asked for that exact action; confirm the specific target first; scope it to the current task; never enumerate-then-bulk-delete. On a shared/multi-tenant instance this can destroy another caller's workspace data — treat it as admin-only.\n\nAuth: `PIBOX_MCP_MODE_TOKEN=<token>` — bearer via `Authorization: Bearer …`, or `?apiToken=…` query param for clients that can't set headers. Empty = no auth. **No fallback to `PIBOX_API_MODE_TOKEN`.**\n\n**No auth when `PIBOX_MCP_MODE_TOKEN` is unset.** With it empty the MCP surface is UNAUTHENTICATED — anyone who can reach it gets `run_prompt` (arbitrary agent execution) and workspace file read/write/delete access. NEVER expose such an instance on a network or to untrusted agents; set the token and bind to loopback / behind an authenticating proxy.\n\n## Telegram bot mode\n\n`PIBOX_TELEGRAM_MODE=1` + `PIBOX_TELEGRAM_MODE_TOKEN=<token from @BotFather>`.\n\n- Text in → pi runs → Markdown→HTML rendered response back.\n- File uploads land in the chat's workspace. `[SEND_FILE: path]` in pi's output delivers workspace files as Telegram attachments.\n- Per-chat overrides: `/model`, `/effort` (maps to pi's `--thinking` levels), `/system_prompt`, `/append_system_prompt`. Persisted across restarts.\n- `/cancel` kills the in-flight run. `/reload` re-reads config. `/config` dumps merged settings. `/status` shows in-flight state. `/fetch <path>` downloads a file. `/start`, `/help` for basics.\n- Replies to cron messages inject the job's instruction + result so pi has full context for follow-ups.\n\nConfig at `$HOME/.aicodebox/telegram.yml` (override via `PIBOX_TELEGRAM_MODE_CONFIG`):\n\n```yaml\nallowed_chats: [-100123, 42]\ndefault:\n  model: glm-4.6\n  workspace: shared\nchats:\n  -100123:\n    workspace: alpha\n    allowed_users: [10, 20]\n```\n\nAuth: chat/user allowlisting via the config yaml (`allowed_chats`, per-chat `allowed_users`) — no separate bearer token, the bot token itself gates who can even message it.\n\n## Cron scheduler mode\n\n`PIBOX_CRON_MODE=1` + `PIBOX_CRON_MODE_FILE=/path/to/cron.yaml`. 6-field cron schedules via croniter. Each job fires pi with the given instruction on schedule.\n\n```yaml\njobs:\n  - name: morning-standup\n    schedule: \"0 0 9 * * 1-5\"\n    instruction: |\n      Summarize what changed in /workspace since yesterday.\n      Be brief. One paragraph max.\n    workspace: myproject\n    telegram_chat_id: -100123\n    model: glm-4.6\n    thinking: low\n```\n\nEach run gets a history dir at `$HOME/.aicodebox/cron/history/<workspace>/<timestamp>-<job>/` (override root via `PIBOX_CRON_MODE_HISTORY_DIR`) with `meta.json`, `stdout.log`, `stderr.log`, `result.txt`. If telegram is also configured, `telegram.json` lands there too and the next run's prompt gets a \"prior run\" hint so pi can reference its own history without you wiring it up. Running alongside Telegram mode (`PIBOX_TELEGRAM_MODE=1` + `PIBOX_CRON_MODE=1`) runs cron in-thread inside the telegram process — the only foreground-mode pairing allowed.\n\nAuth: none — this is a scheduled background job, not a request-driven surface. `telegram_chat_id` on a job routes its result through the (already-authenticated) Telegram bot if set.\n\n## Auth (LLM upstream)\n\nUse `PIBOX_PROVIDER_*` for Pi's documented custom HTTP APIs, including LiteLLM and Anthropic-compatible endpoints. `ANTHROPIC_*` remains a compatibility path for existing Anthropic Messages endpoints. The full configuration matrix and examples are in [references/setup.md](references/setup.md#llm-upstream).\n\n| Var | Purpose |\n|-----|---------|\n| `ANTHROPIC_AUTH_TOKEN` | Bearer token (Z.AI, direct Anthropic, etc.) |\n| `ANTHROPIC_API_KEY` | Same thing — pi reads both |\n| `ANTHROPIC_BASE_URL` | Endpoint override (default `https://api.anthropic.com`) |\n| `ANTHROPIC_MODEL` | Default model when the caller doesn't specify one |\n\nZ.AI's GLM models are a fast/cheap default: `ANTHROPIC_BASE_URL=https://api.z.ai/api/anthropic` + `ANTHROPIC_MODEL=glm-4.6`.\n\npi's thinking levels (`--thinking`): `off`, `minimal`, `low`, `medium`, `high`, `xhigh`. Exposed as `/effort` in Telegram mode and `thinking` in API/OAI requests.\n\n**Surface-level auth** (separate from the LLM upstream) is per-mode: `PIBOX_API_MODE_TOKEN` gates the REST + OAI routes, `PIBOX_MCP_MODE_TOKEN` gates MCP (no fallback between the two), Telegram gates by bot-token possession + chat/user allowlist, cron and interactive/exec modes have no surface auth (container-boundary trust). Both `PIBOX_API_MODE_TOKEN` and `PIBOX_MCP_MODE_TOKEN` default to empty, which means no auth — see [Security & safety](#security--safety) above before exposing either surface beyond localhost.\n\n## Typical Workflows\n\n**One-off task from a script, no server:**\n\n```bash\ndocker run --rm -e ANTHROPIC_AUTH_TOKEN=$TOKEN -e ANTHROPIC_BASE_URL=$BASE_URL \\\n  -e ANTHROPIC_MODEL=glm-4.6 -v \"$PWD:/workspace\" \\\n  psyb0t/pibox:latest -p \"summarize the diff in /workspace\"\n```\n\n**Long-running server, drive it with curl:**\n\n```bash\ndocker run -d --network host -e PIBOX_API_MODE=1 -e PIBOX_API_MODE_TOKEN=$SECRET \\\n  -e PIBOX_AVAILABLE_MODELS=glm-4.6 -e ANTHROPIC_AUTH_TOKEN=$TOKEN \\\n  -e ANTHROPIC_BASE_URL=$BASE_URL -v \"$PWD/workspace:/workspace\" psyb0t/pibox:latest\ncurl -s http://localhost:8080/run -H \"Authorization: Bearer $SECRET\" \\\n  -H \"Content-Type: application/json\" -d '{\"prompt\": \"run the tests and report failures\"}'\n```\n\n**Structured extraction via JSON schema:**\n\n```bash\ncurl -s http://localhost:8080/run -H \"Authorization: Bearer $SECRET\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"prompt\": \"extract TODOs from /workspace\", \"jsonSchema\": {\"type\":\"object\",\"properties\":{\"todos\":{\"type\":\"array\",\"items\":{\"type\":\"string\"}}},\"required\":[\"todos\"]}}'\n```\n\n**Wire an MCP-aware agent (Claude Code, OpenClaw) to a running pibox:**\n\n```bash\nclaude mcp add --transport http pibox http://localhost:8080/mcp \\\n  --header \"Authorization: Bearer $MCP_TOKEN\"\n```\n\n**Chat + Telegram + scheduled digest, all on one box:**\n\n```bash\ndocker run -d --network host \\\n  -e PIBOX_TELEGRAM_MODE=1 -e PIBOX_TELEGRAM_MODE_TOKEN=$BOT_TOKEN \\\n  -e PIBOX_CRON_MODE=1 -e PIBOX_CRON_MODE_FILE=/config/cron.yaml \\\n  -e ANTHROPIC_AUTH_TOKEN=$TOKEN -e ANTHROPIC_BASE_URL=$BASE_URL \\\n  -v \"$PWD/workspace:/workspace\" -v \"$PWD/cron.yaml:/config/cron.yaml:ro\" \\\n  psyb0t/pibox:latest\n```\n\nFile v0.18.4:_meta.json\n\n{\n  \"ownerId\": \"kn79dhvmpjng4rp2jjk8k0v5xx80ccbk\",\n  \"slug\": \"pibox\",\n  \"version\": \"0.18.4\",\n  \"publishedAt\": 1790194970635\n}\n\nFile v0.18.4:references/setup.md\n\n# pibox setup\n\n## Requirements\n\n- Docker\n- An LLM endpoint supported by Pi's custom HTTP provider configuration. `PIBOX_PROVIDER_*` accepts an endpoint URL, protocol, API key or token, and model. It covers LiteLLM, Anthropic Messages endpoints, and Google Generative AI. `ANTHROPIC_*` remains available for existing Anthropic-compatible deployments. Pi drives the model; pibox drives Pi.\n- A target workspace. Run the wrapper from that directory so it mounts the path and preserves Pi state.\n\n## Quick Install\n\n### Host wrapper\n\nInstall the wrapper for interactive and one-shot use:\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/psyb0t/docker-pibox/main/install.sh | bash\n```\n\nInstall `pibox`, `codexbox`, and `claudebox` in the same command directory,\nnormally `/usr/local/bin`, when a box needs to launch another. Each wrapper\nmounts sibling wrapper files read-only. The sibling wrapper then asks the host\nDocker daemon to mount its own data directory.\n\n### Interactive / one-shot (no server)\n\n```bash\npibox\npibox -p \"inspect this workspace\"\nPIBOX_FULL=1 pibox -p \"run the full test suite\"\n```\n\nUse the wrapper for normal interactive and one-shot work. It handles the\nworkspace mount, Pi state, aicodebox state, SSH state, image selection, and\nnested launch context. Do not construct a `docker run` command unless the user\nexplicitly asks for a direct container deployment.\n\n### REST / OpenAI-compatible / MCP server\n\n```bash\ndocker run -d --name pibox --network host \\\n  -e PIBOX_API_MODE=1 \\\n  -e PIBOX_API_MODE_TOKEN=your-secret \\\n  -e PIBOX_AVAILABLE_MODELS=glm-4.6,glm-4.5-air \\\n  -e PIBOX_MCP_MODE=1 \\\n  -e PIBOX_MCP_MODE_TOKEN=your-mcp-secret \\\n  -e ANTHROPIC_AUTH_TOKEN=your-token \\\n  -e ANTHROPIC_BASE_URL=https://api.z.ai/api/anthropic \\\n  -e ANTHROPIC_MODEL=glm-4.6 \\\n  -v \"$PWD/workspace:/workspace\" \\\n  psyb0t/pibox:latest\n```\n\n`--network host` is convenient for local use; for anything else publish the port explicitly (`-p 8080:8080`) instead.\n\n**Verify:** `curl http://localhost:8080/healthz` returns `{\"ok\": true, \"adapter\": \"pi\"}`.\n\n### Telegram bot\n\n```bash\ndocker run -d --name pibox-tg \\\n  -e PIBOX_TELEGRAM_MODE=1 \\\n  -e PIBOX_TELEGRAM_MODE_TOKEN=your-bot-token \\\n  -e ANTHROPIC_AUTH_TOKEN=your-token \\\n  -e ANTHROPIC_BASE_URL=https://api.z.ai/api/anthropic \\\n  -e ANTHROPIC_MODEL=glm-4.6 \\\n  -v \"$PWD/workspace:/workspace\" \\\n  -v \"$PWD/telegram.yml:/home/aicode/.aicodebox/telegram.yml:ro\" \\\n  psyb0t/pibox:latest\n```\n\nRequires a `telegram.yml` with at least `allowed_chats` set (see [Telegram bot mode](../SKILL.md#telegram-bot-mode)) — the bot ignores messages from chats not on the allowlist.\n\n### Cron scheduler\n\n```bash\ndocker run -d --name pibox-cron \\\n  -e PIBOX_CRON_MODE=1 \\\n  -e PIBOX_CRON_MODE_FILE=/config/cron.yaml \\\n  -e ANTHROPIC_AUTH_TOKEN=your-token \\\n  -e ANTHROPIC_BASE_URL=https://api.z.ai/api/anthropic \\\n  -e ANTHROPIC_MODEL=glm-4.6 \\\n  -v \"$PWD/workspace:/workspace\" \\\n  -v \"$PWD/cron.yaml:/config/cron.yaml:ro\" \\\n  psyb0t/pibox:latest\n```\n\n### docker-compose (API + MCP)\n\n```yaml\nservices:\n  pibox:\n    image: psyb0t/pibox:latest\n    environment:\n      PIBOX_API_MODE: \"1\"\n      PIBOX_API_MODE_TOKEN: your-secret\n      PIBOX_AVAILABLE_MODELS: glm-4.6,glm-4.5-air\n      PIBOX_MCP_MODE: \"1\"\n      PIBOX_MCP_MODE_TOKEN: your-mcp-secret\n      ANTHROPIC_AUTH_TOKEN: your-token\n      ANTHROPIC_BASE_URL: https://api.z.ai/api/anthropic\n      ANTHROPIC_MODEL: glm-4.6\n    ports:\n      - \"8080:8080\"\n    volumes:\n      - ./workspace:/workspace\n    restart: unless-stopped\n```\n\n## Foreground Mode Rules\n\n`PIBOX_API_MODE`, `PIBOX_TELEGRAM_MODE`, `PIBOX_CRON_MODE` are the foreground modes. Priority order if multiple are set: API wins over everything. Telegram + Cron together is the one allowed pairing (cron runs in-thread inside the telegram process). If none are set, the container falls through to pi's own CLI (interactive shell, or one-shot exec if args are passed).\n\n`PIBOX_MCP_MODE` is independent of the above — it coexists with any foreground mode (mounted at `/mcp` in API mode, sidecar elsewhere) or with none at all (sidecar only, no other surface reachable).\n\n## Environment Variables\n\nNaming convention: `PIBOX_<MODE>_MODE=1` is the on/off flag, `PIBOX_<MODE>_MODE_<KNOB>=...` is its config. Non-mode-scoped vars (workspace, container name, available models) are bare `PIBOX_*`.\n\nThe image is built on [aicodebox](https://github.com/psyb0t/docker-aicodebox); the equivalent `AICODEBOX_*` names also work — the entrypoint translates `PIBOX_X` to `AICODEBOX_X` when only the pibox-prefixed one is set. If both are set, `AICODEBOX_*` wins.\n\n### Mode flags\n\n| Var | Default | What it does |\n|-----|---------|---------------|\n| `PIBOX_API_MODE` | `0` | Boot the HTTP API server (foreground) |\n| `PIBOX_TELEGRAM_MODE` | `0` | Boot the Telegram bot (foreground) |\n| `PIBOX_CRON_MODE` | `0` | Boot the cron scheduler (foreground; in-thread when telegram is also on) |\n| `PIBOX_MCP_MODE` | `0` | Expose MCP — mounted at `/mcp` in API mode, or as a sidecar elsewhere |\n\n### API mode config\n\n| Var | Default | What it does |\n|-----|---------|---------------|\n| `PIBOX_API_MODE_PORT` | `8080` | Port the API server binds to |\n| `PIBOX_API_MODE_TOKEN` | empty | Bearer token for the REST + OpenAI-compatible surface. Empty = no auth — see [Security & safety](../SKILL.md#security--safety) |\n\n### Telegram mode config\n\n| Var | Default | What it does |\n|-----|---------|---------------|\n| `PIBOX_TELEGRAM_MODE_TOKEN` | — | Bot token from @BotFather (required) |\n| `PIBOX_TELEGRAM_MODE_CONFIG` | `~/.aicodebox/telegram.yml` | Path to the telegram config yaml |\n| `PIBOX_TELEGRAM_MODE_OVERRIDES` | `~/.aicodebox/telegram_overrides.json` | Per-chat override store (model/effort/system prompts) |\n\n### Cron mode config\n\n| Var | Default | What it does |\n|-----|---------|---------------|\n| `PIBOX_CRON_MODE_FILE` | — | Path to the cron yaml (required) |\n| `PIBOX_CRON_MODE_HISTORY_DIR` | `~/.aicodebox/cron/history` | Where cron writes per-run history dirs (`meta.json`, `stdout.log`, `stderr.log`, `result.txt`, `telegram.json`) |\n\n### MCP mode config\n\n| Var | Default | What it does |\n|-----|---------|---------------|\n| `PIBOX_MCP_MODE_PORT` | `8081` | Port the sidecar MCP server binds to (ignored when mounted inside API mode) |\n| `PIBOX_MCP_MODE_TOKEN` | empty | Bearer token for MCP. Empty = no auth — see [Security & safety](../SKILL.md#security--safety). No fallback to `PIBOX_API_MODE_TOKEN` |\n\n### Workspace & runtime\n\n| Var | Default | What it does |\n|-----|---------|---------------|\n| `PIBOX_WORKSPACE` | `/workspace` | Root workspace dir inside the container |\n| `PIBOX_CONTAINER_NAME` | `aicodebox` | Used to scope per-container state files in direct Docker runs. The host wrapper derives a per-workspace name. |\n| `PIBOX_AVAILABLE_MODELS` | — | **Required for API mode.** CSV list returned by `/openai/v1/models` and shown in the telegram `/model` picker. pibox registers every listed model with the upstream provider under `PIBOX_PROVIDER_API` |\n| `PIBOX_AVAILABLE_EFFORTS` | adapter list (`off,minimal,low,medium,high,xhigh`) | Override the effort/`--thinking` list shown by the telegram `/effort` picker (comma-separated) |\n\n### LLM upstream\n\n#### Generic custom HTTP provider\n\nUse these variables for Pi's documented custom HTTP APIs. They configure the upstream model Pi uses, not pibox's own OpenAI-compatible `/openai/v1` endpoint.\n\n| Var | Default | What it does |\n|-----|---------|--------------|\n| `PIBOX_PROVIDER_NAME` | `pibox` | Provider identifier. Lowercase letters, numbers, and `-` only. |\n| `PIBOX_PROVIDER_API` | `openai-completions` | `openai-completions`, `openai-responses`, `anthropic-messages`, or `google-generative-ai` |\n| `PIBOX_PROVIDER_BASE_URL` | none | Required upstream HTTP base URL |\n| `PIBOX_PROVIDER_API_KEY` | none | Required upstream API key or token |\n| `PIBOX_PROVIDER_MODEL` | none | Required default upstream model ID |\n\nLiteLLM example:\n\n```bash\ndocker run --rm --network host \\\n  -e PIBOX_PROVIDER_BASE_URL=http://127.0.0.1:4000/v1 \\\n  -e PIBOX_PROVIDER_API=openai-completions \\\n  -e PIBOX_PROVIDER_API_KEY=your-litellm-virtual-key \\\n  -e PIBOX_PROVIDER_MODEL=your-model-id \\\n  -v \"$PWD/workspace:/workspace\" \\\n  psyb0t/pibox:latest \\\n  -p \"list the files in /workspace\"\n```\n\nFor API mode, set `PIBOX_AVAILABLE_MODELS=your-model-id` too. Do not combine `PIBOX_PROVIDER_*` with `ANTHROPIC_BASE_URL`. pibox rejects the ambiguous configuration. The generic variables cover Pi's documented custom HTTP APIs, not every cloud-specific built-in provider.\n\n#### Anthropic compatibility\n\n| Var | Purpose |\n|-----|---------|\n| `ANTHROPIC_AUTH_TOKEN` | Bearer token (Z.AI, direct Anthropic, etc.) |\n| `ANTHROPIC_API_KEY` | Same thing — pi reads both |\n| `ANTHROPIC_BASE_URL` | Endpoint override (default `https://api.anthropic.com`) |\n| `ANTHROPIC_MODEL` | Default model when the caller doesn't specify one |\n\n## OpenAI endpoint headers\n\nNon-standard `x-aicodebox-*` request headers extend `POST /openai/v1/chat/completions` beyond stock OpenAI fields (legacy `x-claude-*` aliases also work for `workspace`/`continue`/`append-system-prompt`):\n\n| Header | Purpose |\n|---|---|\n| `x-aicodebox-workspace` | Pin the run to a workspace subpath instead of the ephemeral/default one |\n| `x-aicodebox-continue` | `1`/`true`/`yes` to continue the most recent session in that workspace instead of starting fresh |\n| `x-aicodebox-append-system-prompt` | Append text to the system prompt |\n| `x-aicodebox-json-schema` | JSON-encoded schema — fallback for clients that can't set the standard `response_format` body field (body field wins if both are set) |\n| `x-aicodebox-resume` | Resume a specific session id |\n| `x-aicodebox-extra-args` | Extra pi CLI args — JSON array or comma-separated string |\n| `x-aicodebox-timeout-seconds` | Per-request run timeout |\n| `x-aicodebox-tools-allowlist` | Restrict pi's own internal tools — JSON array or comma-separated string |\n| `x-aicodebox-no-tools` | `1`/`true`/`yes` to disable pi's internal tools; in OpenAI-tools mode this is the override to re-enable them (send `0`) |\n\n## Ports\n\n| Port | Default | Service |\n|---|---|---|\n| API/OAI/MCP-in-API | `8080` (`PIBOX_API_MODE_PORT`) | REST, `/openai/v1/*`, `/mcp` (when `PIBOX_MCP_MODE=1`) |\n| MCP sidecar | `8081` (`PIBOX_MCP_MODE_PORT`) | MCP only, used when API mode is not the foreground |\n\nNo ports are opened for Telegram, cron, interactive, or one-shot exec modes — they're outbound-only or container-boundary-trusted.\n\n## Management\n\n```bash\ndocker logs -f pibox    # tail logs\ndocker stop pibox       # stop\ndocker rm pibox          # remove\ndocker pull psyb0t/pibox:latest  # update\n```\n\nCheck what's running inside a live API-mode container:\n\n```bash\ncurl -s http://localhost:8080/status -H \"Authorization: Bearer your-secret\" | jq\n```\n\n## OpenClaw / ClawHub Config\n\n```bash\nexport PIBOX_URL=http://localhost:8080\nexport PIBOX_API_MODE_TOKEN=<token>  # only if the server requires it\n```\n\nOr via `~/.openclaw/openclaw.json`:\n\n```json\n{\n  \"skills\": {\n    \"entries\": {\n      \"pibox\": {\n        \"env\": {\n          \"PIBOX_URL\": \"http://localhost:8080\",\n          \"PIBOX_API_MODE_TOKEN\": \"<token>\"\n        }\n      }\n    }\n  }\n}\n```\n\nFile v0.18.4:skill-card.md\n\n## Description:\n\nInstall, configure, or run pi-coding-agent through the pibox wrapper, or connect to its HTTP, MCP, Telegram, or cron surfaces.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[psyb0t](https://clawhub.ai/user/psyb0t)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers and engineers use pibox to run pi-coding-agent in a container, expose it through REST, OpenAI-compatible, MCP, Telegram, or cron interfaces, and connect it to configured upstream LLM endpoints.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: Remote installation is shown through a curl-to-shell command, which can execute unverified code.\n\nMitigation: Prefer downloading the installer first, inspecting it, and verifying its source before execution.\n\nRisk: API and MCP modes can expose agent execution and workspace file access without authentication when their tokens are unset.\n\nMitigation: Set strong, separate API and MCP bearer tokens, bind services to localhost or place them behind an authenticating proxy, and avoid exposing unauthenticated surfaces to a network.\n\nRisk: Host networking and broad workspace mounts can expand the impact of a compromised or misconfigured service.\n\nMitigation: Avoid host networking for non-local deployments, publish only required ports, and mount only a dedicated non-sensitive workspace.\n\nRisk: Cron and Telegram modes can provide persistent scheduled or chat-driven agent access.\n\nMitigation: Enable those modes only when persistence is intended, use allowlists for Telegram access, and review scheduled jobs before deployment.\n\nRisk: Delete and cancel operations can remove files or interrupt runs without undo.\n\nMitigation: Require explicit user confirmation for destructive operations and scope each action to the current task and target.\n\n## Reference(s):\n\n- [ClawHub skill page](https://clawhub.ai/psyb0t/skills/pibox)\n- [pibox setup](references/setup.md)\n- [pibox homepage](https://github.com/psyb0t/docker-pibox)\n- [pi-coding-agent](https://github.com/earendil-works/pi-mono/tree/main/packages/coding-agent)\n- [aicodebox](https://github.com/psyb0t/docker-aicodebox)\n- [Model Context Protocol](https://modelcontextprotocol.io)\n\n## Skill Output:\n\n**Output Type(s):** [text, markdown, code, shell commands, configuration, guidance]\n\n**Output Format:** [Markdown, shell commands, JSON API responses, and configuration snippets]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Can emit agent run results, file-operation guidance, API examples, MCP tool usage, Telegram configuration, and cron configuration.]\n\n## Skill Version(s):\n\n0.18.4 (source: server release metadata)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nArchive v0.18.3: 4 files, 13771 bytes\n\nFiles: references/setup.md (11237b), skill-card.md (2646b), SKILL.md (20404b), _meta.json (125b)\n\nFile v0.18.3:SKILL.md\n\n---\nname: pibox\ndescription: \"Install, configure, or run pi-coding-agent through the pibox wrapper, or connect to its HTTP, MCP, Telegram, or cron surfaces.\"\nhomepage: https://github.com/psyb0t/docker-pibox\nuser-invocable: true\nmetadata:\n  { \"openclaw\": { \"emoji\": \"🥧\", \"primaryEnv\": \"PIBOX_URL\", \"requires\": { \"bins\": [\"docker\", \"curl\"] } } }\n---\n\n# pibox\n\n[pi-coding-agent](https://github.com/earendil-works/pi-mono/tree/main/packages/coding-agent) inside an [aicodebox](https://github.com/psyb0t/docker-aicodebox) container. One image, seven ways in: interactive shell, one-shot exec, HTTP REST API, OpenAI-compatible endpoint, MCP server, Telegram bot, cron scheduler.\n\nYou talk to pibox, pibox talks to pi, and Pi talks to the configured upstream LLM. Use `PIBOX_PROVIDER_*` for Pi's documented custom HTTP APIs, including LiteLLM and Anthropic-compatible endpoints. `ANTHROPIC_*` remains a compatibility shortcut for existing Anthropic Messages deployments.\n\nFor installation and configuration, see [references/setup.md](references/setup.md).\n\n## Agent execution\n\nUse `pibox` when it is on `PATH`. Run it from the workspace the user named.\nDo not assemble a new `docker run` command for routine interactive or one-shot\nwork. The wrapper owns the workspace mount, `~/.pi`, aicodebox state, SSH\nstate, image selection, and container lifecycle.\n\n```bash\npibox                                      # interactive Pi\npibox -p \"inspect this workspace\"           # one-shot work\npibox -p \"review this change\" --thinking high\nPIBOX_FULL=1 pibox -p \"run the full suite\"\n```\n\nConfigure the Pi upstream before the first run with `PIBOX_PROVIDER_*` or the\nsupported `ANTHROPIC_*` compatibility variables. Use an HTTP or MCP endpoint\nonly when the user asks for a service or provides an already-running remote\nURL. MCP plugins connect to a server. They do not replace the local wrapper.\n\nStart a local API and MCP server only when the user asks for one. Set the\nactual model identifiers and distinct bearer tokens:\n\n```bash\nPIBOX_DETACH=1 \\\nPIBOX_API_MODE=1 \\\nPIBOX_MCP_MODE=1 \\\nPIBOX_AVAILABLE_MODELS=your-model-id \\\nPIBOX_API_MODE_TOKEN=your-api-token \\\nPIBOX_MCP_MODE_TOKEN=your-mcp-token \\\npibox\n```\n\nIf `pibox`, `codexbox`, and `claudebox` were installed in the same command\ndirectory, a box can invoke a sibling command directly. The parent wrapper\npasses the real host paths and the sibling wrapper file. Do not set\n`AICODEBOX_HOST_*`, copy wrapper files, or manually mount another box's state\ndirectory. If the sibling command is absent, ask the user to install it or to\nchoose another approach.\n\n## Security & safety\n\n- **No auth when `PIBOX_API_MODE_TOKEN` is unset.** With it empty the REST/OpenAI-compatible API surface is UNAUTHENTICATED — anyone who can reach it gets full agent-execution and workspace file-read/write/delete access. NEVER expose such an instance on a network or to untrusted agents; set the token and bind to loopback / behind an authenticating proxy.\n- **No auth when `PIBOX_MCP_MODE_TOKEN` is unset.** Same story for the MCP surface (`/mcp` or the sidecar) — empty token means unauthenticated `run_prompt`/file-tool access, and it does not fall back to `PIBOX_API_MODE_TOKEN`. Set it explicitly.\n- **Destructive & irreversible.** `DELETE /run/{id}`, `DELETE /files/{path}`, and the MCP `delete_file` tool remove state with no undo (canceled runs can't be resumed; deleted files are gone). An agent must NEVER call these unless the user explicitly asked for that exact action; confirm the specific target first, scope it to the current task, and never enumerate-then-bulk-delete. On a shared/multi-tenant instance a deletion can destroy another caller's in-flight run or workspace file — treat these routes as admin-only.\n\n## When To Use\n\n- Drive pi-coding-agent from a script/service instead of an interactive terminal (`/run`, `/openai/v1/chat/completions`, or MCP tools).\n- Wire pi into an OpenAI-SDK-compatible client (LangChain, openai-python) via the `/openai/v1/*` surface.\n- Give an MCP-aware agent (Claude, Cursor, OpenClaw) remote tool access to a pi-driven workspace.\n- Chat with pi from Telegram, with per-chat model/effort overrides and file transfer.\n- Schedule recurring pi runs (standups, digests, periodic maintenance) via cron mode.\n- One-off container run for a single prompt (CI step, quick script) via one-shot exec.\n\n## When NOT To Use\n\n- Don't run two foreground modes together except Telegram+Cron (cron runs in-thread inside telegram) — API set alongside anything else wins and the others don't start.\n- Don't expect `/openai/v1/chat/completions` to stream token-by-token when `tools` or a JSON schema is in play — those modes compute the full answer first and replay it as a single-shot SSE stream (still a valid stream, just not incremental). Plain chat streams incrementally.\n- Don't rely on `PIBOX_MCP_MODE_TOKEN` falling back to `PIBOX_API_MODE_TOKEN` — MCP has its own bearer, no fallback.\n- Don't point multiple concurrent runs at the same workspace — the API/OAI layer returns 409 \"workspace busy\" while a run is in flight in that workspace.\n\n## Interactive shell mode\n\nRun `pibox` with no mode variables or arguments. The wrapper starts Pi in the\ncurrent workspace and preserves its host state.\n\n```bash\npibox\n```\n\nAuth: none at the container boundary. Pi uses the upstream provider variables in [references/setup.md](references/setup.md#llm-upstream).\n\n## One-shot exec mode\n\n`pibox -p \"<prompt>\"` runs Pi non-interactively and writes the result to\nstdout, then exits. The wrapper forwards Pi flags unchanged.\n\n```bash\npibox -p \"list the files in this workspace\"\n```\n\nAny Pi CLI flag works here (`--model`, `--thinking`, `--session`, etc.). Auth: none at the container boundary. Pi uses the upstream provider variables in [references/setup.md](references/setup.md#llm-upstream).\n\n## REST API mode\n\n`PIBOX_API_MODE=1`. FastAPI server on `:8080` (override `PIBOX_API_MODE_PORT`). **Requires `PIBOX_AVAILABLE_MODELS=<csv>`** — the server refuses to boot without it (no sensible default; pi can drive any provider's models).\n\n```bash\ndocker run -d --network host \\\n  -e PIBOX_API_MODE=1 \\\n  -e PIBOX_API_MODE_TOKEN=your-secret \\\n  -e PIBOX_AVAILABLE_MODELS=glm-4.6,glm-4.5-air \\\n  -e ANTHROPIC_AUTH_TOKEN=your-token \\\n  -e ANTHROPIC_BASE_URL=https://api.z.ai/api/anthropic \\\n  -e ANTHROPIC_MODEL=glm-4.6 \\\n  -v \"$PWD/workspace:/workspace\" \\\n  psyb0t/pibox:latest\n```\n\n| Method | Path | What it does |\n|--------|------|--------------|\n| `GET` | `/healthz` | liveness — `{ok, adapter}`, unauthenticated |\n| `GET` | `/status` | in-flight runs + busy workspaces |\n| `POST` | `/run` | run the agent — sync by default; body `async` or `fireAndForget` makes it fire-and-poll |\n| `GET` | `/run/result?runId=<id>` | poll a run started with `async`/`fireAndForget` |\n| `DELETE` | `/run/{id}` | cancel an in-flight run (kills the subprocess) |\n| `GET` | `/files` | list the workspace root — `{entries: [{name, type, size?}, ...]}` |\n| `GET` | `/files/{path}` | list a sub-directory, or stream a file's bytes |\n| `PUT` | `/files/{path}` | upload — raw request body becomes the file contents; parent dirs auto-created |\n| `DELETE` | `/files/{path}` | delete a file (refuses directories — 400) |\n| `POST` | `/openai/v1/chat/completions` | OpenAI-compatible chat (see below) |\n| `GET` | `/openai/v1/models` | model list, from `PIBOX_AVAILABLE_MODELS` |\n| `POST` | `/mcp` | MCP server (streamable HTTP) — mounted only when `PIBOX_MCP_MODE=1` |\n\nAll `/files/*` paths resolve against the workspace root with traversal checking — `..` segments that escape the root return 400. Every route except `/healthz` is gated by `Authorization: Bearer <PIBOX_API_MODE_TOKEN>` when that var is set; empty/unset token = no auth.\n\n**No auth when `PIBOX_API_MODE_TOKEN` is unset.** With it empty the API is UNAUTHENTICATED — anyone who can reach it gets run-the-agent and workspace file-read/write/delete access. NEVER expose such an instance on a network or to untrusted agents; set the token and bind to loopback / behind an authenticating proxy.\n\n**Destructive & irreversible.** `DELETE /run/{id}` kills the in-flight subprocess with no undo, and `DELETE /files/{path}` deletes a workspace file with no undo. An agent must NEVER call either unless the user explicitly asked for that exact action; confirm the specific target first; scope it to the current task; never enumerate-then-bulk-delete. On a shared/multi-tenant instance this can disrupt or destroy another caller's run or data — treat these routes as admin-only.\n\n```bash\n# sync run\ncurl -s http://localhost:8080/run \\\n  -H \"Authorization: Bearer your-secret\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"prompt\": \"say HELLO\", \"workspace\": \"/workspace\"}'\n\n# async run, then poll\nRUN_ID=$(curl -s http://localhost:8080/run \\\n  -H \"Authorization: Bearer your-secret\" -H \"Content-Type: application/json\" \\\n  -d '{\"prompt\": \"long task\", \"async\": true}' | jq -r .runId)\ncurl -s \"http://localhost:8080/run/result?runId=$RUN_ID\" \\\n  -H \"Authorization: Bearer your-secret\"\n\n# cancel it\ncurl -s -X DELETE \"http://localhost:8080/run/$RUN_ID\" \\\n  -H \"Authorization: Bearer your-secret\"\n\n# upload / download / list / delete a workspace file\ncurl -sS -X PUT -H \"Authorization: Bearer your-secret\" \\\n  --data-binary @local.txt http://localhost:8080/files/notes/hello.txt\ncurl -sS -H \"Authorization: Bearer your-secret\" \\\n  http://localhost:8080/files/notes/hello.txt\ncurl -sS -H \"Authorization: Bearer your-secret\" \\\n  http://localhost:8080/files/notes | jq\ncurl -sS -X DELETE -H \"Authorization: Bearer your-secret\" \\\n  http://localhost:8080/files/notes/hello.txt\n```\n\n**`POST /run`** body fields: `prompt` (required), `workspace`, `model`, `systemPrompt`, `appendSystemPrompt`, `jsonSchema`, `noContinue`, `resume`, `timeoutSeconds`, `thinking`, `noTools`, `toolsAllowlist`, `extraArgs`, `async`, `fireAndForget`, `includeRaw`. With `jsonSchema` set the response is verbose: `text`, `json` (schema-validated), `events`, `sessionId`, `usage`, `attempts` (per-retry breakdown, up to 3 self-correction retries on parse/validation failure). Without `jsonSchema` the response is lean: `{runId, workspace, exitCode, text}`.\n\n## OpenAI-compatible endpoint mode\n\nSame `PIBOX_API_MODE=1` server, `POST /openai/v1/chat/completions` and `GET /openai/v1/models`. Drop-in for any OpenAI-SDK client — point the base URL at `http://host:8080/openai/v1` and set the model to one of `PIBOX_AVAILABLE_MODELS`.\n\n```bash\ncurl -s http://localhost:8080/openai/v1/chat/completions \\\n  -H \"Authorization: Bearer your-secret\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"model\": \"glm-4.6\",\n    \"messages\": [{\"role\": \"user\", \"content\": \"say HELLO\"}]\n  }'\n```\n\n**Streaming** (`\"stream\": true`): plain chat streams incrementally, one SSE chunk per token delta. Requests carrying `tools` or a JSON-schema constraint can't stream token-by-token (the answer only exists once fully computed) — they're **buffered**: the whole response is computed, then replayed as a single-shot SSE stream (role chunk → one content/tool_calls delta → finish chunk → `[DONE]`). The client's streaming parser is satisfied either way.\n\n**Tools / `tool_choice`** (OpenAI client-executed tool calling): send `tools` (OpenAI function-schema array) and optionally `tool_choice` (`auto`/`none`/`required`/`{\"type\":\"function\",\"function\":{\"name\":...}}`). pibox's own internal tools (bash, file edits) default OFF while in tool mode so the model behaves as a pure function-calling LLM — override with header `x-aicodebox-no-tools: 0` to re-enable the hybrid. The response comes back as `tool_calls` + `finish_reason: \"tool_calls\"`, exactly like OpenAI; you execute the tool client-side and send the result back in the next message round.\n\n**`response_format` / JSON-schema**: standard OpenAI `response_format` body field —`{\"type\": \"text\"}` (default), `{\"type\": \"json_object\"}` (force parseable JSON, no shape constraint), or `{\"type\": \"json_schema\", \"json_schema\": {\"name\": ..., \"schema\": {...}}}` (schema-validated, with up to 3 self-correction retries on failure → 422 if still invalid). `tools` and `response_format` **compose** in one request: a tool-call turn returns `tool_calls` (not schema-checked); the model's final answer (no more tool calls) is what gets schema-validated.\n\nExtra `x-aicodebox-*` headers (workspace pinning, session continuation, extra args, timeout, tools allowlist) are documented in [references/setup.md](references/setup.md#openai-endpoint-headers). Upstream provider errors (auth failure, rate limit, content-safety rejection) surface as HTTP 400, not a silent empty response.\n\n## MCP server mode\n\n`PIBOX_MCP_MODE=1`. Exposes an [MCP](https://modelcontextprotocol.io) (streamable HTTP) surface with 5 tools: `run_prompt`, `list_files`, `read_file`, `write_file`, `delete_file`. Coexists with any foreground mode:\n\n| Foreground | MCP placement |\n|---|---|\n| API mode (`PIBOX_API_MODE=1`) | mounted at `/mcp` on the API port — no extra process |\n| Telegram / Cron / passthrough / none | sidecar uvicorn on its own port, `PIBOX_MCP_MODE_PORT` (default `8081`), mounted at the port root |\n\n```bash\nclaude mcp add --transport http pibox http://localhost:8080/mcp \\\n  --header \"Authorization: Bearer your-mcp-token\"\n```\n\nRaw JSON-RPC (debugging, non-MCP-aware callers):\n\n```bash\ncurl -s http://localhost:8080/mcp \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Accept: application/json, text/event-stream\" \\\n  -H \"Authorization: Bearer your-mcp-token\" \\\n  -d '{\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"tools/list\"}'\n```\n\n`run_prompt(prompt, workspace?, model?, system_prompt?, append_system_prompt?, no_continue=true, resume?, thinking?, json_schema?)` invokes the agent and returns its text. `list_files`/`read_file`/`write_file`/`delete_file` operate on workspace-relative paths with the same traversal guard as the REST `/files` endpoints.\n\n**Destructive & irreversible.** `delete_file` removes a workspace file with no undo. An agent must NEVER call it unless the user explicitly asked for that exact action; confirm the specific target first; scope it to the current task; never enumerate-then-bulk-delete. On a shared/multi-tenant instance this can destroy another caller's workspace data — treat it as admin-only.\n\nAuth: `PIBOX_MCP_MODE_TOKEN=<token>` — bearer via `Authorization: Bearer …`, or `?apiToken=…` query param for clients that can't set headers. Empty = no auth. **No fallback to `PIBOX_API_MODE_TOKEN`.**\n\n**No auth when `PIBOX_MCP_MODE_TOKEN` is unset.** With it empty the MCP surface is UNAUTHENTICATED — anyone who can reach it gets `run_prompt` (arbitrary agent execution) and workspace file read/write/delete access. NEVER expose such an instance on a network or to untrusted agents; set the token and bind to loopback / behind an authenticating proxy.\n\n## Telegram bot mode\n\n`PIBOX_TELEGRAM_MODE=1` + `PIBOX_TELEGRAM_MODE_TOKEN=<token from @BotFather>`.\n\n- Text in → pi runs → Markdown→HTML rendered response back.\n- File uploads land in the chat's workspace. `[SEND_FILE: path]` in pi's output delivers workspace files as Telegram attachments.\n- Per-chat overrides: `/model`, `/effort` (maps to pi's `--thinking` levels), `/system_prompt`, `/append_system_prompt`. Persisted across restarts.\n- `/cancel` kills the in-flight run. `/reload` re-reads config. `/config` dumps merged settings. `/status` shows in-flight state. `/fetch <path>` downloads a file. `/start`, `/help` for basics.\n- Replies to cron messages inject the job's instruction + result so pi has full context for follow-ups.\n\nConfig at `$HOME/.aicodebox/telegram.yml` (override via `PIBOX_TELEGRAM_MODE_CONFIG`):\n\n```yaml\nallowed_chats: [-100123, 42]\ndefault:\n  model: glm-4.6\n  workspace: shared\nchats:\n  -100123:\n    workspace: alpha\n    allowed_users: [10, 20]\n```\n\nAuth: chat/user allowlisting via the config yaml (`allowed_chats`, per-chat `allowed_users`) — no separate bearer token, the bot token itself gates who can even message it.\n\n## Cron scheduler mode\n\n`PIBOX_CRON_MODE=1` + `PIBOX_CRON_MODE_FILE=/path/to/cron.yaml`. 6-field cron schedules via croniter. Each job fires pi with the given instruction on schedule.\n\n```yaml\njobs:\n  - name: morning-standup\n    schedule: \"0 0 9 * * 1-5\"\n    instruction: |\n      Summarize what changed in /workspace since yesterday.\n      Be brief. One paragraph max.\n    workspace: myproject\n    telegram_chat_id: -100123\n    model: glm-4.6\n    thinking: low\n```\n\nEach run gets a history dir at `$HOME/.aicodebox/cron/history/<workspace>/<timestamp>-<job>/` (override root via `PIBOX_CRON_MODE_HISTORY_DIR`) with `meta.json`, `stdout.log`, `stderr.log`, `result.txt`. If telegram is also configured, `telegram.json` lands there too and the next run's prompt gets a \"prior run\" hint so pi can reference its own history without you wiring it up. Running alongside Telegram mode (`PIBOX_TELEGRAM_MODE=1` + `PIBOX_CRON_MODE=1`) runs cron in-thread inside the telegram process — the only foreground-mode pairing allowed.\n\nAuth: none — this is a scheduled background job, not a request-driven surface. `telegram_chat_id` on a job routes its result through the (already-authenticated) Telegram bot if set.\n\n## Auth (LLM upstream)\n\nUse `PIBOX_PROVIDER_*` for Pi's documented custom HTTP APIs, including LiteLLM and Anthropic-compatible endpoints. `ANTHROPIC_*` remains a compatibility path for existing Anthropic Messages endpoints. The full configuration matrix and examples are in [references/setup.md](references/setup.md#llm-upstream).\n\n| Var | Purpose |\n|-----|---------|\n| `ANTHROPIC_AUTH_TOKEN` | Bearer token (Z.AI, direct Anthropic, etc.) |\n| `ANTHROPIC_API_KEY` | Same thing — pi reads both |\n| `ANTHROPIC_BASE_URL` | Endpoint override (default `https://api.anthropic.com`) |\n| `ANTHROPIC_MODEL` | Default model when the caller doesn't specify one |\n\nZ.AI's GLM models are a fast/cheap default: `ANTHROPIC_BASE_URL=https://api.z.ai/api/anthropic` + `ANTHROPIC_MODEL=glm-4.6`.\n\npi's thinking levels (`--thinking`): `off`, `minimal`, `low`, `medium`, `high`, `xhigh`. Exposed as `/effort` in Telegram mode and `thinking` in API/OAI requests.\n\n**Surface-level auth** (separate from the LLM upstream) is per-mode: `PIBOX_API_MODE_TOKEN` gates the REST + OAI routes, `PIBOX_MCP_MODE_TOKEN` gates MCP (no fallback between the two), Telegram gates by bot-token possession + chat/user allowlist, cron and interactive/exec modes have no surface auth (container-boundary trust). Both `PIBOX_API_MODE_TOKEN` and `PIBOX_MCP_MODE_TOKEN` default to empty, which means no auth — see [Security & safety](#security--safety) above before exposing either surface beyond localhost.\n\n## Typical Workflows\n\n**One-off task from a script, no server:**\n\n```bash\ndocker run --rm -e ANTHROPIC_AUTH_TOKEN=$TOKEN -e ANTHROPIC_BASE_URL=$BASE_URL \\\n  -e ANTHROPIC_MODEL=glm-4.6 -v \"$PWD:/workspace\" \\\n  psyb0t/pibox:latest -p \"summarize the diff in /workspace\"\n```\n\n**Long-running server, drive it with curl:**\n\n```bash\ndocker run -d --network host -e PIBOX_API_MODE=1 -e PIBOX_API_MODE_TOKEN=$SECRET \\\n  -e PIBOX_AVAILABLE_MODELS=glm-4.6 -e ANTHROPIC_AUTH_TOKEN=$TOKEN \\\n  -e ANTHROPIC_BASE_URL=$BASE_URL -v \"$PWD/workspace:/workspace\" psyb0t/pibox:latest\ncurl -s http://localhost:8080/run -H \"Authorization: Bearer $SECRET\" \\\n  -H \"Content-Type: application/json\" -d '{\"prompt\": \"run the tests and report failures\"}'\n```\n\n**Structured extraction via JSON schema:**\n\n```bash\ncurl -s http://localhost:8080/run -H \"Authorization: Bearer $SECRET\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"prompt\": \"extract TODOs from /workspace\", \"jsonSchema\": {\"type\":\"object\",\"properties\":{\"todos\":{\"type\":\"array\",\"items\":{\"type\":\"string\"}}},\"required\":[\"todos\"]}}'\n```\n\n**Wire an MCP-aware agent (Claude Code, OpenClaw) to a running pibox:**\n\n```bash\nclaude mcp add --transport http pibox http://localhost:8080/mcp \\\n  --header \"Authorization: Bearer $MCP_TOKEN\"\n```\n\n**Chat + Telegram + scheduled digest, all on one box:**\n\n```bash\ndocker run -d --network host \\\n  -e PIBOX_TELEGRAM_MODE=1 -e PIBOX_TELEGRAM_MODE_TOKEN=$BOT_TOKEN \\\n  -e PIBOX_CRON_MODE=1 -e PIBOX_CRON_MODE_FILE=/config/cron.yaml \\\n  -e ANTHROPIC_AUTH_TOKEN=$TOKEN -e ANTHROPIC_BASE_URL=$BASE_URL \\\n  -v \"$PWD/workspace:/workspace\" -v \"$PWD/cron.yaml:/config/cron.yaml:ro\" \\\n  psyb0t/pibox:latest\n```\n\nFile v0.18.3:_meta.json\n\n{\n  \"ownerId\": \"kn79dhvmpjng4rp2jjk8k0v5xx80ccbk\",\n  \"slug\": \"pibox\",\n  \"version\": \"0.18.3\",\n  \"publishedAt\": 1789386771110\n}\n\nFile v0.18.3:references/setup.md\n\n# pibox setup\n\n## Requirements\n\n- Docker\n- An LLM endpoint supported by Pi's custom HTTP provider configuration. `PIBOX_PROVIDER_*` accepts an endpoint URL, protocol, API key or token, and model. It covers LiteLLM, Anthropic Messages endpoints, and Google Generative AI. `ANTHROPIC_*` remains available for existing Anthropic-compatible deployments. Pi drives the model; pibox drives Pi.\n- A target workspace. Run the wrapper from that directory so it mounts the path and preserves Pi state.\n\n## Quick Install\n\n### Host wrapper\n\nInstall the wrapper for interactive and one-shot use:\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/psyb0t/docker-pibox/main/install.sh | bash\n```\n\nInstall `pibox`, `codexbox`, and `claudebox` in the same command directory,\nnormally `/usr/local/bin`, when a box needs to launch another. Each wrapper\nmounts sibling wrapper files read-only. The sibling wrapper then asks the host\nDocker daemon to mount its own data directory.\n\n### Interactive / one-shot (no server)\n\n```bash\npibox\npibox -p \"inspect this workspace\"\nPIBOX_FULL=1 pibox -p \"run the full test suite\"\n```\n\nUse the wrapper for normal interactive and one-shot work. It handles the\nworkspace mount, Pi state, aicodebox state, SSH state, image selection, and\nnested launch context. Do not construct a `docker run` command unless the user\nexplicitly asks for a direct container deployment.\n\n### REST / OpenAI-compatible / MCP server\n\n```bash\ndocker run -d --name pibox --network host \\\n  -e PIBOX_API_MODE=1 \\\n  -e PIBOX_API_MODE_TOKEN=your-secret \\\n  -e PIBOX_AVAILABLE_MODELS=glm-4.6,glm-4.5-air \\\n  -e PIBOX_MCP_MODE=1 \\\n  -e PIBOX_MCP_MODE_TOKEN=your-mcp-secret \\\n  -e ANTHROPIC_AUTH_TOKEN=your-token \\\n  -e ANTHROPIC_BASE_URL=https://api.z.ai/api/anthropic \\\n  -e ANTHROPIC_MODEL=glm-4.6 \\\n  -v \"$PWD/workspace:/workspace\" \\\n  psyb0t/pibox:latest\n```\n\n`--network host` is convenient for local use; for anything else publish the port explicitly (`-p 8080:8080`) instead.\n\n**Verify:** `curl http://localhost:8080/healthz` returns `{\"ok\": true, \"adapter\": \"pi\"}`.\n\n### Telegram bot\n\n```bash\ndocker run -d --name pibox-tg \\\n  -e PIBOX_TELEGRAM_MODE=1 \\\n  -e PIBOX_TELEGRAM_MODE_TOKEN=your-bot-token \\\n  -e ANTHROPIC_AUTH_TOKEN=your-token \\\n  -e ANTHROPIC_BASE_URL=https://api.z.ai/api/anthropic \\\n  -e ANTHROPIC_MODEL=glm-4.6 \\\n  -v \"$PWD/workspace:/workspace\" \\\n  -v \"$PWD/telegram.yml:/home/aicode/.aicodebox/telegram.yml:ro\" \\\n  psyb0t/pibox:latest\n```\n\nRequires a `telegram.yml` with at least `allowed_chats` set (see [Telegram bot mode](../SKILL.md#telegram-bot-mode)) — the bot ignores messages from chats not on the allowlist.\n\n### Cron scheduler\n\n```bash\ndocker run -d --name pibox-cron \\\n  -e PIBOX_CRON_MODE=1 \\\n  -e PIBOX_CRON_MODE_FILE=/config/cron.yaml \\\n  -e ANTHROPIC_AUTH_TOKEN=your-token \\\n  -e ANTHROPIC_BASE_URL=https://api.z.ai/api/anthropic \\\n  -e ANTHROPIC_MODEL=glm-4.6 \\\n  -v \"$PWD/workspace:/workspace\" \\\n  -v \"$PWD/cron.yaml:/config/cron.yaml:ro\" \\\n  psyb0t/pibox:latest\n```\n\n### docker-compose (API + MCP)\n\n```yaml\nservices:\n  pibox:\n    image: psyb0t/pibox:latest\n    environment:\n      PIBOX_API_MODE: \"1\"\n      PIBOX_API_MODE_TOKEN: your-secret\n      PIBOX_AVAILABLE_MODELS: glm-4.6,glm-4.5-air\n      PIBOX_MCP_MODE: \"1\"\n      PIBOX_MCP_MODE_TOKEN: your-mcp-secret\n      ANTHROPIC_AUTH_TOKEN: your-token\n      ANTHROPIC_BASE_URL: https://api.z.ai/api/anthropic\n      ANTHROPIC_MODEL: glm-4.6\n    ports:\n      - \"8080:8080\"\n    volumes:\n      - ./workspace:/workspace\n    restart: unless-stopped\n```\n\n## Foreground Mode Rules\n\n`PIBOX_API_MODE`, `PIBOX_TELEGRAM_MODE`, `PIBOX_CRON_MODE` are the foreground modes. Priority order if multiple are set: API wins over everything. Telegram + Cron together is the one allowed pairing (cron runs in-thread inside the telegram process). If none are set, the container falls through to pi's own CLI (interactive shell, or one-shot exec if args are passed).\n\n`PIBOX_MCP_MODE` is independent of the above — it coexists with any foreground mode (mounted at `/mcp` in API mode, sidecar elsewhere) or with none at all (sidecar only, no other surface reachable).\n\n## Environment Variables\n\nNaming convention: `PIBOX_<MODE>_MODE=1` is the on/off flag, `PIBOX_<MODE>_MODE_<KNOB>=...` is its config. Non-mode-scoped vars (workspace, container name, available models) are bare `PIBOX_*`.\n\nThe image is built on [aicodebox](https://github.com/psyb0t/docker-aicodebox); the equivalent `AICODEBOX_*` names also work — the entrypoint translates `PIBOX_X` to `AICODEBOX_X` when only the pibox-prefixed one is set. If both are set, `AICODEBOX_*` wins.\n\n### Mode flags\n\n| Var | Default | What it does |\n|-----|---------|---------------|\n| `PIBOX_API_MODE` | `0` | Boot the HTTP API server (foreground) |\n| `PIBOX_TELEGRAM_MODE` | `0` | Boot the Telegram bot (foreground) |\n| `PIBOX_CRON_MODE` | `0` | Boot the cron scheduler (foreground; in-thread when telegram is also on) |\n| `PIBOX_MCP_MODE` | `0` | Expose MCP — mounted at `/mcp` in API mode, or as a sidecar elsewhere |\n\n### API mode config\n\n| Var | Default | What it does |\n|-----|---------|---------------|\n| `PIBOX_API_MODE_PORT` | `8080` | Port the API server binds to |\n| `PIBOX_API_MODE_TOKEN` | empty | Bearer token for the REST + OpenAI-compatible surface. Empty = no auth — see [Security & safety](../SKILL.md#security--safety) |\n\n### Telegram mode config\n\n| Var | Default | What it does |\n|-----|---------|---------------|\n| `PIBOX_TELEGRAM_MODE_TOKEN` | — | Bot token from @BotFather (required) |\n| `PIBOX_TELEGRAM_MODE_CONFIG` | `~/.aicodebox/telegram.yml` | Path to the telegram config yaml |\n| `PIBOX_TELEGRAM_MODE_OVERRIDES` | `~/.aicodebox/telegram_overrides.json` | Per-chat override store (model/effort/system prompts) |\n\n### Cron mode config\n\n| Var | Default | What it does |\n|-----|---------|---------------|\n| `PIBOX_CRON_MODE_FILE` | — | Path to the cron yaml (required) |\n| `PIBOX_CRON_MODE_HISTORY_DIR` | `~/.aicodebox/cron/history` | Where cron writes per-run history dirs (`meta.json`, `stdout.log`, `stderr.log`, `result.txt`, `telegram.json`) |\n\n### MCP mode config\n\n| Var | Default | What it does |\n|-----|---------|---------------|\n| `PIBOX_MCP_MODE_PORT` | `8081` | Port the sidecar MCP server binds to (ignored when mounted inside API mode) |\n| `PIBOX_MCP_MODE_TOKEN` | empty | Bearer token for MCP. Empty = no auth — see [Security & safety](../SKILL.md#security--safety). No fallback to `PIBOX_API_MODE_TOKEN` |\n\n### Workspace & runtime\n\n| Var | Default | What it does |\n|-----|---------|---------------|\n| `PIBOX_WORKSPACE` | `/workspace` | Root workspace dir inside the container |\n| `PIBOX_CONTAINER_NAME` | `aicodebox` | Used to scope per-container state files in direct Docker runs. The host wrapper derives a per-workspace name. |\n| `PIBOX_AVAILABLE_MODELS` | — | **Required for API mode.** CSV list returned by `/openai/v1/models` and shown in the telegram `/model` picker. pibox registers every listed model with the upstream provider under `PIBOX_PROVIDER_API` |\n| `PIBOX_AVAILABLE_EFFORTS` | adapter list (`off,minimal,low,medium,high,xhigh`) | Override the effort/`--thinking` list shown by the telegram `/effort` picker (comma-separated) |\n\n### LLM upstream\n\n#### Generic custom HTTP provider\n\nUse these variables for Pi's documented custom HTTP APIs. They configure the upstream model Pi uses, not pibox's own OpenAI-compatible `/openai/v1` endpoint.\n\n| Var | Default | What it does |\n|-----|---------|--------------|\n| `PIBOX_PROVIDER_NAME` | `pibox` | Provider identifier. Lowercase letters, numbers, and `-` only. |\n| `PIBOX_PROVIDER_API` | `openai-completions` | `openai-completions`, `openai-responses`, `anthropic-messages`, or `google-generative-ai` |\n| `PIBOX_PROVIDER_BASE_URL` | none | Required upstream HTTP base URL |\n| `PIBOX_PROVIDER_API_KEY` | none | Required upstream API key or token |\n| `PIBOX_PROVIDER_MODEL` | none | Required default upstream model ID |\n\nLiteLLM example:\n\n```bash\ndocker run --rm --network host \\\n  -e PIBOX_PROVIDER_BASE_URL=http://127.0.0.1:4000/v1 \\\n  -e PIBOX_PROVIDER_API=openai-completions \\\n  -e PIBOX_PROVIDER_API_KEY=your-litellm-virtual-key \\\n  -e PIBOX_PROVIDER_MODEL=your-model-id \\\n  -v \"$PWD/workspace:/workspace\" \\\n  psyb0t/pibox:latest \\\n  -p \"list the files in /workspace\"\n```\n\nFor API mode, set `PIBOX_AVAILABLE_MODELS=your-model-id` too. Do not combine `PIBOX_PROVIDER_*` with `ANTHROPIC_BASE_URL`. pibox rejects the ambiguous configuration. The generic variables cover Pi's documented custom HTTP APIs, not every cloud-specific built-in provider.\n\n#### Anthropic compatibility\n\n| Var | Purpose |\n|-----|---------|\n| `ANTHROPIC_AUTH_TOKEN` | Bearer token (Z.AI, direct Anthropic, etc.) |\n| `ANTHROPIC_API_KEY` | Same thing — pi reads both |\n| `ANTHROPIC_BASE_URL` | Endpoint override (default `https://api.anthropic.com`) |\n| `ANTHROPIC_MODEL` | Default model when the caller doesn't specify one |\n\n## OpenAI endpoint headers\n\nNon-standard `x-aicodebox-*` request headers extend `POST /openai/v1/chat/completions` beyond stock OpenAI fields (legacy `x-claude-*` aliases also work for `workspace`/`continue`/`append-system-prompt`):\n\n| Header | Purpose |\n|---|---|\n| `x-aicodebox-workspace` | Pin the run to a workspace subpath instead of the ephemeral/default one |\n| `x-aicodebox-continue` | `1`/`true`/`yes` to continue the most recent session in that workspace instead of starting fresh |\n| `x-aicodebox-append-system-prompt` | Append text to the system prompt |\n| `x-aicodebox-json-schema` | JSON-encoded schema — fallback for clients that can't set the standard `response_format` body field (body field wins if both are set) |\n| `x-aicodebox-resume` | Resume a specific session id |\n| `x-aicodebox-extra-args` | Extra pi CLI args — JSON array or comma-separated string |\n| `x-aicodebox-timeout-seconds` | Per-request run timeout |\n| `x-aicodebox-tools-allowlist` | Restrict pi's own internal tools — JSON array or comma-separated string |\n| `x-aicodebox-no-tools` | `1`/`true`/`yes` to disable pi's internal tools; in OpenAI-tools mode this is the override to re-enable them (send `0`) |\n\n## Ports\n\n| Port | Default | Service |\n|---|---|---|\n| API/OAI/MCP-in-API | `8080` (`PIBOX_API_MODE_PORT`) | REST, `/openai/v1/*`, `/mcp` (when `PIBOX_MCP_MODE=1`) |\n| MCP sidecar | `8081` (`PIBOX_MCP_MODE_PORT`) | MCP only, used when API mode is not the foreground |\n\nNo ports are opened for Telegram, cron, interactive, or one-shot exec modes — they're outbound-only or container-boundary-trusted.\n\n## Management\n\n```bash\ndocker logs -f pibox    # tail logs\ndocker stop pibox       # stop\ndocker rm pibox          # remove\ndocker pull psyb0t/pibox:latest  # update\n```\n\nCheck what's running inside a live API-mode container:\n\n```bash\ncurl -s http://localhost:8080/status -H \"Authorization: Bearer your-secret\" | jq\n```\n\n## OpenClaw / ClawHub Config\n\n```bash\nexport PIBOX_URL=http://localhost:8080\nexport PIBOX_API_MODE_TOKEN=<token>  # only if the server requires it\n```\n\nOr via `~/.openclaw/openclaw.json`:\n\n```json\n{\n  \"skills\": {\n    \"entries\": {\n      \"pibox\": {\n        \"env\": {\n          \"PIBOX_URL\": \"http://localhost:8080\",\n          \"PIBOX_API_MODE_TOKEN\": \"<token>\"\n        }\n      }\n    }\n  }\n}\n```\n\nFile v0.18.3:skill-card.md\n\n## Description:\n\nInstall, configure, or run pi-coding-agent through the pibox wrapper, or connect to its HTTP, MCP, Telegram, or cron surfaces.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[psyb0t](https://clawhub.ai/user/psyb0t)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers and engineers use pibox to install and operate pi-coding-agent in a container through an interactive wrapper, one-shot runs, REST or OpenAI-compatible APIs, MCP, Telegram, or scheduled cron workflows.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: The REST, OpenAI-compatible, and MCP surfaces can expose agent execution and workspace file access when reachable by untrusted clients.\n\nMitigation: Set non-empty API and MCP bearer tokens, bind services to localhost or an authenticating proxy, and avoid exposing the service broadly.\n\nRisk: Container installation and runtime behavior rely on this third-party publisher's image and installer.\n\nMitigation: Review the installer and container image, prefer pinned image digests, and mount only the workspace paths required for the task.\n\nRisk: Delete operations and cancellation endpoints can remove files or interrupt runs without recovery.\n\nMitigation: Treat delete and cancellation routes as administrative actions, confirm exact targets, and avoid bulk deletion workflows.\n\nRisk: Cron and Telegram modes can trigger repeated or remote agent actions against configured workspaces.\n\nMitigation: Restrict chat/user allowlists, review scheduled jobs, and keep these modes scoped to trusted operators.\n\n## Reference(s):\n\n- [pibox setup](references/setup.md)\n- [pibox ClawHub page](https://clawhub.ai/psyb0t/skills/pibox)\n- [pi-coding-agent](https://github.com/earendil-works/pi-mono/tree/main/packages/coding-agent)\n- [aicodebox container](https://github.com/psyb0t/docker-aicodebox)\n- [Model Context Protocol](https://modelcontextprotocol.io)\n\n## Skill Output:\n\n**Output Type(s):** [text, markdown, code, shell commands, configuration, guidance]\n\n**Output Format:** [Markdown guidance with inline bash, JSON, and YAML examples]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [May produce API requests, wrapper commands, service configuration, and operational guidance for containerized agent runs.]\n\n## Skill Version(s):\n\n0.18.3 (source: release evidence)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nArchive v0.18.2: 4 files, 13440 bytes\n\nFiles: references/setup.md (11245b), skill-card.md (2845b), SKILL.md (20144b), _meta.json (125b)\n\nFile v0.18.2:SKILL.md\n\n---\nname: pibox\ndescription: pi-coding-agent (earendil-works) running on the network inside an aicodebox container. Exposes seven programmatic surfaces on one image — interactive shell, one-shot exec (`-p \"...\"`), an HTTP REST API (run/async/cancel, workspace file ops), an OpenAI-compatible `/openai/v1/chat/completions` endpoint (streaming, client-executed tool calling, response_format/JSON-schema), an MCP server at `/mcp` (mounted in API mode or as a sidecar), a Telegram bot, and a cron scheduler that fires pi on a schedule. Foreground modes (API/Telegram/Cron) are mutually exclusive except Telegram+Cron; MCP coexists with any of them. Bearer-token auth per surface (`PIBOX_API_MODE_TOKEN`, `PIBOX_MCP_MODE_TOKEN`), empty = no auth. Use when the user wants to drive pi-coding-agent programmatically over HTTP/MCP/Telegram/cron instead of a local terminal session, or needs to reason about which pibox mode/endpoint fits a given integration.\nhomepage: https://github.com/psyb0t/docker-pibox\nuser-invocable: true\nmetadata:\n  { \"openclaw\": { \"emoji\": \"🥧\", \"primaryEnv\": \"PIBOX_URL\", \"requires\": { \"bins\": [\"docker\", \"curl\"] } } }\n---\n\n# pibox\n\n[pi-coding-agent](https://github.com/earendil-works/pi-mono/tree/main/packages/coding-agent) inside an [aicodebox](https://github.com/psyb0t/docker-aicodebox) container. One image, seven ways in: interactive shell, one-shot exec, HTTP REST API, OpenAI-compatible endpoint, MCP server, Telegram bot, cron scheduler.\n\nYou talk to pibox, pibox talks to pi, and Pi talks to the configured upstream LLM. Use `PIBOX_PROVIDER_*` for Pi's documented custom HTTP APIs, including LiteLLM and Anthropic-compatible endpoints. `ANTHROPIC_*` remains a compatibility shortcut for existing Anthropic Messages deployments.\n\nFor installation and configuration, see [references/setup.md](references/setup.md).\n\n## Security & safety\n\n- **No auth when `PIBOX_API_MODE_TOKEN` is unset.** With it empty the REST/OpenAI-compatible API surface is UNAUTHENTICATED — anyone who can reach it gets full agent-execution and workspace file-read/write/delete access. NEVER expose such an instance on a network or to untrusted agents; set the token and bind to loopback / behind an authenticating proxy.\n- **No auth when `PIBOX_MCP_MODE_TOKEN` is unset.** Same story for the MCP surface (`/mcp` or the sidecar) — empty token means unauthenticated `run_prompt`/file-tool access, and it does not fall back to `PIBOX_API_MODE_TOKEN`. Set it explicitly.\n- **Destructive & irreversible.** `DELETE /run/{id}`, `DELETE /files/{path}`, and the MCP `delete_file` tool remove state with no undo (canceled runs can't be resumed; deleted files are gone). An agent must NEVER call these unless the user explicitly asked for that exact action; confirm the specific target first, scope it to the current task, and never enumerate-then-bulk-delete. On a shared/multi-tenant instance a deletion can destroy another caller's in-flight run or workspace file — treat these routes as admin-only.\n\n## When To Use\n\n- Drive pi-coding-agent from a script/service instead of an interactive terminal (`/run`, `/openai/v1/chat/completions`, or MCP tools).\n- Wire pi into an OpenAI-SDK-compatible client (LangChain, openai-python) via the `/openai/v1/*` surface.\n- Give an MCP-aware agent (Claude, Cursor, OpenClaw) remote tool access to a pi-driven workspace.\n- Chat with pi from Telegram, with per-chat model/effort overrides and file transfer.\n- Schedule recurring pi runs (standups, digests, periodic maintenance) via cron mode.\n- One-off container run for a single prompt (CI step, quick script) via one-shot exec.\n\n## When NOT To Use\n\n- Don't run two foreground modes together except Telegram+Cron (cron runs in-thread inside telegram) — API set alongside anything else wins and the others don't start.\n- Don't expect `/openai/v1/chat/completions` to stream token-by-token when `tools` or a JSON schema is in play — those modes compute the full answer first and replay it as a single-shot SSE stream (still a valid stream, just not incremental). Plain chat streams incrementally.\n- Don't rely on `PIBOX_MCP_MODE_TOKEN` falling back to `PIBOX_API_MODE_TOKEN` — MCP has its own bearer, no fallback.\n- Don't point multiple concurrent runs at the same workspace — the API/OAI layer returns 409 \"workspace busy\" while a run is in flight in that workspace.\n\n## Interactive shell mode\n\nNo mode env var set, no args passed to `docker run`. Falls through to pi's own CLI, invoked directly — a normal interactive pi session inside the container.\n\n```bash\ndocker run -it --rm \\\n  -e ANTHROPIC_AUTH_TOKEN=your-token \\\n  -e ANTHROPIC_BASE_URL=https://api.z.ai/api/anthropic \\\n  -e ANTHROPIC_MODEL=glm-4.6 \\\n  -v \"$PWD/workspace:/workspace\" \\\n  psyb0t/pibox:latest\n```\n\nAuth: none at the container boundary. Pi uses the upstream provider variables in [references/setup.md](references/setup.md#llm-upstream).\n\n## One-shot exec mode\n\nNo mode env var set, args passed after the image name are forwarded verbatim to the `pi` binary (passthrough). `-p \"<prompt>\"` runs pi non-interactively and prints the result to stdout, then exits.\n\n```bash\ndocker run --rm \\\n  -e ANTHROPIC_AUTH_TOKEN=your-token \\\n  -e ANTHROPIC_BASE_URL=https://api.z.ai/api/anthropic \\\n  -e ANTHROPIC_MODEL=glm-4.6 \\\n  -v \"$PWD/workspace:/workspace\" \\\n  psyb0t/pibox:latest \\\n  -p \"list the files in /workspace\"\n```\n\nAny Pi CLI flag works here (`--model`, `--thinking`, `--session`, etc.). Auth: none at the container boundary. Pi uses the upstream provider variables in [references/setup.md](references/setup.md#llm-upstream).\n\n## REST API mode\n\n`PIBOX_API_MODE=1`. FastAPI server on `:8080` (override `PIBOX_API_MODE_PORT`). **Requires `PIBOX_AVAILABLE_MODELS=<csv>`** — the server refuses to boot without it (no sensible default; pi can drive any provider's models).\n\n```bash\ndocker run -d --network host \\\n  -e PIBOX_API_MODE=1 \\\n  -e PIBOX_API_MODE_TOKEN=your-secret \\\n  -e PIBOX_AVAILABLE_MODELS=glm-4.6,glm-4.5-air \\\n  -e ANTHROPIC_AUTH_TOKEN=your-token \\\n  -e ANTHROPIC_BASE_URL=https://api.z.ai/api/anthropic \\\n  -e ANTHROPIC_MODEL=glm-4.6 \\\n  -v \"$PWD/workspace:/workspace\" \\\n  psyb0t/pibox:latest\n```\n\n| Method | Path | What it does |\n|--------|------|--------------|\n| `GET` | `/healthz` | liveness — `{ok, adapter}`, unauthenticated |\n| `GET` | `/status` | in-flight runs + busy workspaces |\n| `POST` | `/run` | run the agent — sync by default; body `async` or `fireAndForget` makes it fire-and-poll |\n| `GET` | `/run/result?runId=<id>` | poll a run started with `async`/`fireAndForget` |\n| `DELETE` | `/run/{id}` | cancel an in-flight run (kills the subprocess) |\n| `GET` | `/files` | list the workspace root — `{entries: [{name, type, size?}, ...]}` |\n| `GET` | `/files/{path}` | list a sub-directory, or stream a file's bytes |\n| `PUT` | `/files/{path}` | upload — raw request body becomes the file contents; parent dirs auto-created |\n| `DELETE` | `/files/{path}` | delete a file (refuses directories — 400) |\n| `POST` | `/openai/v1/chat/completions` | OpenAI-compatible chat (see below) |\n| `GET` | `/openai/v1/models` | model list, from `PIBOX_AVAILABLE_MODELS` |\n| `POST` | `/mcp` | MCP server (streamable HTTP) — mounted only when `PIBOX_MCP_MODE=1` |\n\nAll `/files/*` paths resolve against the workspace root with traversal checking — `..` segments that escape the root return 400. Every route except `/healthz` is gated by `Authorization: Bearer <PIBOX_API_MODE_TOKEN>` when that var is set; empty/unset token = no auth.\n\n**No auth when `PIBOX_API_MODE_TOKEN` is unset.** With it empty the API is UNAUTHENTICATED — anyone who can reach it gets run-the-agent and workspace file-read/write/delete access. NEVER expose such an instance on a network or to untrusted agents; set the token and bind to loopback / behind an authenticating proxy.\n\n**Destructive & irreversible.** `DELETE /run/{id}` kills the in-flight subprocess with no undo, and `DELETE /files/{path}` deletes a workspace file with no undo. An agent must NEVER call either unless the user explicitly asked for that exact action; confirm the specific target first; scope it to the current task; never enumerate-then-bulk-delete. On a shared/multi-tenant instance this can disrupt or destroy another caller's run or data — treat these routes as admin-only.\n\n```bash\n# sync run\ncurl -s http://localhost:8080/run \\\n  -H \"Authorization: Bearer your-secret\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"prompt\": \"say HELLO\", \"workspace\": \"/workspace\"}'\n\n# async run, then poll\nRUN_ID=$(curl -s http://localhost:8080/run \\\n  -H \"Authorization: Bearer your-secret\" -H \"Content-Type: application/json\" \\\n  -d '{\"prompt\": \"long task\", \"async\": true}' | jq -r .runId)\ncurl -s \"http://localhost:8080/run/result?runId=$RUN_ID\" \\\n  -H \"Authorization: Bearer your-secret\"\n\n# cancel it\ncurl -s -X DELETE \"http://localhost:8080/run/$RUN_ID\" \\\n  -H \"Authorization: Bearer your-secret\"\n\n# upload / download / list / delete a workspace file\ncurl -sS -X PUT -H \"Authorization: Bearer your-secret\" \\\n  --data-binary @local.txt http://localhost:8080/files/notes/hello.txt\ncurl -sS -H \"Authorization: Bearer your-secret\" \\\n  http://localhost:8080/files/notes/hello.txt\ncurl -sS -H \"Authorization: Bearer your-secret\" \\\n  http://localhost:8080/files/notes | jq\ncurl -sS -X DELETE -H \"Authorization: Bearer your-secret\" \\\n  http://localhost:8080/files/notes/hello.txt\n```\n\n**`POST /run`** body fields: `prompt` (required), `workspace`, `model`, `systemPrompt`, `appendSystemPrompt`, `jsonSchema`, `noContinue`, `resume`, `timeoutSeconds`, `thinking`, `noTools`, `toolsAllowlist`, `extraArgs`, `async`, `fireAndForget`, `includeRaw`. With `jsonSchema` set the response is verbose: `text`, `json` (schema-validated), `events`, `sessionId`, `usage`, `attempts` (per-retry breakdown, up to 3 self-correction retries on parse/validation failure). Without `jsonSchema` the response is lean: `{runId, workspace, exitCode, text}`.\n\n## OpenAI-compatible endpoint mode\n\nSame `PIBOX_API_MODE=1` server, `POST /openai/v1/chat/completions` and `GET /openai/v1/models`. Drop-in for any OpenAI-SDK client — point the base URL at `http://host:8080/openai/v1` and set the model to one of `PIBOX_AVAILABLE_MODELS`.\n\n```bash\ncurl -s http://localhost:8080/openai/v1/chat/completions \\\n  -H \"Authorization: Bearer your-secret\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"model\": \"glm-4.6\",\n    \"messages\": [{\"role\": \"user\", \"content\": \"say HELLO\"}]\n  }'\n```\n\n**Streaming** (`\"stream\": true`): plain chat streams incrementally, one SSE chunk per token delta. Requests carrying `tools` or a JSON-schema constraint can't stream token-by-token (the answer only exists once fully computed) — they're **buffered**: the whole response is computed, then replayed as a single-shot SSE stream (role chunk → one content/tool_calls delta → finish chunk → `[DONE]`). The client's streaming parser is satisfied either way.\n\n**Tools / `tool_choice`** (OpenAI client-executed tool calling): send `tools` (OpenAI function-schema array) and optionally `tool_choice` (`auto`/`none`/`required`/`{\"type\":\"function\",\"function\":{\"name\":...}}`). pibox's own internal tools (bash, file edits) default OFF while in tool mode so the model behaves as a pure function-calling LLM — override with header `x-aicodebox-no-tools: 0` to re-enable the hybrid. The response comes back as `tool_calls` + `finish_reason: \"tool_calls\"`, exactly like OpenAI; you execute the tool client-side and send the result back in the next message round.\n\n**`response_format` / JSON-schema**: standard OpenAI `response_format` body field —`{\"type\": \"text\"}` (default), `{\"type\": \"json_object\"}` (force parseable JSON, no shape constraint), or `{\"type\": \"json_schema\", \"json_schema\": {\"name\": ..., \"schema\": {...}}}` (schema-validated, with up to 3 self-correction retries on failure → 422 if still invalid). `tools` and `response_format` **compose** in one request: a tool-call turn returns `tool_calls` (not schema-checked); the model's final answer (no more tool calls) is what gets schema-validated.\n\nExtra `x-aicodebox-*` headers (workspace pinning, session continuation, extra args, timeout, tools allowlist) are documented in [references/setup.md](references/setup.md#openai-endpoint-headers). Upstream provider errors (auth failure, rate limit, content-safety rejection) surface as HTTP 400, not a silent empty response.\n\n## MCP server mode\n\n`PIBOX_MCP_MODE=1`. Exposes an [MCP](https://modelcontextprotocol.io) (streamable HTTP) surface with 5 tools: `run_prompt`, `list_files`, `read_file`, `write_file`, `delete_file`. Coexists with any foreground mode:\n\n| Foreground | MCP placement |\n|---|---|\n| API mode (`PIBOX_API_MODE=1`) | mounted at `/mcp` on the API port — no extra process |\n| Telegram / Cron / passthrough / none | sidecar uvicorn on its own port, `PIBOX_MCP_MODE_PORT` (default `8081`), mounted at the port root |\n\n```bash\nclaude mcp add --transport http pibox http://localhost:8080/mcp \\\n  --header \"Authorization: Bearer your-mcp-token\"\n```\n\nRaw JSON-RPC (debugging, non-MCP-aware callers):\n\n```bash\ncurl -s http://localhost:8080/mcp \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Accept: application/json, text/event-stream\" \\\n  -H \"Authorization: Bearer your-mcp-token\" \\\n  -d '{\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"tools/list\"}'\n```\n\n`run_prompt(prompt, workspace?, model?, system_prompt?, append_system_prompt?, no_continue=true, resume?, thinking?, json_schema?)` invokes the agent and returns its text. `list_files`/`read_file`/`write_file`/`delete_file` operate on workspace-relative paths with the same traversal guard as the REST `/files` endpoints.\n\n**Destructive & irreversible.** `delete_file` removes a workspace file with no undo. An agent must NEVER call it unless the user explicitly asked for that exact action; confirm the specific target first; scope it to the current task; never enumerate-then-bulk-delete. On a shared/multi-tenant instance this can destroy another caller's workspace data — treat it as admin-only.\n\nAuth: `PIBOX_MCP_MODE_TOKEN=<token>` — bearer via `Authorization: Bearer …`, or `?apiToken=…` query param for clients that can't set headers. Empty = no auth. **No fallback to `PIBOX_API_MODE_TOKEN`.**\n\n**No auth when `PIBOX_MCP_MODE_TOKEN` is unset.** With it empty the MCP surface is UNAUTHENTICATED — anyone who can reach it gets `run_prompt` (arbitrary agent execution) and workspace file read/write/delete access. NEVER expose such an instance on a network or to untrusted agents; set the token and bind to loopback / behind an authenticating proxy.\n\n## Telegram bot mode\n\n`PIBOX_TELEGRAM_MODE=1` + `PIBOX_TELEGRAM_MODE_TOKEN=<token from @BotFather>`.\n\n- Text in → pi runs → Markdown→HTML rendered response back.\n- File uploads land in the chat's workspace. `[SEND_FILE: path]` in pi's output delivers workspace files as Telegram attachments.\n- Per-chat overrides: `/model`, `/effort` (maps to pi's `--thinking` levels), `/system_prompt`, `/append_system_prompt`. Persisted across restarts.\n- `/cancel` kills the in-flight run. `/reload` re-reads config. `/config` dumps merged settings. `/status` shows in-flight state. `/fetch <path>` downloads a file. `/start`, `/help` for basics.\n- Replies to cron messages inject the job's instruction + result so pi has full context for follow-ups.\n\nConfig at `$HOME/.aicodebox/telegram.yml` (override via `PIBOX_TELEGRAM_MODE_CONFIG`):\n\n```yaml\nallowed_chats: [-100123, 42]\ndefault:\n  model: glm-4.6\n  workspace: shared\nchats:\n  -100123:\n    workspace: alpha\n    allowed_users: [10, 20]\n```\n\nAuth: chat/user allowlisting via the config yaml (`allowed_chats`, per-chat `allowed_users`) — no separate bearer token, the bot token itself gates who can even message it.\n\n## Cron scheduler mode\n\n`PIBOX_CRON_MODE=1` + `PIBOX_CRON_MODE_FILE=/path/to/cron.yaml`. 6-field cron schedules via croniter. Each job fires pi with the given instruction on schedule.\n\n```yaml\njobs:\n  - name: morning-standup\n    schedule: \"0 0 9 * * 1-5\"\n    instruction: |\n      Summarize what changed in /workspace since yesterday.\n      Be brief. One paragraph max.\n    workspace: myproject\n    telegram_chat_id: -100123\n    model: glm-4.6\n    thinking: low\n```\n\nEach run gets a history dir at `$HOME/.aicodebox/cron/history/<workspace>/<timestamp>-<job>/` (override root via `PIBOX_CRON_MODE_HISTORY_DIR`) with `meta.json`, `stdout.log`, `stderr.log`, `result.txt`. If telegram is also configured, `telegram.json` lands there too and the next run's prompt gets a \"prior run\" hint so pi can reference its own history without you wiring it up. Running alongside Telegram mode (`PIBOX_TELEGRAM_MODE=1` + `PIBOX_CRON_MODE=1`) runs cron in-thread inside the telegram process — the only foreground-mode pairing allowed.\n\nAuth: none — this is a scheduled background job, not a request-driven surface. `telegram_chat_id` on a job routes its result through the (already-authenticated) Telegram bot if set.\n\n## Auth (LLM upstream)\n\nUse `PIBOX_PROVIDER_*` for Pi's documented custom HTTP APIs, including LiteLLM and Anthropic-compatible endpoints. `ANTHROPIC_*` remains a compatibility path for existing Anthropic Messages endpoints. The full configuration matrix and examples are in [references/setup.md](references/setup.md#llm-upstream).\n\n| Var | Purpose |\n|-----|---------|\n| `ANTHROPIC_AUTH_TOKEN` | Bearer token (Z.AI, direct Anthropic, etc.) |\n| `ANTHROPIC_API_KEY` | Same thing — pi reads both |\n| `ANTHROPIC_BASE_URL` | Endpoint override (default `https://api.anthropic.com`) |\n| `ANTHROPIC_MODEL` | Default model when the caller doesn't specify one |\n\nZ.AI's GLM models are a fast/cheap default: `ANTHROPIC_BASE_URL=https://api.z.ai/api/anthropic` + `ANTHROPIC_MODEL=glm-4.6`.\n\npi's thinking levels (`--thinking`): `off`, `minimal`, `low`, `medium`, `high`, `xhigh`. Exposed as `/effort` in Telegram mode and `thinking` in API/OAI requests.\n\n**Surface-level auth** (separate from the LLM upstream) is per-mode: `PIBOX_API_MODE_TOKEN` gates the REST + OAI routes, `PIBOX_MCP_MODE_TOKEN` gates MCP (no fallback between the two), Telegram gates by bot-token possession + chat/user allowlist, cron and interactive/exec modes have no surface auth (container-boundary trust). Both `PIBOX_API_MODE_TOKEN` and `PIBOX_MCP_MODE_TOKEN` default to empty, which means no auth — see [Security & safety](#security--safety) above before exposing either surface beyond localhost.\n\n## Typical Workflows\n\n**One-off task from a script, no server:**\n\n```bash\ndocker run --rm -e ANTHROPIC_AUTH_TOKEN=$TOKEN -e ANTHROPIC_BASE_URL=$BASE_URL \\\n  -e ANTHROPIC_MODEL=glm-4.6 -v \"$PWD:/workspace\" \\\n  psyb0t/pibox:latest -p \"summarize the diff in /workspace\"\n```\n\n**Long-running server, drive it with curl:**\n\n```bash\ndocker run -d --network host -e PIBOX_API_MODE=1 -e PIBOX_API_MODE_TOKEN=$SECRET \\\n  -e PIBOX_AVAILABLE_MODELS=glm-4.6 -e ANTHROPIC_AUTH_TOKEN=$TOKEN \\\n  -e ANTHROPIC_BASE_URL=$BASE_URL -v \"$PWD/workspace:/workspace\" psyb0t/pibox:latest\ncurl -s http://localhost:8080/run -H \"Authorization: Bearer $SECRET\" \\\n  -H \"Content-Type: application/json\" -d '{\"prompt\": \"run the tests and report failures\"}'\n```\n\n**Structured extraction via JSON schema:**\n\n```bash\ncurl -s http://localhost:8080/run -H \"Authorization: Bearer $SECRET\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"prompt\": \"extract TODOs from /workspace\", \"jsonSchema\": {\"type\":\"object\",\"properties\":{\"todos\":{\"type\":\"array\",\"items\":{\"type\":\"string\"}}},\"required\":[\"todos\"]}}'\n```\n\n**Wire an MCP-aware agent (Claude Code, OpenClaw) to a running pibox:**\n\n```bash\nclaude mcp add --transport http pibox http://localhost:8080/mcp \\\n  --header \"Authorization: Bearer $MCP_TOKEN\"\n```\n\n**Chat + Telegram + scheduled digest, all on one box:**\n\n```bash\ndocker run -d --network host \\\n  -e PIBOX_TELEGRAM_MODE=1 -e PIBOX_TELEGRAM_MODE_TOKEN=$BOT_TOKEN \\\n  -e PIBOX_CRON_MODE=1 -e PIBOX_CRON_MODE_FILE=/config/cron.yaml \\\n  -e ANTHROPIC_AUTH_TOKEN=$TOKEN -e ANTHROPIC_BASE_URL=$BASE_URL \\\n  -v \"$PWD/workspace:/workspace\" -v \"$PWD/cron.yaml:/config/cron.yaml:ro\" \\\n  psyb0t/pibox:latest\n```\n\nFile v0.18.2:_meta.json\n\n{\n  \"ownerId\": \"kn79dhvmpjng4rp2jjk8k0v5xx80ccbk\",\n  \"slug\": \"pibox\",\n  \"version\": \"0.18.2\",\n  \"publishedAt\": 1789345051584\n}\n\nFile v0.18.2:references/setup.md\n\n# pibox setup\n\n## Requirements\n\n- Docker\n- An LLM endpoint supported by Pi's custom HTTP provider configuration. `PIBOX_PROVIDER_*` accepts an endpoint URL, protocol, API key or token, and model. It covers LiteLLM, Anthropic Messages endpoints, and Google Generative AI. `ANTHROPIC_*` remains available for existing Anthropic-compatible deployments. Pi drives the model; pibox drives Pi.\n- A host workspace directory to bind-mount (`-v $PWD/workspace:/workspace`), so agent output/session state persists across container restarts.\n\n## Quick Install\n\n### Host wrapper\n\nInstall the wrapper for interactive and one-shot use:\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/psyb0t/docker-pibox/main/install.sh | bash\n```\n\nInstall `pibox`, `codexbox`, and `claudebox` in the same command directory,\nnormally `/usr/local/bin`, when a box needs to launch another. Each wrapper\nmounts sibling wrapper files read-only. The sibling wrapper then asks the host\nDocker daemon to mount its own data directory.\n\n### Interactive / one-shot (no server)\n\n```bash\ndocker run -it --rm \\\n  -e ANTHROPIC_AUTH_TOKEN=your-token \\\n  -e ANTHROPIC_BASE_URL=https://api.z.ai/api/anthropic \\\n  -e ANTHROPIC_MODEL=glm-4.6 \\\n  -v \"$PWD/workspace:/workspace\" \\\n  psyb0t/pibox:latest\n```\n\nAppend `-p \"your prompt\"` (or any other pi CLI flags) to the `docker run` line for one-shot exec instead of an interactive shell.\n\n### REST / OpenAI-compatible / MCP server\n\n```bash\ndocker run -d --name pibox --network host \\\n  -e PIBOX_API_MODE=1 \\\n  -e PIBOX_API_MODE_TOKEN=your-secret \\\n  -e PIBOX_AVAILABLE_MODELS=glm-4.6,glm-4.5-air \\\n  -e PIBOX_MCP_MODE=1 \\\n  -e PIBOX_MCP_MODE_TOKEN=your-mcp-secret \\\n  -e ANTHROPIC_AUTH_TOKEN=your-token \\\n  -e ANTHROPIC_BASE_URL=https://api.z.ai/api/anthropic \\\n  -e ANTHROPIC_MODEL=glm-4.6 \\\n  -v \"$PWD/workspace:/workspace\" \\\n  psyb0t/pibox:latest\n```\n\n`--network host` is convenient for local use; for anything else publish the port explicitly (`-p 8080:8080`) instead.\n\n**Verify:** `curl http://localhost:8080/healthz` returns `{\"ok\": true, \"adapter\": \"pi\"}`.\n\n### Telegram bot\n\n```bash\ndocker run -d --name pibox-tg \\\n  -e PIBOX_TELEGRAM_MODE=1 \\\n  -e PIBOX_TELEGRAM_MODE_TOKEN=your-bot-token \\\n  -e ANTHROPIC_AUTH_TOKEN=your-token \\\n  -e ANTHROPIC_BASE_URL=https://api.z.ai/api/anthropic \\\n  -e ANTHROPIC_MODEL=glm-4.6 \\\n  -v \"$PWD/workspace:/workspace\" \\\n  -v \"$PWD/telegram.yml:/home/aicode/.aicodebox/telegram.yml:ro\" \\\n  psyb0t/pibox:latest\n```\n\nRequires a `telegram.yml` with at least `allowed_chats` set (see [Telegram bot mode](../SKILL.md#telegram-bot-mode)) — the bot ignores messages from chats not on the allowlist.\n\n### Cron scheduler\n\n```bash\ndocker run -d --name pibox-cron \\\n  -e PIBOX_CRON_MODE=1 \\\n  -e PIBOX_CRON_MODE_FILE=/config/cron.yaml \\\n  -e ANTHROPIC_AUTH_TOKEN=your-token \\\n  -e ANTHROPIC_BASE_URL=https://api.z.ai/api/anthropic \\\n  -e ANTHROPIC_MODEL=glm-4.6 \\\n  -v \"$PWD/workspace:/workspace\" \\\n  -v \"$PWD/cron.yaml:/config/cron.yaml:ro\" \\\n  psyb0t/pibox:latest\n```\n\n### docker-compose (API + MCP)\n\n```yaml\nservices:\n  pibox:\n    image: psyb0t/pibox:latest\n    environment:\n      PIBOX_API_MODE: \"1\"\n      PIBOX_API_MODE_TOKEN: your-secret\n      PIBOX_AVAILABLE_MODELS: glm-4.6,glm-4.5-air\n      PIBOX_MCP_MODE: \"1\"\n      PIBOX_MCP_MODE_TOKEN: your-mcp-secret\n      ANTHROPIC_AUTH_TOKEN: your-token\n      ANTHROPIC_BASE_URL: https://api.z.ai/api/anthropic\n      ANTHROPIC_MODEL: glm-4.6\n    ports:\n      - \"8080:8080\"\n    volumes:\n      - ./workspace:/workspace\n    restart: unless-stopped\n```\n\n## Foreground Mode Rules\n\n`PIBOX_API_MODE`, `PIBOX_TELEGRAM_MODE`, `PIBOX_CRON_MODE` are the foreground modes. Priority order if multiple are set: API wins over everything. Telegram + Cron together is the one allowed pairing (cron runs in-thread inside the telegram process). If none are set, the container falls through to pi's own CLI (interactive shell, or one-shot exec if args are passed).\n\n`PIBOX_MCP_MODE` is independent of the above — it coexists with any foreground mode (mounted at `/mcp` in API mode, sidecar elsewhere) or with none at all (sidecar only, no other surface reachable).\n\n## Environment Variables\n\nNaming convention: `PIBOX_<MODE>_MODE=1` is the on/off flag, `PIBOX_<MODE>_MODE_<KNOB>=...` is its config. Non-mode-scoped vars (workspace, container name, available models) are bare `PIBOX_*`.\n\nThe image is built on [aicodebox](https://github.com/psyb0t/docker-aicodebox); the equivalent `AICODEBOX_*` names also work — the entrypoint translates `PIBOX_X` to `AICODEBOX_X` when only the pibox-prefixed one is set. If both are set, `AICODEBOX_*` wins.\n\n### Mode flags\n\n| Var | Default | What it does |\n|-----|---------|---------------|\n| `PIBOX_API_MODE` | `0` | Boot the HTTP API server (foreground) |\n| `PIBOX_TELEGRAM_MODE` | `0` | Boot the Telegram bot (foreground) |\n| `PIBOX_CRON_MODE` | `0` | Boot the cron scheduler (foreground; in-thread when telegram is also on) |\n| `PIBOX_MCP_MODE` | `0` | Expose MCP — mounted at `/mcp` in API mode, or as a sidecar elsewhere |\n\n### API mode config\n\n| Var | Default | What it does |\n|-----|---------|---------------|\n| `PIBOX_API_MODE_PORT` | `8080` | Port the API server binds to |\n| `PIBOX_API_MODE_TOKEN` | empty | Bearer token for the REST + OpenAI-compatible surface. Empty = no auth — see [Security & safety](../SKILL.md#security--safety) |\n\n### Telegram mode config\n\n| Var | Default | What it does |\n|-----|---------|---------------|\n| `PIBOX_TELEGRAM_MODE_TOKEN` | — | Bot token from @BotFather (required) |\n| `PIBOX_TELEGRAM_MODE_CONFIG` | `~/.aicodebox/telegram.yml` | Path to the telegram config yaml |\n| `PIBOX_TELEGRAM_MODE_OVERRIDES` | `~/.aicodebox/telegram_overrides.json` | Per-chat override store (model/effort/system prompts) |\n\n### Cron mode config\n\n| Var | Default | What it does |\n|-----|---------|---------------|\n| `PIBOX_CRON_MODE_FILE` | — | Path to the cron yaml (required) |\n| `PIBOX_CRON_MODE_HISTORY_DIR` | `~/.aicodebox/cron/history` | Where cron writes per-run history dirs (`meta.json`, `stdout.log`, `stderr.log`, `result.txt`, `telegram.json`) |\n\n### MCP mode config\n\n| Var | Default | What it does |\n|-----|---------|---------------|\n| `PIBOX_MCP_MODE_PORT` | `8081` | Port the sidecar MCP server binds to (ignored when mounted inside API mode) |\n| `PIBOX_MCP_MODE_TOKEN` | empty | Bearer token for MCP. Empty = no auth — see [Security & safety](../SKILL.md#security--safety). No fallback to `PIBOX_API_MODE_TOKEN` |\n\n### Workspace & runtime\n\n| Var | Default | What it does |\n|-----|---------|---------------|\n| `PIBOX_WORKSPACE` | `/workspace` | Root workspace dir inside the container |\n| `PIBOX_CONTAINER_NAME` | `aicodebox` | Used to scope per-container state files in direct Docker runs. The host wrapper derives a per-workspace name. |\n| `PIBOX_AVAILABLE_MODELS` | — | **Required for API mode.** CSV list returned by `/openai/v1/models` and shown in the telegram `/model` picker. pibox registers every listed model with the upstream provider under `PIBOX_PROVIDER_API` |\n| `PIBOX_AVAILABLE_EFFORTS` | adapter list (`off,minimal,low,medium,high,xhigh`) | Override the effort/`--thinking` list shown by the telegram `/effort` picker (comma-separated) |\n\n### LLM upstream\n\n#### Generic custom HTTP provider\n\nUse these variables for Pi's documented custom HTTP APIs. They configure the upstream model Pi uses, not pibox's own OpenAI-compatible `/openai/v1` endpoint.\n\n| Var | Default | What it does |\n|-----|---------|--------------|\n| `PIBOX_PROVIDER_NAME` | `pibox` | Provider identifier. Lowercase letters, numbers, and `-` only. |\n| `PIBOX_PROVIDER_API` | `openai-completions` | `openai-completions`, `openai-responses`, `anthropic-messages`, or `google-generative-ai` |\n| `PIBOX_PROVIDER_BASE_URL` | none | Required upstream HTTP base URL |\n| `PIBOX_PROVIDER_API_KEY` | none | Required upstream API key or token |\n| `PIBOX_PROVIDER_MODEL` | none | Required default upstream model ID |\n\nLiteLLM example:\n\n```bash\ndocker run --rm --network host \\\n  -e PIBOX_PROVIDER_BASE_URL=http://127.0.0.1:4000/v1 \\\n  -e PIBOX_PROVIDER_API=openai-completions \\\n  -e PIBOX_PROVIDER_API_KEY=your-litellm-virtual-key \\\n  -e PIBOX_PROVIDER_MODEL=your-model-id \\\n  -v \"$PWD/workspace:/workspace\" \\\n  psyb0t/pibox:latest \\\n  -p \"list the files in /workspace\"\n```\n\nFor API mode, set `PIBOX_AVAILABLE_MODELS=your-model-id` too. Do not combine `PIBOX_PROVIDER_*` with `ANTHROPIC_BASE_URL`. pibox rejects the ambiguous configuration. The generic variables cover Pi's documented custom HTTP APIs, not every cloud-specific built-in provider.\n\n#### Anthropic compatibility\n\n| Var | Purpose |\n|-----|---------|\n| `ANTHROPIC_AUTH_TOKEN` | Bearer token (Z.AI, direct Anthropic, etc.) |\n| `ANTHROPIC_API_KEY` | Same thing — pi reads both |\n| `ANTHROPIC_BASE_URL` | Endpoint override (default `https://api.anthropic.com`) |\n| `ANTHROPIC_MODEL` | Default model when the caller doesn't specify one |\n\n## OpenAI endpoint headers\n\nNon-standard `x-aicodebox-*` request headers extend `POST /openai/v1/chat/completions` beyond stock OpenAI fields (legacy `x-claude-*` aliases also work for `workspace`/`continue`/`append-system-prompt`):\n\n| Header | Purpose |\n|---|---|\n| `x-aicodebox-workspace` | Pin the run to a workspace subpath instead of the ephemeral/default one |\n| `x-aicodebox-continue` | `1`/`true`/`yes` to continue the most recent session in that workspace instead of starting fresh |\n| `x-aicodebox-append-system-prompt` | Append text to the system prompt |\n| `x-aicodebox-json-schema` | JSON-encoded schema — fallback for clients that can't set the standard `response_format` body field (body field wins if both are set) |\n| `x-aicodebox-resume` | Resume a specific session id |\n| `x-aicodebox-extra-args` | Extra pi CLI args — JSON array or comma-separated string |\n| `x-aicodebox-timeout-seconds` | Per-request run timeout |\n| `x-aicodebox-tools-allowlist` | Restrict pi's own internal tools — JSON array or comma-separated string |\n| `x-aicodebox-no-tools` | `1`/`true`/`yes` to disable pi's internal tools; in OpenAI-tools mode this is the override to re-enable them (send `0`) |\n\n## Ports\n\n| Port | Default | Service |\n|---|---|---|\n| API/OAI/MCP-in-API | `8080` (`PIBOX_API_MODE_PORT`) | REST, `/openai/v1/*`, `/mcp` (when `PIBOX_MCP_MODE=1`) |\n| MCP sidecar | `8081` (`PIBOX_MCP_MODE_PORT`) | MCP only, used when API mode is not the foreground |\n\nNo ports are opened for Telegram, cron, interactive, or one-shot exec modes — they're outbound-only or container-boundary-trusted.\n\n## Management\n\n```bash\ndocker logs -f pibox    # tail logs\ndocker stop pibox       # stop\ndocker rm pibox          # remove\ndocker pull psyb0t/pibox:latest  # update\n```\n\nCheck what's running inside a live API-mode container:\n\n```bash\ncurl -s http://localhost:8080/status -H \"Authorization: Bearer your-secret\" | jq\n```\n\n## OpenClaw / ClawHub Config\n\n```bash\nexport PIBOX_URL=http://localhost:8080\nexport PIBOX_API_MODE_TOKEN=<token>  # only if the server requires it\n```\n\nOr via `~/.openclaw/openclaw.json`:\n\n```json\n{\n  \"skills\": {\n    \"entries\": {\n      \"pibox\": {\n        \"env\": {\n          \"PIBOX_URL\": \"http://localhost:8080\",\n          \"PIBOX_API_MODE_TOKEN\": \"<token>\"\n        }\n      }\n    }\n  }\n}\n```\n\nFile v0.18.2:skill-card.md\n\n## Description:\n\npibox helps agents and developers configure and use pi-coding-agent inside a Docker-based aicodebox container across shell, REST, OpenAI-compatible, MCP, Telegram, and cron interfaces.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[psyb0t](https://clawhub.ai/user/psyb0t)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers and engineers use this skill to choose, configure, and operate pibox modes for remote or containerized pi-coding-agent workflows, including REST, OpenAI-compatible, MCP, Telegram, cron, and one-shot command use.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: REST, OpenAI-compatible, and MCP surfaces can be unauthenticated when their token environment variables are empty.\n\nMitigation: Set strong non-empty API and MCP bearer tokens, bind services to localhost or an authenticated proxy, and do not expose unauthenticated instances to networks or untrusted agents.\n\nRisk: The documented install and deployment paths can run remote installer content or mutable container tags.\n\nMitigation: Avoid curl-to-bash installation for sensitive environments, review deployment scripts, and pin the Docker image to a reviewed digest.\n\nRisk: Run cancellation and workspace file deletion endpoints can remove state or files without undo.\n\nMitigation: Treat delete and cancellation capabilities as admin-only, require explicit user confirmation for the exact target, and mount only the workspace paths needed for the task.\n\nRisk: Token query parameters and broad network settings can expose credentials or powerful agent controls.\n\nMitigation: Prefer Authorization headers, avoid token query parameters, and avoid host networking unless it is strictly required.\n\n## Reference(s):\n\n- [pibox on ClawHub](https://clawhub.ai/psyb0t/skills/pibox)\n- [pibox setup](references/setup.md)\n- [docker-pibox](https://github.com/psyb0t/docker-pibox)\n- [pi-coding-agent](https://github.com/earendil-works/pi-mono/tree/main/packages/coding-agent)\n- [docker-aicodebox](https://github.com/psyb0t/docker-aicodebox)\n- [Model Context Protocol](https://modelcontextprotocol.io)\n\n## Skill Output:\n\n**Output Type(s):** [text, markdown, code, shell commands, configuration, guidance]\n\n**Output Format:** [Markdown with inline shell, JSON, and YAML examples]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Guidance may include mode selection, deployment commands, API requests, MCP setup, and security configuration.]\n\n## Skill Version(s):\n\n0.18.2 (source: server release evidence)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nArchive v0.18.1: 4 files, 13493 bytes\n\nFiles: references/setup.md (11245b), skill-card.md (2888b), SKILL.md (20144b), _meta.json (125b)\n\nFile v0.18.1:SKILL.md\n\n---\nname: pibox\ndescription: pi-coding-agent (earendil-works) running on the network inside an aicodebox container. Exposes seven programmatic surfaces on one image — interactive shell, one-shot exec (`-p \"...\"`), an HTTP REST API (run/async/cancel, workspace file ops), an OpenAI-compatible `/openai/v1/chat/completions` endpoint (streaming, client-executed tool calling, response_format/JSON-schema), an MCP server at `/mcp` (mounted in API mode or as a sidecar), a Telegram bot, and a cron scheduler that fires pi on a schedule. Foreground modes (API/Telegram/Cron) are mutually exclusive except Telegram+Cron; MCP coexists with any of them. Bearer-token auth per surface (`PIBOX_API_MODE_TOKEN`, `PIBOX_MCP_MODE_TOKEN`), empty = no auth. Use when the user wants to drive pi-coding-agent programmatically over HTTP/MCP/Telegram/cron instead of a local terminal session, or needs to reason about which pibox mode/endpoint fits a given integration.\nhomepage: https://github.com/psyb0t/docker-pibox\nuser-invocable: true\nmetadata:\n  { \"openclaw\": { \"emoji\": \"🥧\", \"primaryEnv\": \"PIBOX_URL\", \"requires\": { \"bins\": [\"docker\", \"curl\"] } } }\n---\n\n# pibox\n\n[pi-coding-agent](https://github.com/earendil-works/pi-mono/tree/main/packages/coding-agent) inside an [aicodebox](https://github.com/psyb0t/docker-aicodebox) container. One image, seven ways in: in\n\nArchive v0.18.0: 4 files, 13280 bytes\n\nFiles: references/setup.md (10735b), skill-card.md (2945b), SKILL.md (20144b), _meta.json (125b)\n\nArchive v0.17.0: 4 files, 13342 bytes\n\nFiles: references/setup.md (10735b), skill-card.md (3105b), SKILL.md (20144b), _meta.json (125b)\n\nArchive v0.16.2: 4 files, 13298 bytes\n\nFiles: references/setup.md (10735b), skill-card.md (2959b), SKILL.md (20144b), _meta.json (125b)\n\nArchive v0.16.1: 4 files, 13185 bytes\n\nFiles: references/setup.md (10645b), skill-card.md (2812b), SKILL.md (20144b), _meta.json (125b)\n\nArchive v0.16.0: 4 files, 13184 bytes\n\nFiles: references/setup.md (10645b), skill-card.md (2727b), SKILL.md (20144b), _meta.json (125b)","readmeExcerpt":"Skill: pibox Owner: psyb0t Summary: Install, configure, or run pi-coding-agent through the pibox wrapper, or connect to its HTTP, MCP, Telegram, or cron surfaces. Tags: latest:0.19.0 Version history: v0.19.0 | 2026-10-07T17:24:28.183Z | auto pibox 0.19.0 - Updated REST API MCP server route: now mounted at /mcp/ (with trailing slash); slashless /mcp still supported. - Documentation updates in SKILL.md to reflect API p","codeSnippets":[],"executableExamples":[{"language":"bash","snippet":"pibox                                      # interactive Pi\npibox -p \"inspect this workspace\"           # one-shot work\npibox -p \"review this change\" --thinking high\nPIBOX_FULL=1 pibox -p \"run the full suite\""},{"language":"bash","snippet":"PIBOX_DETACH=1 \\\nPIBOX_API_MODE=1 \\\nPIBOX_MCP_MODE=1 \\\nPIBOX_AVAILABLE_MODELS=your-model-id \\\nPIBOX_API_MODE_TOKEN=your-api-token \\\nPIBOX_MCP_MODE_TOKEN=your-mcp-token \\\npibox"},{"language":"bash","snippet":"pibox"},{"language":"bash","snippet":"pibox -p \"list the files in this workspace\""},{"language":"bash","snippet":"docker run -d --network host \\\n  -e PIBOX_API_MODE=1 \\\n  -e PIBOX_API_MODE_TOKEN=your-secret \\\n  -e PIBOX_AVAILABLE_MODELS=glm-4.6,glm-4.5-air \\\n  -e ANTHROPIC_AUTH_TOKEN=your-token \\\n  -e ANTHROPIC_BASE_URL=https://api.z.ai/api/anthropic \\\n  -e ANTHROPIC_MODEL=glm-4.6 \\\n  -v \"$PWD/workspace:/workspace\" \\\n  psyb0t/pibox:latest"},{"language":"bash","snippet":"curl -s http://localhost:8080/run \\\n  -H \"Authorization: Bearer your-secret\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"prompt\": \"say HELLO\", \"workspace\": \"/workspace\"}'"}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\nname: pibox\ndescription: \"Install, configure, or run pi-coding-agent through the pibox wrapper, or connect to its HTTP, MCP, Telegram, or cron surfaces.\"\nhomepage: https://github.com/psyb0t/docker-pibox\nuser-invocable: true\nmetadata:\n  { \"openclaw\": { \"emoji\": \"🥧\", \"primaryEnv\": \"PIBOX_URL\", \"requires\": { \"bins\": [\"docker\", \"curl\"] } } }\n---\n\n# pibox\n\n[pi-coding-agent](https://github.com/earendil-works/pi-mono/tree/main/packages/coding-agent) inside an [aicodebox](https://github.com/psyb0t/docker-aicodebox) container. One image, seven ways in: interactive shell, one-shot exec, HTTP REST API, OpenAI-compatible endpoint, MCP server, Telegram bot, cron scheduler.\n\nYou talk to pibox, pibox talks to pi, and Pi talks to the configured upstream LLM. Use `PIBOX_PROVIDER_*` for Pi's documented custom HTTP APIs, including LiteLLM and Anthropic-compatible endpoints. `ANTHROPIC_*` remains a compatibility shortcut for existing Anthropic Messages deployments.\n\nFor installation and configuration, see [references/setup.md](references/setup.md).\n\n## Agent execution\n\nUse `pibox` when it is on `PATH`. Run it from the workspace the user named.\nDo not assemble a new `docker run` command for routine interactive or one-shot\nwork. The wrapper owns the workspace mount, `~/.pi`, aicodebox state, SSH\nstate, image selection, and container lifecycle.\n\n```bash\npibox                                      # interactive Pi\npibox -p \"inspect this workspace\"           # one-shot work\npibox -p \"review this change\" --thinking high\nPIBOX_FULL=1 pibox -p \"run the full suite\"\n```\n\nConfigure the Pi upstream before the first run with `PIBOX_PROVIDER_*` or the\nsupported `ANTHROPIC_*` compatibility variables. Use an HTTP or MCP endpoint\nonly when the user asks for a service or provides an already-running remote\nURL. MCP plugins connect to a server. They do not replace the local wrapper.\n\nStart a local API and MCP server only when the user asks for one. Set the\nactual model identifiers and distinct bearer tokens:\n\n```bash\nPIBOX_DETACH=1 \\\nPIBOX_API_MODE=1 \\\nPIBOX_MCP_MODE=1 \\\nPIBOX_AVAILABLE_MODELS=your-model-id \\\nPIBOX_API_MODE_TOKEN=your-api-token \\\nPIBOX_MCP_MODE_TOKEN=your-mcp-token \\\npibox\n```\n\nIf `pibox`, `codexbox`, and `claudebox` were installed in the same command\ndirectory, a box can invoke a sibling command directly. The parent wrapper\npasses the real host paths and the sibling wrapper file. Do not set\n`AICODEBOX_HOST_*`, copy wrapper files, or manually mount another box's state\ndirectory. If the sibling command is absent, ask the user to install it or to\nchoose another approach.\n\n## Security & safety\n\n- **No auth when `PIBOX_API_MODE_TOKEN` is unset.** With it empty the REST/OpenAI-compatible API surface is UNAUTHENTICATED — anyone who can reach it gets full agent-execution and workspace file-read/write/delete access. NEVER expose such an instance on a network or to untrusted agents; set the token and bind to loopback / behind an authenticating proxy.\n- **No auth when `PIBOX"},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn79dhvmpjng4rp2jjk8k0v5xx80ccbk\",\n  \"slug\": \"pibox\",\n  \"version\": \"0.19.0\",\n  \"publishedAt\": 1791393868183\n}"},{"path":"references/setup.md","content":"# pibox setup\n\n## Requirements\n\n- Docker\n- An LLM endpoint supported by Pi's custom HTTP provider configuration. `PIBOX_PROVIDER_*` accepts an endpoint URL, protocol, API key or token, and model. It covers LiteLLM, Anthropic Messages endpoints, and Google Generative AI. `ANTHROPIC_*` remains available for existing Anthropic-compatible deployments. Pi drives the model; pibox drives Pi.\n- A target workspace. Run the wrapper from that directory so it mounts the path and preserves Pi state.\n\n## Quick Install\n\n### Host wrapper\n\nInstall the wrapper for interactive and one-shot use:\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/psyb0t/docker-pibox/main/install.sh | bash\n```\n\nInstall `pibox`, `codexbox`, and `claudebox` in the same command directory,\nnormally `/usr/local/bin`, when a box needs to launch another. Each wrapper\nmounts sibling wrapper files read-only. The sibling wrapper then asks the host\nDocker daemon to mount its own data directory.\n\n### Interactive / one-shot (no server)\n\n```bash\npibox\npibox -p \"inspect this workspace\"\nPIBOX_FULL=1 pibox -p \"run the full test suite\"\n```\n\nUse the wrapper for normal interactive and one-shot work. It handles the\nworkspace mount, Pi state, aicodebox state, SSH state, image selection, and\nnested launch context. Do not construct a `docker run` command unless the user\nexplicitly asks for a direct container deployment.\n\n### REST / OpenAI-compatible / MCP server\n\n```bash\ndocker run -d --name pibox --network host \\\n  -e PIBOX_API_MODE=1 \\\n  -e PIBOX_API_MODE_TOKEN=your-secret \\\n  -e PIBOX_AVAILABLE_MODELS=glm-4.6,glm-4.5-air \\\n  -e PIBOX_MCP_MODE=1 \\\n  -e PIBOX_MCP_MODE_TOKEN=your-mcp-secret \\\n  -e ANTHROPIC_AUTH_TOKEN=your-token \\\n  -e ANTHROPIC_BASE_URL=https://api.z.ai/api/anthropic \\\n  -e ANTHROPIC_MODEL=glm-4.6 \\\n  -v \"$PWD/workspace:/workspace\" \\\n  psyb0t/pibox:latest\n```\n\n`--network host` is convenient for local use; for anything else publish the port explicitly (`-p 8080:8080`) instead.\n\n**Verify:** `curl http://localhost:8080/healthz` returns `{\"ok\": true, \"adapter\": \"pi\"}`.\n\n### Telegram bot\n\n```bash\ndocker run -d --name pibox-tg \\\n  -e PIBOX_TELEGRAM_MODE=1 \\\n  -e PIBOX_TELEGRAM_MODE_TOKEN=your-bot-token \\\n  -e ANTHROPIC_AUTH_TOKEN=your-token \\\n  -e ANTHROPIC_BASE_URL=https://api.z.ai/api/anthropic \\\n  -e ANTHROPIC_MODEL=glm-4.6 \\\n  -v \"$PWD/workspace:/workspace\" \\\n  -v \"$PWD/telegram.yml:/home/aicode/.aicodebox/telegram.yml:ro\" \\\n  psyb0t/pibox:latest\n```\n\nRequires a `telegram.yml` with at least `allowed_chats` set (see [Telegram bot mode](../SKILL.md#telegram-bot-mode)) — the bot ignores messages from chats not on the allowlist.\n\n### Cron scheduler\n\n```bash\ndocker run -d --name pibox-cron \\\n  -e PIBOX_CRON_MODE=1 \\\n  -e PIBOX_CRON_MODE_FILE=/config/cron.yaml \\\n  -e ANTHROPIC_AUTH_TOKEN=your-token \\\n  -e ANTHROPIC_BASE_URL=https://api.z.ai/api/anthropic \\\n  -e ANTHROPIC_MODEL=glm-4.6 \\\n  -v \"$PWD/workspace:/workspace\" \\\n  -v \"$PWD/cron.yaml:/config/cron.yaml:ro\" \\\n  psyb0t/pibox:latest\n```\n\n###"},{"path":"skill-card.md","content":"## Description:\n\nInstall, configure, or run pi-coding-agent through the pibox wrapper, or connect to its HTTP, MCP, Telegram, or cron surfaces.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[psyb0t](https://clawhub.ai/user/psyb0t)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers use pibox to run pi-coding-agent against selected workspaces and connect it to scripts, HTTP clients, MCP tools, Telegram, or scheduled jobs.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: An exposed API or MCP service without its own bearer token can grant agent execution and workspace file access to anyone who can reach it.\n\nMitigation: Set distinct API and MCP tokens and bind ports to loopback; add stronger access controls before any shared or public exposure.\n\nRisk: Piping an installer into a shell, using an unpinned image, or deploying with host networking increases installation and exposure risks.\n\nMitigation: Inspect the installer first, pin the Docker image by digest, and prefer explicit loopback port bindings to host networking.\n\nRisk: Agent access to broad workspace mounts and destructive file or run operations can cause irrecoverable data loss.\n\nMitigation: Mount only necessary workspaces, back up important data, and require explicit confirmation of a specific target before deletion.\n\n## Reference(s):\n\n- [pibox setup guide](artifact/references/setup.md)\n- [pibox project homepage](https://github.com/psyb0t/docker-pibox)\n- [pi-coding-agent](https://github.com/earendil-works/pi-mono/tree/main/packages/coding-agent)\n- [pibox on ClawHub](https://clawhub.ai/psyb0t/skills/pibox)\n\n## Skill Output:\n\n**Output Type(s):** [Text, Code, Shell commands, Configuration instructions]\n\n**Output Format:** [Markdown with code and shell examples]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [May run an agent that reads and changes files in a selected workspace.]\n\n## Skill Version(s):\n\n0.19.0 (source: ClawHub release metadata)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment."}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":null,"editorialQuality":{"score":100,"threshold":65,"status":"thin","wordCount":1553,"uniquenessScore":43,"reasons":["uniqueness-below-45"]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-10T04:58:14.784Z","emptyReason":"No screenshots, media assets, or demo links are available."},"primaryImageUrl":null,"mediaAssetCount":0,"assets":[],"demoUrl":null},"ownerResources":{"evidence":{"source":"unclaimed","verified":false,"confidence":"low","updatedAt":"2026-10-10T04:58:14.784Z","emptyReason":"This page has not been claimed by the agent owner."},"hasCustomPage":false,"customPageUpdatedAt":null,"customLinks":[],"structuredLinks":{"docsUrl":null,"demoUrl":null,"supportUrl":null,"pricingUrl":null,"statusUrl":null},"customPage":null},"relatedAgents":{"evidence":{"source":"protocol-neighbors","verified":false,"confidence":"medium","updatedAt":"2026-10-10T10:43:20.218Z","emptyReason":null},"items":[{"id":"8ebccd8e-3863-4187-8355-c3f14e1f9edf","entityType":"agent","canonicalPath":"/agent/iofficeai-aionui","slug":"iofficeai-aionui","name":"AionUi","description":"Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!","url":"https://github.com/iOfficeAI/AionUi","homepage":"https://www.aionui.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-10-09T19:11:12.944Z","createdAt":"2026-02-25T03:38:16.584Z","downloads":null},{"id":"b917f68a-ebff-438e-84f8-3f4b2494c0bc","entityType":"agent","canonicalPath":"/agent/activepieces-activepieces","slug":"activepieces-activepieces","name":"activepieces","description":"AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents","url":"https://github.com/activepieces/activepieces","homepage":"https://www.activepieces.com","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-15T02:22:12.426Z","createdAt":"2026-02-25T03:38:12.412Z","downloads":null},{"id":"5cb26759-3a39-483f-94cf-276a98c13bb8","entityType":"agent","canonicalPath":"/agent/cherryhq-cherry-studio","slug":"cherryhq-cherry-studio","name":"cherry-studio","description":"AI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs","url":"https://github.com/CherryHQ/cherry-studio","homepage":"https://cherry-ai.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-11T14:38:40.986Z","createdAt":"2026-02-25T03:38:19.379Z","downloads":null},{"id":"6f6582d0-5d76-4f0f-b81d-86520247950b","entityType":"agent","canonicalPath":"/agent/copilotkit-copilotkit","slug":"copilotkit-copilotkit","name":"CopilotKit","description":"The Frontend for Agents & Generative UI. React + Angular","url":"https://github.com/CopilotKit/CopilotKit","homepage":"https://docs.copilotkit.ai","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-03-25T09:50:57.846Z","createdAt":"2026-02-25T03:39:14.617Z","downloads":null}],"links":{"hub":"/agent","source":"/agent/source/clawhub","protocols":[{"label":"OpenClaw","href":"/agent/protocol/openclew"}]}}}