YAML Metadata Warning:empty or missing yaml metadata in repo card
Check out the documentation for more information.
RSIH
Turn an agent's harness into something you can version, share, and generate automatically.
Built on the Pi coding agent, with a configuration layer called Genome on top. A Genome is a complete, self-contained, deliverable harness configuration โ system prompt, tool set, skills, MCP servers, extensions, runtime policies, memory, keybindings, themes โ all in one directory. Switching contexts is switching Genomes.
Basic usage
git clone https://github.com/CosmosMind-ai/RSI-Harness.git && cd RSI-Harness
./install.sh
Requires Node 22.19+. The script checks dependencies, builds, installs into
~/.local/bin, and asks you to pick an install mode: --copy moves the binary and
all its assets out of the repo for good; --link symlinks to the build output, for
hacking on RSIH itself. With bun installed it compiles a single-file binary; without
it, it falls back to a node wrapper.
Once installed, rsih is pi, zero difference: every flag, subcommand, and slash
command works unchanged. Launched without a Genome it behaves exactly like pi โ a
test guards this invariant โ except the config directory becomes ~/.rsih:
rsih
rsih --resume
rsih --fork <session>
rsih -p "Review the current workspace"
For scripted use, add --run-id: every call carrying the same id appends to the same
conversation, and the Genome is stated once, on the first call, then restored
automatically:
rsih :notes -p "Outline this week's lab notes" --run-id week-32 --cwd ~/lab
rsih -p "Section 3 is too long; split it" --run-id week-32 --cwd ~/lab
rsih -p "Export as markdown" --run-id week-32 --cwd ~/lab --json
--cwd sets the working directory and where the session lands, --model swaps the
model for one call, and --json emits a structured event stream.
Launching a Genome
Everything that separates RSIH from pi comes from one switch: name a Genome at
launch. Four spellings are equivalent:
rsih --genome coding # explicit
rsih :coding # colon shorthand
rsih ::coding # double colon
rsih +coding # plus
Only the first argument counts. Pi treats positional arguments as the message and
most options take a value, so a genome marker anywhere else would swallow a message
word or an option value. (( is not offered: it is a shell metacharacter โ
rsih (coding is a syntax error in both zsh and bash.)
Two Genomes ship with the distribution:
| Genome | What it is |
|---|---|
coding |
a harness for writing code |
harness-rsi |
the harness that builds harnesses โ its output is other Genomes |
Managing Genomes:
rsih genome list # what's installed, what shipped, what's outdated
rsih genome show coding # resolved Genome + the settings patch it would write (read-only)
rsih genome validate ./my-genome
rsih genome install coding # restore the factory version
Drop a Genome directory someone shared with you into ~/.rsih/genomes/ and it runs.
GEE: generating a Genome from your history
gee # == rsih :harness-rsi == rsih --genome harness-rsi
How it works. GEE never asks what system prompt you want โ it reads what you
actually did. It starts by asking one question in conversation: what is this Genome
for? Then it asks which session stores to analyze (RSIH's own is included by default;
you can add Pi's ~/.pi/agent/sessions and Claude Code's ~/.claude/projects). It
groups history by working directory, then aggregates tool-call histograms, frequent
bash commands, hot files, and the corrections you keep repeating โ aggregating first,
reading raw text selectively, never dumping a whole JSONL into context. The scenario
you described becomes the yardstick for classifying evidence: which recurring pattern
should become a skill, which a tool, which an MCP server, and which is mere
preference for memory. Before writing anything it walks you through the whole plan
with its evidence, in enough detail that you can object to the wording. It writes
nothing until you confirm.
What it produces. A Genome directory, ~/.rsih/genomes/<name>/: the
genome.json manifest plus configuration for the 12 components (instructions, tools,
skills, commands, model, runtime, policies, integrations, โฆ), passing the
rsih genome validate gate on completion. Launch it with rsih :<name>. Send the
directory to someone else and it runs from their ~/.rsih/genomes/.
Why this design
Harnesses should be first-class. Tuning an agent today scatters configuration
across settings.json, CLI flags, prompts pasted around, and "I remember that prompt
worked well last time" โ none of it versionable, diffable, reproducible, or handable
to someone else. Genome collects it into one object.
No fork of the Core, only its public configuration surface. CLI, TUI, slash commands, keybindings, session tree/fork/resume, the model and settings screens, extension UI โ all provided by Pi; this project re-implements none of it.
Pi coding-agent โ immutable Core, not forked
โ
Genome adapter โ this project
โ
harness-rsi โ a Genome whose output is other Genomes
Two invariants follow, each held by a test:
- Without
--genome,rsihbehaves exactly likepi, except the config directory becomes~/.rsih. - Anything Pi can configure, a Genome can configure.
test/pi-surface.test.tsextracts every settings key and keybinding id from Pi's own.d.ts; any key left unrouted turns the test red โ when a Pi upgrade adds a switch, the test tells you first.
Configuration is a patch, not a replacement. An absent field inherits the Pi
default; null resets explicitly to the default; only a present value overrides
(objects merge recursively, arrays replace wholesale). A Genome that sets only
model still gets Pi's full system prompt, full tool set, and AGENTS.md discovery.
You never reimplement a harness to change one field.
Self-referential. Not one line in src/ serves harness-rsi itself: its charter
lives in the instructions component, its methodology in a file-based skill, its
interactive tools in its own extension โ built entirely with means available to any
ordinary Genome. That is where "RSI" lands: not the model editing its own weights,
but editing its own harness, by exactly the means you would use to hand-write
one.
Personalization from evidence. harness-rsi does not ask what system prompt you
want; it reads what you have done. Fields without evidence stay empty โ empty means
inheriting the Pi default, which is always the safe answer.
Hand-writing a Genome
A directory bundle whose manifest is always named genome.json:
my-genome/
genome.json # base + component list
components/<id>.json # each component's configuration
contracts/<id>.dev.md # each component's contract (what it may touch)
skills/** # bundled skills
extension/*.ts # bundled extensions
Twelve components with mutually exclusive field ownership; an out-of-bounds write
fails at load time (a tools component trying to set system_prompt โ immediate
failure):
| Component | Owns |
|---|---|
instructions |
system_prompt, append_system_prompt |
tools |
built-in tool on/off (patch semantics), argument narrowing, generated tools |
skills |
inline skills and Pi skill files/directories |
commands |
inline slash commands and Pi prompt template files |
model |
default provider/model, model cycle list, request options |
runtime |
tool execution, steering, follow-up, max turns, thinking level |
policies |
tool policies, scratchpad, compaction, memory |
integrations |
Pi extensions and stdio MCP servers |
appearance |
Pi theme assets, theme selection, theme discovery |
settings |
every field of Pi's settings.json |
keybindings |
every binding in Pi's keybindings.json |
resources |
scope of Pi's automatic resource discovery (isolate) |
โ Component protocol ยท 12 contracts ยท harness-rsi in depth
Mechanics
Discovery order (first match wins); a path also works directly:
./.rsih/genomes/<name>.json or ./.rsih/genomes/<name>/genome.json
~/.rsih/genomes/<name>.json or ~/.rsih/genomes/<name>/genome.json
<dist>/genomes/<name>/genome.json # seed
The third layer is a seed, not the run location. A built-in Genome is copied into
~/.rsih/genomes/ the first time it is used by name, and loaded from there ever
after โ the Genome you run always lives in your own directory, and its skills and
extensions load from there too. Send someone a Genome folder; it runs from their
~/.rsih/genomes/.
Seeds update, but never overwrite you. At install time a .rsih-seed.json
inside the bundle records the seed's content hash:
| Situation | Behavior |
|---|---|
| Seed unchanged | nothing happens (edits included โ that copy is yours) |
| New seed, you didn't edit | refreshed automatically, announced at startup |
| New seed, you edited | left alone โ a warning plus rsih genome install <name> |
| Same-name Genome from someone else | left alone (different genome_id โ never overwritten) |
Settings are compiled. Pi has no API for injecting settings, so keys a Genome
declares are rewritten into ~/.rsih/settings.json at every startup; keys it doesn't
declare (including theme and defaultModel, which Pi writes itself) pass through
untouched. Switching Genomes clears keys the previous one managed and the current one
no longer declares. The managed set is recorded in the file as $rsih.managedKeys.
A project-level <cwd>/.rsih/settings.json outranks the Genome โ an explicit escape
hatch.
Semantic fields and the escape hatch. Semantic fields like
runtime.steering_mode, policies.compaction, and model.cycle project onto the
corresponding Pi settings; the settings component is the raw escape hatch at the
bottom layer โ values written there override the projections.
Current status
Works: building Genomes end to end โ 12 components covering Pi's whole
configuration surface, inherit-by-default merging, the settings compilation layer,
directory bundles, seeding and upgrades, and harness-rsi generating interactively
from the RSIH, Pi, and Claude Code session stores.
Not yet: getting someone else's Genome. genome install accepts built-in names
and local paths only, not git/npm URLs. There is no pre-publish redaction gate
either โ a Genome is distilled from private transcripts, and before sharing it must
be able to flag absolute paths, intranet domains, and likely secrets. The Codex
session store is not wired up: it is another order of magnitude (1341 files /
2.9 GB on this machine, largest single file 298 MB) and needs either MB-scale read
windows or a join against history.jsonl.
See TODO.md for the backlog and known limits.
Development
npm run check # typecheck + test + build
npm run build:binary
npm run smoke:binary
npm run sync:contracts # after editing docs/genome/components/, sync into the bundle
The documentation index lives at docs/README.md. The repository contains no benchmark, data-generation, training, or evaluation code.