A tiny scaffold for spinning up a focused workspace with your favorite agentic-coding tool. Open a folder, get a fresh session with the mission, knowledge base, and freshness-aware validation already loaded. Works in Claude Code, Amplifier, Cursor, Codex CLI, Amp, Cline, RooCode, Aider, Gemini CLI, and Windsurf.
The pain it solves. Every new project you start with an agentic assistant, you re-explain context — what data feeds you use, what "done" looks like, what the mission is. You paste in URLs and commands. Six weeks later half of them are broken and you don't know which ones. A batcave gives you one place to keep that context, in a format that knows when it's gone stale.
- See it in action
- Get started in 5 minutes
- The full model
- Adapters
- FAQ and troubleshooting
- Contribute a new adapter
- License
- Acknowledgments
A batcave for triaging your GitHub PR backlog looks like this:
triage-prs/
├── CLAUDE.md ← persona + mission + operating rules
├── README.md
├── .claude/settings.json ← PostToolUse hook: runs okf.py validate
├── .batcave/canonical ← one line: absolute path to canonical okf.py
├── scripts/okf.py ← vendored validator + toolkit
├── knowledge/
│ ├── index.md ← generated listing
│ ├── connectors/
│ │ └── github-prs.md ← type: Connector — how to pull PRs
│ ├── reference/
│ │ └── triage-rubric.md ← type: Reference — how to score them
│ └── records/
│ └── 2026-07-27-morning.md ← type: Record — this morning's triage
└── outputs/
└── triage-report-2026-07-27.md ← the deliverable
Everything in knowledge/ is an OKF markdown file — YAML frontmatter with a type, human-readable body:
knowledge/connectors/github-prs.md
---
type: Connector
title: Open PRs where I'm the reviewer
description: All open PRs across my repos with review requested from me
verified: 2026-07-27
stale_after: 2026-10-27
---
# Open PRs where I'm the reviewer
**Refresh:** each session
## How to ingest
gh search prs --review-requested=@me --state=open \
--json number,title,url,repository
## Shape / notes
Returns a JSON array. Each item has `number`, `title`, `url`,
`repository.nameWithOwner`. Rate-limited to 30 req/min unauthenticated;
uses `$GITHUB_TOKEN` if set.Open the folder in Claude Code (cd triage-prs && claude) and you're in — persona loaded, okf.py validate guarding every edit, ready to pull today's data through the connector. Three months from now, okf.py stale tells you which connectors need re-verifying before you trust them.
Have Claude Code installed? Three commands:
# 1. Clone this repo
git clone https://github.com/<you>/batcave.git
cd batcave
# 2. Install the Claude Code adapter as a skill
mkdir -p ~/.claude/skills/batcave/lib
cp adapters/claude-code/SKILL.md ~/.claude/skills/batcave/SKILL.md
cp core/okf.py ~/.claude/skills/batcave/lib/okf.py
cp adapters/claude-code/settings.json ~/.claude/skills/batcave/lib/settings.json
# 3. Tell okf.py where its canonical copy lives (so `okf.py update` works
# inside handed-off caves)
echo 'export BATCAVE_CANONICAL="$HOME/.claude/skills/batcave/lib/okf.py"' >> ~/.zshrc
export BATCAVE_CANONICAL="$HOME/.claude/skills/batcave/lib/okf.py"Now in any Claude Code session, say:
"set up a batcave for triaging my PR backlog"
The skill walks you through the mission, tier, feeds, and location, then scaffolds the folder. Hand off with cd triage-prs && claude and start working.
Each adapter has its own 3-step install. Pick yours:
| Tool | Install guide | Enforcement |
|---|---|---|
| Claude Code | adapters/claude-code/ | hard (per-write hook) |
| Amplifier | adapters/amplifier/ | soft + git-gated |
| Codex CLI, Amp, Cline, RooCode, Aider | adapters/agents-md/ | soft + git-gated |
| Cursor | adapters/cursor/ | soft + git-gated |
| Gemini CLI | adapters/gemini/ | soft + git-gated |
| Windsurf | adapters/windsurf/ | soft + git-gated |
See Enforcement — an honest table below for what "hard" vs "soft + git-gated" actually mean.
A batcave has exactly two moving parts:
- A persona file — whichever file your tool auto-loads from the working directory:
CLAUDE.md,AGENTS.md,GEMINI.md,.cursor/rules/persona.mdc,.windsurfrules. This holds the mission, tone, and operating rules for whoever works out of the cave. - A
knowledge/directory — an OKF bundle: everything the cave knows, as markdown files with YAML frontmatter. Feeds, references, records, playbooks — all of it, one format.
Plus, at the standard tier and above, vendored tooling (scripts/okf.py) and a validation hook that keeps the format true without relying on anyone remembering to.
Everything the cave knows is an OKF document. There is no second vocabulary.
A data feed is not a special kind of file in a special directory — it is a document with type: Connector. A durable fact is type: Reference. One tracked item is type: Record. Types are producer-defined; invent what the mission needs.
This matters because knowledge decays. A scraping trick that worked in July is broken by October. OKF's verified / stale_after fields make a cave able to tell you what it no longer trusts, instead of confidently serving you a dead URL.
Full spec: core/SPEC.md.
batcave/
├── core/ ← tool-agnostic; the actual value
│ ├── SPEC.md ← what a batcave IS
│ ├── okf.py ← zero-dependency validator + toolkit
│ └── templates/ ← placeholder-driven scaffolding templates
└── adapters/ ← one per agentic-tool ecosystem
├── claude-code/ ← Claude Code (SKILL.md + PostToolUse hook)
├── amplifier/ ← Amplifier (SKILL.md + AGENTS.md persona)
├── agents-md/ ← Codex CLI, Amp, Cline, RooCode, Aider
├── cursor/ ← Cursor (.cursor/rules/*.mdc)
├── gemini/ ← Gemini CLI (GEMINI.md persona)
└── windsurf/ ← Windsurf (.windsurfrules persona)
Every adapter implements the same procedure from core/SPEC.md. What differs is only the persona filename, the enforcement mechanism, and the launch command.
Not every mission needs the whole spec. Pick the smallest tier that fits.
| Tier | When | OKF subset | Tooling |
|---|---|---|---|
| lean | one-shot or throwaway mission | type only |
none — just persona + knowledge/ |
| standard | recurring work, modest knowledge | + title, description, tags, generated index.md |
vendor okf.py + validation hook |
| living | knowledge accumulates and decays | + verified, status, stale_after, log.md |
above + okf.py stale sweeps |
Tiers are advisory. Start lean; graduate whenever you're ready.
Connector— a data feed. Must carry a runnable command, not prose.Reference— a durable fact or ruleset.Record— one instance of whatever the cave tracks.Playbook— a repeatable procedure with steps.Template— a reusable skeleton for an output.
| Level | What it means | Where you get it |
|---|---|---|
| Hard (per-write) | okf.py validate --hook runs after every Write/Edit; the agent sees stderr as feedback and must fix. |
Claude Code (PostToolUse hook). Optionally Amplifier if your bundle wires a hooks-* module. |
| Soft + git-gated | The persona asks the agent to run okf.py validate after edits; a git pre-commit hook refuses invalid commits. |
Amplifier, all AGENTS.md-standard tools, Cursor, Gemini CLI, Windsurf. |
Tools without a universal PostToolUse hook can't offer per-write enforcement. The git pre-commit hook is the hard boundary; the persona is the soft one. Every adapter's README states which level it provides — no false parity.
A cave built by adapters/agents-md/ (or by adapters/amplifier/, which also uses AGENTS.md) works unmodified in Codex CLI, Amp, Cline, RooCode, and Aider — all of them auto-load AGENTS.md. One cave, five tools.
- Each adapter vendors
core/okf.pyinto a cave at scaffold time as<cave>/scripts/okf.py. The cave is standalone after that — hand it to someone else and it works. core/okf.pyreads$BATCAVE_CANONICAL(or./.batcave/canonical, a pointer file dropped at scaffold time) to know where to re-vendor from when a user runspython3 scripts/okf.py update. No single host tool's install layout is baked into the source.- Placeholder-driven templates in
core/templates/are the shared vocabulary; each adapter renders them into the tool's expected filename.
I ran python3 scripts/okf.py update and it said "cannot locate canonical copy."
Set BATCAVE_CANONICAL to the absolute path of the canonical okf.py:
- Claude Code:
$HOME/.claude/skills/batcave/lib/okf.py - Amplifier:
$HOME/.amplifier/skills/batcave/lib/okf.py - Everything else: wherever you copied it (see your adapter's README)
Add the export to your shell profile so it persists.
Alternatively, the cave itself has .batcave/canonical — a one-line pointer written at scaffold time. If yours is missing or wrong, edit it manually.
The Claude Code PostToolUse hook doesn't seem to fire.
Check three things:
<cave>/.claude/settings.jsonexists and contains aPostToolUseblock matchingWrite|Edit.<cave>/scripts/okf.pyexists — the hook silently exits 0 if the script is missing, so you'll see nothing.- Your Claude Code version supports PostToolUse hooks. Older versions do not.
My git pre-commit hook isn't running.
.git/hooks/pre-commit must be executable: chmod +x .git/hooks/pre-commit. On minimal containers, verify python3 is on PATH.
okf.py validate fails on a file I didn't intend to be a knowledge doc.
Either move it out of knowledge/, or add its filename to RESERVED in core/okf.py if it's a convention the tool needs. index.md, log.md, README.md, and each tool's persona filename are already reserved.
Can I hand-edit knowledge/*/index.md?
Yes — remove the <!-- generated by okf.py --> comment at the top and okf.py index will leave it alone.
Do I have to use the tier I picked at scaffold time forever?
No. Tiers are advisory. Add verified / stale_after to documents whenever you're ready, and start running okf.py stale on a schedule. You're now a living-tier cave.
Where do I put secrets like API tokens?
Never in a file. Reference the env var name in your Connector doc (e.g. "auth via $GITHUB_TOKEN") and export it in your shell. okf.py will not complain, and your cave stays safe to share.
Can a cave be its own git repo?
Yes — most should be. Run git init inside a cave to get the pre-commit hook (standard+ tiers install one automatically). A cave is designed to be a self-contained repo you can push, share, or hand off.
To port batcave to a new agentic tool, answer these four questions:
- What filename does the tool auto-load as a persona from the working directory?
- How (if at all) can it run a shell command after every file write?
- What's the launch command?
- Where does it install skills / rules / plugins (if any)?
Then copy adapters/agents-md/ as a starting shape, adjust, add a row to the enforcement table, and send a PR.
Guard rails for changes to core/:
core/okf.pymust stay zero-dependency (PyYAML is optional at runtime).- Do not bake a host tool's paths into it. Canonical resolution goes through
$BATCAVE_CANONICALand./.batcave/canonical. core/SPEC.mdis the source of truth. If you change the shape of a batcave, update the spec first, then the adapters.- Do not invent a second vocabulary outside the OKF bundle.
See CONTRIBUTING.md for the full guide and CODE_OF_CONDUCT.md for community norms.
MIT — see LICENSE.
Created and maintained by Manoj Prabhakar Paidiparthy (@manojp99).
Issues, PRs, and adapter proposals for other agentic tools are welcome — see CONTRIBUTING.md.
- Open Knowledge Format (OKF) v0.2 spec from GoogleCloudPlatform/knowledge-catalog.
- The
AGENTS.mdcross-tool persona-file convention from agents.md.