perseus
Provides live context and workspace state to Hermes Agent (by NousResearch), enabling it to start sessions with pre-resolved, verified facts about the workspace.
Perseusβ’ πͺ β MCP Server + Live Context Engine
Perseus is an MCP server and live context engine for AI assistants. It solves the cold-start problem β every new session, the assistant already knows what's running, what you were working on, and what tools exist. No orientation phase. No pre-flight tax. Exposes 24 MCP tools over stdio/SSE for workspace state resolution. Works with any MCP-compatible assistant: Claude Desktop, Claude Code, Cursor, Codex, Hermes Agent (by NousResearch), Rovo Dev.

[![CI]
TL;DR
Perseus is a live context engine and MCP server for AI assistants, eliminating cold starts. It resolves dynamic data (running services, code changes, session state) before the assistant sees it, providing verified facts instead of stale files or instructions to find information. Exposes 24 MCP tools for workspace state over stdio/SSE.
pip install perseus-ctx
perseus init /workspace/myproject
perseus render .perseus/context.md --output CLAUDE.mdWorks with any MCP-compatible assistant: Claude Desktop, Claude Code, Cursor, Codex, Hermes Agent, and Rovo Dev.
MCP Server β 24 Tools for Workspace State
Perseus implements the Model Context Protocol (MCP), exposing 24 tools over stdio or SSE transport. Every tool resolves live workspace state at invocation time β no stale cache, no pre-computed snapshots.
Quick Start (MCP)
pip install perseus-ctx
perseus mcp serve # stdio (default β Claude Desktop, Claude Code, Cursor)
perseus mcp serve --transport sse --port 8420 # SSE (remote agents, multi-machine)Tools
Tool | Description |
| Health-check running services |
| Run a shell command and return stdout |
| Read file contents |
| List directory or structured data |
| Tree view of directory |
| Read environment variables |
| Current date/time |
| Latest checkpoint summary |
| Recent session digests |
| Context maintenance report |
| Oracle drift report |
| MnΔmΔ narrative memory |
| Recall persistent memories via bastra-recall |
| List available skills |
| Include and render another file |
| Execute local agent subprocess |
| Task board from tasks/*.md |
| Agent message inbox |
| System prompt block |
| Validate rendered block against schema |
| Run allowlisted external tool |
| Fetch context from remote Perseus instance |
| Full rendered workspace context |
| Daedalus context-maintenance heuristics |
Client Integration
Claude Desktop (claude_desktop_config.json):
{
"mcpServers": {
"perseus": {
"command": "perseus",
"args": ["mcp", "serve"],
"env": { "PERSEUS_WORKSPACE": "/path/to/workspace" }
}
}
}Claude Code / Cursor (.mcp.json):
{
"mcpServers": {
"perseus": {
"command": "perseus",
"args": ["mcp", "serve"]
}
}
}Docker
docker build -t perseus .
docker run --rm -v /path/to/workspace:/workspace perseus mcp serveSee Container Runtime for full Docker and compose deployment.
MCP Registry
Published as io.github.tcconnally/perseus on the official MCP Registry. Includes server.json for zero-config discovery.
The Problem
Every AI assistant session starts cold. Before useful work begins, the assistant burns turns on orientation β checking which services are running, reading stale config files, rediscovering where you left off. Static markdown files (.cursorrules, CLAUDE.md) rot immediately. The port you wrote down has changed. The container that was "always running" hasn't been started since Tuesday.
Stale context isn't neutral. It's drag.
The Fix: Resolve Before Context
Perseus is a pre-processor. You write directives in a source document β @query, @services, @waypoint β and Perseus resolves them at render time, then outputs plain markdown. The assistant reads verified facts, not instructions to go find facts.
Without Perseus With Perseus
ββββββββββββββββββββββββββββββββ ββββββββββββββββββββββββββββββββββ
"Port is 3001 (check .env)" β Port: 3001
"47 tests (may be stale)" β Tests: all passing (run 8s ago)
"Check docker ps first" β mongo-dev: Up 4h 12m
"Where did we leave off?" β Checkpoint: webhook handler written,
pending test runPerseus replaces your assistant's context file β CLAUDE.md, .cursorrules, AGENTS.md, .hermes.md β with rendered live context. If you already have a hand-written context file, migrate its static content into .perseus/context.md first. Perseus overwrites the output file on every render. Add @perseus to line 1 of your source and it becomes live. The assistant never sees directive syntax. It sees a document that was already true.
Quick Start (30 Seconds to Live Context)
perseus init /workspace/myproject # scaffold a source document
perseus render .perseus/context.md --output CLAUDE.md # render to whatever your assistant readsThat's it. The output file name is the only assistant-specific detail:
Assistant | Output file |
Claude Code |
|
Hermes Agent |
|
Cursor |
|
Codex |
|
Rovo Dev |
|
Any other | Whatever your assistant reads at session start |
Keep it fresh with cron, launchd, systemd, or perseus watch β see the Integration Guide for Hermes auto-refresh setups. For other assistants (Codex, Cursor, Claude Code, Rovo Dev), follow the adapter patterns in spec/integration.md.
Why Perseus? (Proof, Hardening, and Enterprise Value)
Perseus delivers verified, up-to-date context, eliminating the need for AI assistants to spend turns orienting themselves. Here's how it stands up:
Performance & Efficiency
1,190Γ coldβwarm gap β Real-world scenario using the Perseus repo itself as the benchmark target. At the 1,408 directive scale, the cold render took 578.7s, while the warm render took 0.486s. Raw data β
93% token reduction, 0ms overhead β live 200-request A/B harness: 488 β 27 avg prompt tokens per request. P99 latency overhead: 0ms β Perseus adds nothing to response time. Full harness results β
Enterprise Ready - Cost analysis shows that for a 500-developer team, Perseus can save between $14,844 and $40,625 per year in API costs, with a 3.1B token reduction. Cost analysis β
Extreme Enterprise Benchmark β 10-phase suite (reps=10, 50 devs, 250 concurrent agents): 10/10 hard gates Β· 6/6 soft gates Β· 0 errors at 250 concurrent Β· 90% enterprise ROI Β· fleet P99 1,169ms. The benchmark is designed to surface regressions, not hide them. Full methodology β Β· Raw results β
Reliability & Security
Perseus is tested against edge cases that challenge the "resolve before context" claim:
14/14 hard gates passed β The ultimate benchmark suite, including swarm chaos, cache thrash, and adversarial tests, passed all gates. Full results β
Semantic Equivalence: 1.0 β A live Gemini 2.5 Flash judge found 20/20 A/B test pairs to be semantically equivalent, confirming that Perseus changes what the assistant knows, not what it says. (Also 20/20 A/B pairs in a second independent run.)
Workspace boundaries β Symlink escapes (direct, relative, chained, to
/etc) are all blocked. The trust-gate resolves symlinks to their real target before checking boundaries.Context overflow protection β
@readand@includewarn and truncate when files exceedmax_read_bytes/max_include_bytes(512 KB default,Nonefor unlimited).Transitive resolution β
@includeon.mdfiles recursively renders directives up tomax_include_depth(default 5), with cycle detection.Integrity drift β Optional
integrity_checkcaptures file mtimes before render and warns if any file changed mid-resolution.Plugin sandboxing β Plugin directives with
executes_shell=Trueare gated behindallow_query_shell, same as built-ins. Plugin errors are caught and surfaced as inline warnings β a broken plugin never breaks a render.
Edge-case tests cover circular dependencies, race conditions, symlink escapes, and context overflow. These four config knobs live under render: in ~/.perseus/config.yaml.
Perseus reads from a live filesystem β there is no snapshot isolation unless you enable integrity_check. Files can change between directive resolutions. The render output reflects whatever was on disk at the moment each directive resolved, not a single atomic point-in-time. This is the right tradeoff for a zero-dependency pre-processor (zero overhead by default, check when it matters), but it is not a database transaction.
The O_CREAT | O_EXCL checkpoint locking is atomic on local POSIX filesystems. Network filesystems (NFS < v4, SMB, cloud mounts) may not honor these semantics β if you run a multi-agent relay across machines, use a local disk or a filesystem with verified atomic-create support.
perseus.py is a compiled build artifact produced by scripts/build.py from the modular src/perseus/ tree. It is not hand-maintained as a single file. The source modules are the canonical form.
How Perseus Works
You write this:
@perseus v0.4
# Context β @date format="YYYY-MM-DD HH:mm z"
## What's Running
@query "docker ps --format 'table {{.Names}} {{.Status}}'"
## Last Session
@waypoint ttl=86400
## Ports
@read .env key="API_PORT" fallback="3001"Perseus renders this:
# Context β 2026-05-18 08:33 CDT
## What's Running
mongo-dev Up 4 hours
redis-dev Up 4 hours
## Last Session
Checkpoint written: 2026-05-18T08:28
Task: webhook handler β written, pending test run
Next: run pytest tests/test_webhook.py
## Ports
3001The assistant never sees a directive. It sees a document that was already true.
Extensibility in Practice
Macros reduce repetition. Pipes compose. Aliases keep things short:
@macro health-check %service%
@query "curl -s http://%service%:8080/health"
@services
- name: %service%
url: http://%service%:8080/health
@endmacro
@q "git log --oneline -5" | @cache ttl=300
@health-check my-apiThe assistant sees resolved output β never a directive.
Full directive reference: docs/DIRECTIVES.md.
Session Waypoints
If an agent session crashes or a connection drops, Waypoints preserve the execution state.
perseus checkpoint \
--task "Implementing webhook integration" \
--status "handler written, pending test run" \
--next "run pytest tests/test_webhook.py" \
--workspace /workspace/myprojectThe next session recovers immediately with perseus recover β workspace-aware, freshness-gated, no re-orientation.
Multi-Agent Coordination

Because Perseus outputs flat files and writes checkpoints to disk, downstream systems can build coordination on top of it without Perseus itself being an orchestration platform. The checkpoint store is namespaced and lock-protected β agents read each other's latest state from the filesystem rather than a message bus. Teams have extended this pattern to multi-agent relay, shared inboxes, and agora task boards.
dev-01: [architect β implementer β reviewer β tester] ββ
dev-02: [architect β implementer β reviewer β tester] ββ€
... ββ shared checkpoint store
dev-30: [architect β implementer β reviewer β tester] ββ (namespaced + lock-protected)Proven at enterprise scale β see Multi-Agent Relay.
Architecture
Plugins: ~/.perseus/plugins/ ββ Discovered at render time.
~/.perseus/validators/ β Macros, hooks, webhooks,
~/.perseus/formats/ β and aliases load from config.
Source document (.perseus/context.md)
@perseus v0.4
@query "git log --oneline -5" β
@read .env key="PORT" β Directives resolved
@waypoint ttl=86400 β before context window.
@services β Cache layer avoids
- name: My App β re-running slow queries.
url: http://localhost:3001/health β
β
βΌ perseus render
Resolved markdown (facts, not instructions)
β
βΌ
.hermes.md βββ cron watchdog keeps this β€5 min fresh
β
βΌ
AI context window β complete, accurate, zero pre-flight tax
Waypoints: ~/.perseus/checkpoints/
Plugins: ~/.perseus/plugins/
Validators:~/.perseus/validators/
Formats: ~/.perseus/formats/
Cache: ~/.perseus/cache/
Config: ~/.perseus/config.yamlExtensibility (Hephaestus)
Perseus is extensible without source patching. Drop Python files into
~/.perseus/ and the renderer discovers them at startup.
Plugins
# ~/.perseus/plugins/my_plugin.py
from perseus.registry import DirectiveSpec
def _resolve_service_status(args, cfg, workspace):
import urllib.request
try:
resp = urllib.request.urlopen(args.strip(), timeout=5)
return f"Status: {resp}"
except Exception as e:
return f"Error: {e}"
REGISTER = {
"@service-status": DirectiveSpec(
name="@service-status",
resolver=_resolve_service_status,
args=["url"],
kind="inline",
call_sig="acw",
executes_shell=False,
safe_for_hover=True,
cacheable=True,
summary="Check HTTP status of a URL",
)
}Use it in context files: @service-status https://api.example.com/health
Built-in directives always win collisions. Plugins respect the same permission
profile as built-ins (executes_shell gates behind allow_query_shell).
Macros
Reusable directive compositions β no Python needed:
@macro deploy %env% %version%
@query "kubectl rollout status deploy/app -n %env%"
@services
- name: app-%env%
url: https://%env%.example.com/health
@endmacro
@deploy production 2.3.1Macros expand before directive resolution. Chaining supported up to depth 5 with
cycle detection. Define them in your context file or at .perseus/macros.md.
Render Pipeline Hooks
Shell scripts or Python callbacks fire at render lifecycle points β
on_render_start, on_directive_resolved, on_cache_hit, on_cache_miss,
on_render_complete, on_directive_error:
# ~/.perseus/config.yaml
hooks:
enabled: true
on_render_complete:
- cmd: "notify-send 'Context refreshed'"
on_directive_error:
- plugin: "my_error_handler"Pipe Syntax
Chain directives with | for lightweight composition (max 3 stages):
@query "ls services/" | @cache ttl=300
@read config.yaml path="endpoints" | @validate schema="endpoint-list"Output of each stage becomes the first positional argument to the next.
Tiered Context (Progressive Disclosure)
Not every question needs the full environment injected. A "what's 2+2?" shouldn't pull in Docker health checks, skill listings, and session digests. Perseus now ships tiered context rendering β the agent is the RAG.
perseus render .perseus/context.md --tier 1 # core context (~12 directives, lean)
perseus render .perseus/context.md --tier 2 # + services, skills, sessions
perseus render .perseus/context.md # everything (backward compatible)Three tiers, assigned per directive in the registry:
Tier | Name | What goes here |
1 | Always | Core context β lightweight, always needed ( |
2 | Conditional | Task-specific, heavier ( |
3 | On-Demand | Bulky/expensive β the agent pulls it if needed ( |
Directives above the tier limit are skipped and reported in a Context Manifest:
> π Context Manifest β Tier limit: 1
>
> β’ @services (Tier 2 / Conditional) β Health-check listed services
> β’ @skills (Tier 2 / Conditional) β List available skills
> β’ @query (Tier 3 / On-Demand) β Run a shell command and embed stdout
>
> Re-run with `perseus render --tier 2` for conditional context,
> or `--tier 3` for full context on demand.Template authors can override per-instance with @tier:N:
@services @tier:1 # Always resolve this block, even though @services defaults to Tier 2
docker
nginx
@endSet render.default_tier: 1 in ~/.perseus/config.yaml to make lean context the default for all renders. No embedding model, no LLM routing β one integer comparison per directive gates resolution. The agent sees what's available and can pull it on demand.
Directive Aliases
Config-driven shorthand β single-pass, no recursive expansion:
# ~/.perseus/config.yaml
directives:
aliases:
"@q": "@query"
"@svc": "@services"
"@stale-skills": "@skills flag_stale=true category=all"Pre-defined aliases: @qβ@query, @rβ@read, @svcβ@services, @mbβ@memory,
@agβ@agora, @wpβ@waypoint, @sessβ@session. Config aliases override them.
Custom Schema Validators
Plugin validators for domain-specific schemas:
@query "cat endpoints.yaml" schema="plugin:endpoint_list"Validator modules in ~/.perseus/validators/ export a validate(value, schema_def)
function returning (valid: bool, message: str).
Event Webhooks
POST render lifecycle events to an external URL with optional HMAC-SHA256 signing:
webhooks:
enabled: true
url: "https://hooks.example.com/perseus-events"
secret: "your-hmac-key"
events:
- on_render_start
- on_render_complete
- on_directive_errorStructured JSON Output
perseus render .perseus/context.md --format jsonReturns {meta, resolved, directives, integrity} β consumable by agents, CI
pipelines, and format plugins in ~/.perseus/formats/.
Allowlisted External Tools
@tool runs external executables with an explicit allowlist, argument
restrictions, timeouts, and output size caps β safer than ad-hoc @agent:
tools:
enabled: true
allowlist:
- path: "/usr/local/bin/scanner"
args_allowlist: ["--workspace", "--format"]
timeout_s: 30
max_output_bytes: 65536@tool "/usr/local/bin/scanner" --workspace . --format json @cache ttl=3600Remote Context Fetching
@perseus <url> fetches rendered context from a remote Perseus serve instance:
@perseus https://team-server:8420/workspace/infra @cache ttl=300Gated by foreign_resolver.allowlist and render.allow_remote_services_health.
Athena gave Perseus a mirror-shield, not a sword. He slew Medusa by watching her reflection β never meeting her gaze directly.
The Medusa is a chaotic development environment. The mirror is resolved context: you see the situation clearly without being paralyzed by it. Hermes gave Perseus winged sandals and guidance; this Perseus returns the favor β giving every AI assistant a way to navigate any workspace without the orientation tax.
Perseus with the Head of Medusa β Benvenuto Cellini, 1545. Loggia dei Lanzi, Florence.
Documentation
Everything else lives in docs/:
Website β Landing page with benchmarks, assistant compatibility, and 30-second quickstart
Quickstart β Install, configure, and render your first context in 5 minutes
Integration Guide β Wire Perseus to Hermes via LLM routing (Hermes Agent by NousResearch)
Adapter Patterns β Wire Perseus to Claude Code, Cursor, Codex, Rovo Dev, and other assistants
Context Packs β Portable workspace context with assistant-specific profiles
CLI Reference β Full command surface:
render,checkpoint,agora,suggest,serve,synthesize, and moreDirectives Reference β All directives with modifiers and examples
Performance Benchmarks β Scaling data, cold vs. warm, enterprise profiles
Container Runtime β Docker and compose deployment
Contributing β How to contribute code, directives, and tests
Edge-Case Vetting β Tests covering circular deps, race conditions, symlink escapes, and context overflow
Product Contract β What Perseus guarantees and what it doesn't
VSCode Extension β LSP server + editor integration
License
MIT β see LICENSE.
Maintenance
Latest Blog Posts
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/tcconnally/perseus'
If you have feedback or need assistance with the MCP directory API, please join our Discord server