@elizaos/plugin-sub-agent-claude-code
Compatibility package for the remote-mode Claude Code sub-agent plugin.
The implementation now lives in @elizaos/plugin-remote-manifest/sub-agent-claude-code; this package keeps the historical @elizaos/plugin-sub-agent-claude-code imports working.
What it does
The plugin wraps the claude CLI binary in an OS-sandboxed Bun subprocess and exposes session management over host-RPC so an Eliza agent can:
- Spawn a Claude Code session pointed at a workspace directory.
- Send prompts to the session over stdin.
- Read buffered stdout output on demand.
- Terminate the session when done.
Hardening covers SOC2 controls A-2, A-3, and O-8:
- Env filtering — only an explicit allowlist of env keys is forwarded to the child process; a blocklist regex drops any credential-shaped keys.
- CWD validation — the working directory is resolved via
realpathand must be under a workspace root or/tmp; symlink escapes are rejected. - Binary allowlisting — the
claudebinary is resolved against a static whitelist of directories (/usr/local/bin,/opt/homebrew/bin,~/.local/bin,~/.bun/bin, etc.). - OS sandboxing — macOS uses
sandbox-execwith a Seatbelt profile (packages/plugin-remote-manifest/sandbox/macos.sb); Linux usesbwrapviapackages/plugin-remote-manifest/sandbox/linux-bwrap.sh. When neither helper is available the plugin logs a WARN and falls back to allowlist-only. - Session transcripts — each session's I/O is redacted and written to
~/.eliza/sub-agent-sessions/<sessionId>/transcript.log; an audit event carrying the transcript hash is emitted on termination.
Installation
This package is private: true and intended for use as a workspace dependency within the elizaOS monorepo. It is a wrapper around the implementation in @elizaos/plugin-remote-manifest/sub-agent-claude-code and is loaded via the worker-runtime remote-plugin mechanism:
import { plugin } from "@elizaos/plugin-sub-agent-claude-code";
await runtime.installRemotePlugin(plugin, {
source: { kind: "workspace", pkgName: "@elizaos/plugin-sub-agent-claude-code" },
lifetime: "session",
});
Usage
After installation, obtain the service and call its RPC methods:
const svc = await runtime.getService("sub-agent.claude-code");
// Spawn a session
const { sessionId } = await svc.createSession({
cwd: "/absolute/path/to/project",
model: "claude-opus-4-5", // optional; defaults to claude CLI default
initialPrompt: "List files in src/",
// Note: ANTHROPIC_API_KEY cannot be passed via extraEnv (filterEnv throws for API_KEY/TOKEN keys).
// The worker reads it from process.env via Bun env permissions.
extraEnv: { ANTHROPIC_BASE_URL: "https://api.anthropic.com" }, // safe non-sensitive key example
});
// Send additional prompts
await svc.sendPrompt({ sessionId, prompt: "Explain the main entry point." });
// Read new output since the last call
const { lines } = await svc.getOutput({ sessionId, mode: "since-last" });
// Read all output buffered so far
const { lines: all } = await svc.getOutput({ sessionId, mode: "all" });
// Terminate
await svc.terminate({ sessionId });
Environment variables
| Variable | Default | Purpose |
|---|---|---|
ELIZA_WORKSPACE_DIR |
— | Workspace root; cwd passed to createSession must be under this (or ELIZA_STATE_DIR, or process cwd). |
ELIZA_STATE_DIR |
— | State dir; used as workspace root fallback. |
ELIZA_SUB_AGENT_SESSIONS_DIR |
~/.eliza/sub-agent-sessions |
Where session transcript directories are written. |
ELIZA_SUB_AGENT_SESSION_RETENTION_DAYS |
30 |
Age threshold for transcript pruning. |
ANTHROPIC_API_KEY and CLAUDE_CODE_OAUTH_TOKEN are available to the worker process via Bun env permissions declared in the plugin descriptor. They cannot be forwarded to the claude subprocess via extraEnv — filterEnv throws for keys matching SENSITIVE_ENV_RE (TOKEN and API_KEY both match). Only non-sensitive keys (e.g. ANTHROPIC_BASE_URL) may be passed via extraEnv.
Sandbox smoke tests
See packages/plugin-remote-manifest/sandbox/SMOKE.md for manual verification steps confirming the macOS and Linux sandbox profiles block reads outside the workspace root.
Development
bun run --cwd packages/plugin-sub-agent-claude-code build
bun run --cwd packages/plugin-sub-agent-claude-code typecheck
bun run --cwd packages/plugin-sub-agent-claude-code test
bun run --cwd packages/plugin-sub-agent-claude-code lint
Implementation changes belong in packages/plugin-remote-manifest/src/sub-agent-claude-code/; keep this package limited to compatibility re-exports unless the public compatibility surface itself changes.