{"_id":"@ellyseum/cordyceps","_rev":"6-3820dd867467ac7dd0df06379fa7b2c5","name":"@ellyseum/cordyceps","dist-tags":{"latest":"0.5.5"},"versions":{"0.5.0":{"name":"@ellyseum/cordyceps","version":"0.5.0","keywords":["claude","claude-code","codex","gemini","aider","agent","harness","pty","orchestration","json-rpc","websocket","ai","llm","cli"],"author":{"url":"https://github.com/ellyseum","name":"Jocelyn Ellyse","email":"jocelyn@ellyseum.dev"},"license":"MIT","_id":"@ellyseum/cordyceps@0.5.0","maintainers":[{"name":"ellyseum","email":"jocelyn@ellyseum.dev"}],"homepage":"https://github.com/ellyseum/cordyceps#readme","bugs":{"url":"https://github.com/ellyseum/cordyceps/issues"},"bin":{"cordy":"dist/cli/shell.js"},"dist":{"shasum":"f043c990c8df55185dc1429c89217c80d6d83747","tarball":"https://registry.npmjs.org/@ellyseum/cordyceps/-/cordyceps-0.5.0.tgz","fileCount":213,"integrity":"sha512-eM9RuRaQpXWUdRrA2Vp4cK8wQ59k6mYp34uuw1sNEPzTYpkvBRnigBiopFy6DC9hCJ4plD4/zOKjFf+pVD4tcA==","signatures":[{"sig":"MEUCIQD9VLgWKQgCLm+GPmCaO8fcrHrHsZoqQqk4smXu+MsiVwIgI+ZuU8e8m5sexUJhqCEd0+u5y2zgVCNVjpVC97hQlEU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":651035},"pnpm":{"onlyBuiltDependencies":["node-pty"]},"type":"module","engines":{"node":"^20 || ^22 || ^24"},"gitHead":"e921961da9f03e5f2625b83aa2b46a023ead911e","scripts":{"dev":"tsc --watch","test":"vitest run","build":"tsc && node -e \"try{require('fs').chmodSync('dist/cli/shell.js',0o755)}catch{}\"","clean":"node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\"","test:watch":"vitest"},"_npmUser":{"name":"ellyseum","email":"jocelyn@ellyseum.dev"},"repository":{"url":"git+https://github.com/ellyseum/cordyceps.git","type":"git"},"_npmVersion":"10.9.3","description":"Local-first agent harness — spawns and drives PTY-based CLI coding agents via a JSON-RPC 2.0 control plane, with a service bus and plugin architecture.","directories":{},"_nodeVersion":"22.18.0","dependencies":{"ws":"^8.20.0","node-pty":"^1.1.0"},"publishConfig":{"access":"public","provenance":true},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.0.0","@types/ws":"^8.18.1","typescript":"^5.7.0","@types/node":"^22.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cordyceps_0.5.0_1777392827952_0.8922505348462026","host":"s3://npm-registry-packages-npm-production"}},"0.5.1":{"name":"@ellyseum/cordyceps","version":"0.5.1","keywords":["claude","claude-code","codex","gemini","aider","agent","harness","pty","orchestration","json-rpc","websocket","ai","llm","cli"],"author":{"url":"https://github.com/ellyseum","name":"Jocelyn Ellyse","email":"jocelyn@ellyseum.dev"},"license":"MIT","_id":"@ellyseum/cordyceps@0.5.1","maintainers":[{"name":"ellyseum","email":"jocelyn@ellyseum.dev"}],"homepage":"https://github.com/ellyseum/cordyceps#readme","bugs":{"url":"https://github.com/ellyseum/cordyceps/issues"},"bin":{"cordy":"dist/cli/shell.js"},"dist":{"shasum":"215b24cca57ce68c5571b0a93aec136e25f348cf","tarball":"https://registry.npmjs.org/@ellyseum/cordyceps/-/cordyceps-0.5.1.tgz","fileCount":213,"integrity":"sha512-KPJneebN+eIW1s5UIyiVEJGiMKbufYOQ6VZo49Avwhgwtw5COIs4K2LuPMqJlgJT9nZXBrSbELbh9yETbA/2yw==","signatures":[{"sig":"MEUCIQDtKGIhloaDgCPy2ZFpzJj5oDykWRvg2qGfDBQ7hkRbxgIgNCZIxupxk+IdGFAM+eazOwI1JqqsONSRbkwPVhlccH4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":652438},"pnpm":{"onlyBuiltDependencies":["node-pty"]},"type":"module","engines":{"node":"^20 || ^22 || ^24"},"gitHead":"f64a8b56f7051e7b9fe6a5ad65a4eecba88d2b35","scripts":{"dev":"tsc --watch","test":"vitest run","build":"tsc && node -e \"try{require('fs').chmodSync('dist/cli/shell.js',0o755)}catch{}\"","clean":"node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\"","test:watch":"vitest"},"_npmUser":{"name":"ellyseum","email":"jocelyn@ellyseum.dev"},"repository":{"url":"git+https://github.com/ellyseum/cordyceps.git","type":"git"},"_npmVersion":"10.9.3","description":"Local-first agent harness — spawns and drives PTY-based CLI coding agents via a JSON-RPC 2.0 control plane, with a service bus and plugin architecture.","directories":{},"_nodeVersion":"22.18.0","dependencies":{"ws":"^8.20.0","node-pty":"^1.1.0"},"publishConfig":{"access":"public","provenance":true},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.0.0","@types/ws":"^8.18.1","typescript":"^5.7.0","@types/node":"^22.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cordyceps_0.5.1_1777440159508_0.5474531526299793","host":"s3://npm-registry-packages-npm-production"}},"0.5.2":{"name":"@ellyseum/cordyceps","version":"0.5.2","keywords":["claude","claude-code","codex","gemini","aider","agent","harness","pty","orchestration","json-rpc","websocket","ai","llm","cli"],"author":{"url":"https://github.com/ellyseum","name":"Jocelyn Ellyse","email":"jocelyn@ellyseum.dev"},"license":"MIT","_id":"@ellyseum/cordyceps@0.5.2","maintainers":[{"name":"ellyseum","email":"jocelyn@ellyseum.dev"}],"homepage":"https://github.com/ellyseum/cordyceps#readme","bugs":{"url":"https://github.com/ellyseum/cordyceps/issues"},"bin":{"cordy":"dist/cli/shell.js"},"dist":{"shasum":"8c408c35d50d85f81258ed39e8f1f1d8d56ad22f","tarball":"https://registry.npmjs.org/@ellyseum/cordyceps/-/cordyceps-0.5.2.tgz","fileCount":213,"integrity":"sha512-QuunMTGsdbiRgeqBCw75q4wTz/mCERvaseQS5BrI6EdKZZnTphP0bSfSRS9xLbIFZCSXYBk31MGos170pep+tg==","signatures":[{"sig":"MEUCIQDwoR0bmIK/s6UpyeRMBf/ZBTZYXXxdHlszrThT2o6oQwIgaJPCCbFY6EoT2kZZ4xzZeWALtvu4vkhyqH8roQc1T9U=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":654545},"pnpm":{"onlyBuiltDependencies":["node-pty"]},"type":"module","engines":{"node":"^20 || ^22 || ^24"},"gitHead":"5489854c9df1db461579b189883fa608ec1ffeed","scripts":{"dev":"tsc --watch","test":"vitest run","build":"tsc && node -e \"try{require('fs').chmodSync('dist/cli/shell.js',0o755)}catch{}\"","clean":"node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\"","test:watch":"vitest"},"_npmUser":{"name":"ellyseum","email":"jocelyn@ellyseum.dev"},"repository":{"url":"git+https://github.com/ellyseum/cordyceps.git","type":"git"},"_npmVersion":"10.9.3","description":"Local-first agent harness — spawns and drives PTY-based CLI coding agents via a JSON-RPC 2.0 control plane, with a service bus and plugin architecture.","directories":{},"_nodeVersion":"22.18.0","dependencies":{"ws":"^8.20.0","node-pty":"^1.1.0"},"publishConfig":{"access":"public","provenance":true},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.0.0","@types/ws":"^8.18.1","typescript":"^5.7.0","@types/node":"^22.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cordyceps_0.5.2_1777443743223_0.37116013643634393","host":"s3://npm-registry-packages-npm-production"}},"0.5.3":{"name":"@ellyseum/cordyceps","version":"0.5.3","keywords":["claude","claude-code","codex","gemini","aider","agent","harness","pty","orchestration","json-rpc","websocket","ai","llm","cli"],"author":{"url":"https://github.com/ellyseum","name":"Jocelyn Ellyse","email":"jocelyn@ellyseum.dev"},"license":"MIT","_id":"@ellyseum/cordyceps@0.5.3","maintainers":[{"name":"ellyseum","email":"jocelyn@ellyseum.dev"}],"homepage":"https://github.com/ellyseum/cordyceps#readme","bugs":{"url":"https://github.com/ellyseum/cordyceps/issues"},"bin":{"cordy":"dist/cli/shell.js"},"dist":{"shasum":"3c96c40f4e3de571d850ebd7f48977e5ba2fd9bd","tarball":"https://registry.npmjs.org/@ellyseum/cordyceps/-/cordyceps-0.5.3.tgz","fileCount":213,"integrity":"sha512-NKSavNGj3o+Zgkk4xt88vwzJrp+BdKLBv1hVALzSQ8xR2efQFy1uh+MQDPEh/tT4jhIMpTPjFSySghvuj5IldQ==","signatures":[{"sig":"MEYCIQC/sCh7nJnVDDBAimKdFr8k8u47Txcy5rKSvuNMVUe/VQIhAKdGF1Xq0fXPchGEYEPH8CyYbtcIeDIkJ4wQyfZeGVFs","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":654570},"type":"module","_from":"file:ellyseum-cordyceps-0.5.3.tgz","engines":{"node":"^20 || ^22 || ^24"},"scripts":{"dev":"tsc --watch","test":"vitest run","build":"tsc && node -e \"try{require('fs').chmodSync('dist/cli/shell.js',0o755)}catch{}\"","clean":"node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\"","test:watch":"vitest"},"_npmUser":{"name":"ellyseum","email":"jocelyn@ellyseum.dev"},"_resolved":"/tmp/026c8d1523f708d7789f3823c2800a1f/ellyseum-cordyceps-0.5.3.tgz","_integrity":"sha512-NKSavNGj3o+Zgkk4xt88vwzJrp+BdKLBv1hVALzSQ8xR2efQFy1uh+MQDPEh/tT4jhIMpTPjFSySghvuj5IldQ==","repository":{"url":"git+https://github.com/ellyseum/cordyceps.git","type":"git"},"_npmVersion":"10.9.3","description":"Local-first agent harness — spawns and drives PTY-based CLI coding agents via a JSON-RPC 2.0 control plane, with a service bus and plugin architecture.","directories":{},"_nodeVersion":"22.18.0","dependencies":{"ws":"^8.20.0","node-pty":"^1.1.0"},"publishConfig":{"access":"public","provenance":true},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.0.0","@types/ws":"^8.18.1","typescript":"^5.7.0","@types/node":"^22.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cordyceps_0.5.3_1777460913723_0.25419247890523256","host":"s3://npm-registry-packages-npm-production"}},"0.5.4":{"name":"@ellyseum/cordyceps","version":"0.5.4","keywords":["claude","claude-code","codex","gemini","aider","agent","harness","pty","orchestration","json-rpc","websocket","ai","llm","cli"],"author":{"url":"https://github.com/ellyseum","name":"Jocelyn Ellyse","email":"jocelyn@ellyseum.dev"},"license":"MIT","_id":"@ellyseum/cordyceps@0.5.4","maintainers":[{"name":"ellyseum","email":"jocelyn@ellyseum.dev"}],"homepage":"https://github.com/ellyseum/cordyceps#readme","bugs":{"url":"https://github.com/ellyseum/cordyceps/issues"},"bin":{"cordy":"dist/cli/shell.js"},"dist":{"shasum":"c0a00b261e6068981c5f6c7f8c12172e0acfc610","tarball":"https://registry.npmjs.org/@ellyseum/cordyceps/-/cordyceps-0.5.4.tgz","fileCount":213,"integrity":"sha512-2dc+prExxcmURY+SnGbTOW78dZsFfSDSRUC8lrRjpL1WCckUM8i1ZDIGNMk8QIrt68OplBLAkvb5PUH1Mv+LTA==","signatures":[{"sig":"MEQCIADN6JQxrSYupPXOkVlIGhlouVA9Gz9XJBxFVAgytaDcAiAUgYlqa/F2dv/KO+HrQc7Rr2HD+SBcsXEbJwqyRQRXrQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ellyseum%2fcordyceps@0.5.4","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":654642},"pnpm":{"onlyBuiltDependencies":["node-pty"]},"type":"module","engines":{"node":"^20 || ^22 || ^24"},"gitHead":"e56e8eb200fd700f57a53064bd270fe4282d21c0","scripts":{"dev":"tsc --watch","test":"vitest run","build":"tsc && node -e \"try{require('fs').chmodSync('dist/cli/shell.js',0o755)}catch{}\"","clean":"node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\"","test:watch":"vitest"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:5d4edce6-ea64-4190-b33a-a1b51f6c961b"}},"repository":{"url":"git+https://github.com/ellyseum/cordyceps.git","type":"git"},"_npmVersion":"11.13.0","description":"Local-first agent harness — spawns and drives PTY-based CLI coding agents via a JSON-RPC 2.0 control plane, with a service bus and plugin architecture.","directories":{},"_nodeVersion":"22.22.2","dependencies":{"ws":"^8.20.0","node-pty":"^1.1.0"},"publishConfig":{"access":"public","provenance":true},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.0.0","@types/ws":"^8.18.1","typescript":"^5.7.0","@types/node":"^22.0.0"},"_npmOperationalInternal":{"tmp":"tmp/cordyceps_0.5.4_1777461678056_0.11222465041311458","host":"s3://npm-registry-packages-npm-production"}},"0.5.5":{"name":"@ellyseum/cordyceps","version":"0.5.5","description":"Local-first agent harness — spawns and drives PTY-based CLI coding agents via a JSON-RPC 2.0 control plane, with a service bus and plugin architecture.","type":"module","bin":{"cordy":"dist/cli/shell.js"},"engines":{"node":"^20 || ^22 || ^24"},"pnpm":{"onlyBuiltDependencies":["node-pty"]},"scripts":{"build":"tsc && node -e \"try{require('fs').chmodSync('dist/cli/shell.js',0o755)}catch{}\"","dev":"tsc --watch","test":"vitest run","test:watch":"vitest","clean":"node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\""},"keywords":["claude","claude-code","codex","gemini","aider","agent","harness","pty","orchestration","json-rpc","websocket","ai","llm","cli"],"author":{"name":"Jocelyn Ellyse","email":"jocelyn@ellyseum.dev","url":"https://github.com/ellyseum"},"license":"MIT","homepage":"https://github.com/ellyseum/cordyceps#readme","repository":{"type":"git","url":"git+https://github.com/ellyseum/cordyceps.git"},"bugs":{"url":"https://github.com/ellyseum/cordyceps/issues"},"publishConfig":{"access":"public","provenance":true},"dependencies":{"node-pty":"^1.1.0","ws":"^8.20.0"},"devDependencies":{"@types/node":"^22.0.0","@types/ws":"^8.18.1","typescript":"^5.7.0","vitest":"^4.0.0"},"gitHead":"34db62a9e38c20247c524b05af3da47a7988443c","_id":"@ellyseum/cordyceps@0.5.5","_nodeVersion":"22.22.2","_npmVersion":"11.13.0","dist":{"integrity":"sha512-mS00ebv6jJ6ZaQu8hA5/tUYcbbeUakaG8zc4JRLxYiOmY4511zshXsfgAupd/4b1C8BqVU5wmgV+cRx0LXn4mg==","shasum":"6852ec09f7ce4b5b7c0f965e7a7c559497dabee5","tarball":"https://registry.npmjs.org/@ellyseum/cordyceps/-/cordyceps-0.5.5.tgz","fileCount":213,"unpackedSize":658143,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ellyseum%2fcordyceps@0.5.5","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCQKyjuXmN2lw5J9oz78eNvXzSn0soH8cNSVc6i135UBAIhAIqHONFcPySaEkNiBNPSpWqBuOezOb9s45S05yGw5X0O"}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:5d4edce6-ea64-4190-b33a-a1b51f6c961b"}},"directories":{},"maintainers":[{"name":"ellyseum","email":"jocelyn@ellyseum.dev"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/cordyceps_0.5.5_1777463094020_0.20107109741726603"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-28T16:13:47.874Z","modified":"2026-04-29T11:44:54.440Z","0.5.0":"2026-04-28T16:13:48.115Z","0.5.1":"2026-04-29T05:22:39.729Z","0.5.2":"2026-04-29T06:22:23.419Z","0.5.3":"2026-04-29T11:08:33.905Z","0.5.4":"2026-04-29T11:21:18.259Z","0.5.5":"2026-04-29T11:44:54.192Z"},"bugs":{"url":"https://github.com/ellyseum/cordyceps/issues"},"author":{"name":"Jocelyn Ellyse","email":"jocelyn@ellyseum.dev","url":"https://github.com/ellyseum"},"license":"MIT","homepage":"https://github.com/ellyseum/cordyceps#readme","keywords":["claude","claude-code","codex","gemini","aider","agent","harness","pty","orchestration","json-rpc","websocket","ai","llm","cli"],"repository":{"type":"git","url":"git+https://github.com/ellyseum/cordyceps.git"},"description":"Local-first agent harness — spawns and drives PTY-based CLI coding agents via a JSON-RPC 2.0 control plane, with a service bus and plugin architecture.","maintainers":[{"name":"ellyseum","email":"jocelyn@ellyseum.dev"}],"readme":"# Cordyceps\n\n[![npm version](https://img.shields.io/npm/v/@ellyseum/cordyceps.svg?style=flat-square)](https://www.npmjs.com/package/@ellyseum/cordyceps)\n[![CI](https://img.shields.io/github/actions/workflow/status/ellyseum/cordyceps/ci.yml?branch=main&style=flat-square&label=ci)](https://github.com/ellyseum/cordyceps/actions/workflows/ci.yml)\n[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square)](LICENSE)\n[![Node ^20 || ^22 || ^24](https://img.shields.io/badge/node-%5E20%20%7C%7C%20%5E22%20%7C%7C%20%5E24-brightgreen.svg?style=flat-square)](package.json)\n\n**Local-first agent harness.** A daemon that spawns and drives PTY-based CLI coding agents — Claude Code, Codex, Gemini, Ollama — through a single JSON-RPC 2.0 control plane. Every primitive a human invokes from the shell (spawn, submit, interrupt, approve, kill) is reachable over the same API a manager LLM uses to drive a fleet of peers.\n\n## Why this exists\n\nMost agent frameworks assume one model, one task, one process. Real agentic\nwork is a fleet — a manager LLM driving peers, with humans escalated only\nwhen needed. The design insight that unlocked it: a manager LLM should be a\npeer client on the same control plane as a human operator, not a privileged\nspecial case. Once `spawn` / `submit` / `interrupt` / `approve` are reachable\nover a stable API, the manager gets everything the operator has — and a code\nreview council, an MCP bridge, an autonomous repo grinder, and a deterministic\ntest runner all fall out of the same plumbing.\n\nCordyceps is that plumbing. The PTY work is a backend detail; the control\nplane is the product.\n\n## Quick start\n\n```bash\n# Install\nnpm install -g @ellyseum/cordyceps\n\n# Start the daemon (loopback-only, bearer-auth WebSocket)\ncordy daemon start\n\n# Spawn a Claude agent (uses your normal Claude auth — OAuth, memory, hooks)\ncordy spawn claude --name smoke\n\n# Send a prompt; print the response\ncordy send smoke \"respond with just: banana\"\n\n# Inspect; clean up\ncordy state smoke\ncordy kill smoke\ncordy daemon stop\n```\n\nFor one-shots without a persistent daemon: `cordy --ephemeral spawn claude --name once`.\n\n### Prerequisites\n\n- Node `^20 || ^22 || ^24`.\n- `node-pty` is a native module. The npm registry ships prebuilt binaries\n  for common Node ABIs; on a system without a matching prebuild, install\n  needs Python 3 and a C++ toolchain (`build-essential` on Debian/Ubuntu,\n  Xcode CLT on macOS).\n- The CLI agents you want to drive (`claude`, `codex`, `gemini`, `ollama`)\n  must already be installed on `PATH`. Cordyceps is a harness — it doesn't\n  ship its own model access.\n\n### Install from source\n\n```bash\ngit clone https://github.com/ellyseum/cordyceps\ncd cordyceps\npnpm install\npnpm build\n./bin/cordy daemon start\n```\n\n## The manager-agent pattern\n\nThe agentic bit: a \"manager\" agent is just another client connected to the\ndaemon's JSON-RPC API. Given a prompt, it spawns peer agents, drives them\nthrough work, responds to approvals, and tears them down. Gatekeeper,\nreviewer, orchestrator, human-in-the-loop escalator — these all fall out of\none LLM holding the steering wheel of a fleet.\n\nEvery primitive is reachable over the same API surface a human uses from the\nshell, so a manager LLM operating cordy has the same capability as an\noperator driving it manually. The agent becomes a peer, not a special case.\n\n```bash\ncordy manager \"summarize the git log since last week\"\n```\n\nThis spawns a Claude session wired with cordy's MCP bridge and a manager\nsystem prompt. The manager can spawn other agents (Codex for exec tasks,\nGemini for search-heavy work, Ollama for cheap reasoning), coordinate their\noutput, and report back. Press Ctrl+C to interrupt.\n\n## Code review council\n\n```bash\ncordy council review src/core/bus.ts\ncordy council review src/core/bus.ts --panel claude,codex,gemini --chair codex --json\ncordy council review src/core/bus.ts --no-chair --json   # synthesize yourself\ncordy council diff                              # uncommitted changes vs HEAD\ncordy council diff --staged                     # only staged changes\ncordy council diff main..feature --scope src/   # branch comparison, scoped\n```\n\nN reviewers from different driver families run in parallel, each in a silo\n(no reviewer sees another's output), then a chair agent synthesizes their\nfindings into a prioritized markdown verdict. The whole point is\nheterogeneous training lineages — intra-family ensembles correlate their\nblind spots; inter-family councils don't.\n\n`--no-chair` (0.5.2+) skips the chair-spawn step and returns\nper-reviewer findings only. Useful when an LLM caller (e.g. a Claude\nCode session driving cordy) wants to synthesize the panel's output\nitself using full conversation context, instead of paying for a\nseparate chair model.\n\n`review` operates on a whole file; `diff` reviews the changes shown by `git\ndiff` (with `--no-ext-diff --no-textconv --end-of-options` for hostile-repo\nsafety). Tool-capable drivers (Claude PTY, Codex exec, Gemini exec) get a\npath-only prompt and read the file themselves; tool-less drivers fall back\nto inline mode with auto-chunking at ~30KB.\n\n## Use from Claude Code\n\nThe recommended way to drive cordy from a Claude Code session is the\n[`claude-cordyceps`](https://github.com/ellyseum/claude-cordyceps)\nplugin. It teaches Claude how to map natural-language asks\n(\"consult peers on src/foo.ts\", \"spawn council\", \"brainstorm with\nmultiple LLMs\", \"ask Codex about this design\") to the right `cordy`\ninvocation, and ships a SessionStart hook that detects which drivers\nare reachable on the current machine.\n\nAfter installing cordy globally as above:\n\n```text\n/plugin marketplace add ellyseum/claude-cordyceps\n/plugin install claude-cordyceps\n```\n\nThen trigger via natural language or the `/cordy <ask>` slash command.\nSee the plugin's README for the full setup and trigger phrase list.\n\n## MCP bridge — expose cordy to another agent\n\n> **Experimental.** The bridge currently speaks line-delimited JSON-RPC,\n> which is what Claude Code's MCP loader accepts. Stricter MCP clients may\n> reject the framing; full MCP stdio framing is tracked for a future release.\n\nFor lower-level integration (no plugin), add `cordy mcp-stdio` to a\nClaude Code MCP config — the agent gains delegated authority to spawn\npeers and drive them via tool calls (`cordy_agents_spawn`,\n`cordy_agents_submit`, `cordy_drivers_list`, …):\n\n```jsonc\n{\n  \"mcpServers\": {\n    \"cordy\": { \"command\": \"cordy\", \"args\": [\"mcp-stdio\"] }\n  }\n}\n```\n\nThis is the substrate the `claude-cordyceps` plugin builds on, and is\nthe path to take if you want raw tool calls instead of the plugin's\nopinionated skill body.\n\n## Drivers\n\n| Driver | Family | Modes | Notes |\n|--------|--------|-------|-------|\n| `claude-code` | Anthropic | `pty`, `exec` | Interactive TUI (`pty`) or one-shot via `claude --print` (`exec`). PTY supports approve / reject / mode-switch; exec is cleaner for one-shot prompts and council reviewers. |\n| `codex` | OpenAI | `exec` | `codex exec --json --skip-git-repo-check` |\n| `gemini` | Google | `exec` | `gemini -p … --output-format stream-json`; needs `GEMINI_API_KEY` in the daemon env |\n| `ollama` | local | `server-http` | Streams NDJSON from `/api/generate`; needs a local Ollama daemon (`ollama serve`). Free for local models. |\n\nDrivers declare their modes; the `AgentManager` runtime registry maps each\nmode to a controller plugin without core changes. Adding a new CLI family\nis a driver (plus a runtime plugin if it speaks an unsupported protocol);\nnothing in the bus, transport, or existing drivers needs to change.\n\nSee [`docs/DRIVERS.md`](docs/DRIVERS.md) for the parser/control protocol and\nhow to add one.\n\n## Architecture\n\n```\n┌──────────────────────────────────────────────────────────────┐\n│                      Daemon Process                          │\n│  ┌────────────┐    ┌──────────────┐    ┌──────────────┐      │\n│  │  Transport │◄──►│ Service Bus  │◄──►│   Plugins    │      │\n│  │  WS /rpc   │    │ (events+kv)  │    │ (audit, …)   │      │\n│  └─────┬──────┘    └──────┬───────┘    └──────────────┘      │\n│        │                  │                   ▲              │\n│        │                  ▼                   │              │\n│        │         ┌────────────────┐           │              │\n│        │         │ Agent Manager  ├───────────┘              │\n│        │         │ + RuntimeReg   │                          │\n│        │         └────────┬───────┘                          │\n│        │                  │                                  │\n│        ▼      ┌───────────┼───────────┐                      │\n│  WS clients   ▼           ▼           ▼                      │\n│       ┌───────────┐┌────────────┐┌────────────┐              │\n│       │  Pty      ││   Exec     ││ ServerHttp │              │\n│       │Controller ││ Controller ││ Controller │              │\n│       └─────┬─────┘└─────┬──────┘└─────┬──────┘              │\n│             ▼            ▼             ▼                     │\n│       ┌─────────┐  ┌─────────┐   ┌─────────┐                 │\n│       │  PTY    │  │  exec   │   │  HTTP   │                 │\n│       │(agent)  │  │(agent)  │   │(server) │                 │\n│       └─────────┘  └─────────┘   └─────────┘                 │\n└──────────────────────────────────────────────────────────────┘\n\n  HTTP /health        — liveness probe (no auth)\n  WS   /rpc           — JSON-RPC 2.0 (Authorization: Bearer <token>)\n```\n\nTwo keystone patterns:\n\n- **Service Bus** (`src/core/bus.ts`) — pub/sub events + flat key-value\n  state. `on()` returns an unsubscribe handle so plugins clean up cleanly.\n  Plugins coordinate through agreed bus-key prefixes; nothing imports\n  across plugins.\n- **Plugin architecture** (`src/plugins/api.ts`) — every extension is a\n  `CordycepsPlugin` declaring `methods`, lifecycle hooks, and bus\n  subscriptions. Loaded in priority groups with topological sort. The\n  `audit` plugin is the reference implementation.\n\nFor Mermaid diagrams of the spawn / send / response flow and the\nmanager-agent sequence, see [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md).\nJSON-RPC method reference: [`docs/PROTOCOL.md`](docs/PROTOCOL.md).\n\n## Notable design decisions\n\n**Manager as peer, not special case.** The same JSON-RPC surface that powers\nthe `cordy` CLI also powers manager LLMs talking through `cordy mcp-stdio`.\nA manager has zero capabilities beyond what an operator has — which means\nevery shell workflow tested manually maps directly to an agent's behavior.\n\n**Glyph-based state machine over regex scraping.** PTY output is messy:\nescape sequences, partial writes, spinner frames over the same cursor\nposition. The Claude parser walks Unicode glyphs (`●` message, `⎿` result,\n`⏵`/`⏸` mode) as state-machine transitions and ships a fixture-replay\nharness as a regression net. Regex would have to handle every render-time\nrace; a state machine fed by the actual TTY stream doesn't.\n\n**Bus-coordinated plugins.** Plugins talk through `bus.on()` / `bus.emit()`\nrather than importing each other's types. That keeps the plugin set\nloosely coupled, lets the loader topo-sort by declared `order`, and makes\nhot-load / unload practical without a registry refactor.\n\n## What it isn't\n\n- Not a human-facing TUI or web UI — pure agentic infrastructure.\n- Not a provider SDK client (drives installed CLIs; no direct\n  Anthropic / OpenAI / Google API calls). The trade-off is that you bring\n  your own auth and pay for whatever the underlying CLI bills you for.\n- Not a multi-machine orchestrator — the daemon is loopback-only by design.\n\n## Persistence and security\n\n- `~/.cordyceps/` (mode `0700`) — daemon state, instance files, optional\n  audit logs (opt-in via `--audit`).\n- `~/.cordyceps/instances/{pid}.json` (mode `0600`, atomic writes) — the\n  client uses these to discover the running daemon and read its bearer\n  token. The token is regenerated on every daemon start.\n- `~/.cordyceps/env` (mode `0600`) — optional env file auto-loaded at\n  daemon start. Shell env wins over file values. Useful for driver API\n  keys like `GEMINI_API_KEY`. Override the path via `CORDY_ENV_FILE`;\n  per-repo override is `<repo>/.cordyceps/env`.\n- Loopback-only transport (`127.0.0.1`); upgrade rejects non-loopback\n  Host / Origin headers as defense in depth.\n- 192-bit bearer token (`base64url` of 24 random bytes), regenerated per\n  daemon start, presented via `Authorization: Bearer <token>` on the\n  upgrade request.\n- The bearer token is shell-execution-equivalent — anyone who reads it can\n  spawn arbitrary subprocess via cordy's spawn API. Treat it like an SSH\n  key.\n\n## Tests\n\n```bash\npnpm test          # vitest, full suite green\npnpm build         # tsc clean\n```\n\nThe repo uses pnpm; `npm test` and `npm run build` work too if you don't\nhave pnpm installed.\n\nWhen a CLI release shifts glyph spacing, mode-line shape, or spinner\nframes, the fixture-replay harness in `test/fixtures/` catches the drift\non the next test run and the fix lives in the relevant driver's directory.\n\n## Status\n\nPre-1.0. Ships a working daemon, four built-in drivers, the council and\nmanager plugins, an MCP stdio bridge (experimental framing), and the\nplugin / runtime registries. See [`STATUS.md`](STATUS.md) for what's in\nprogress and what's sketched.\n\n## Contributing\n\nIssues and PRs welcome. Read [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md)\nfirst if you're touching anything beyond a typo; touching a driver,\n[`docs/DRIVERS.md`](docs/DRIVERS.md); touching a plugin,\n[`docs/PLUGINS.md`](docs/PLUGINS.md).\n\n## License\n\nMIT — see [`LICENSE`](LICENSE).\n\nBuilt by [Jocelyn Ellyse](https://github.com/ellyseum).\n","readmeFilename":"README.md"}