Portable, tool-agnostic AI coding harness generator. One source of truth,
AGENTS.md
as the entrypoint, no vendor lock-in.
Quick StartWhy sehLayersThe two shapes ofAGENTS.md
CommandsHarness PackagesSkillsMemoryAgent skill directoriesInstallationTry it (sandboxed demo)Development
curl -fsSL https://raw.githubusercontent.com/manuuuel/seh/main/scripts/install.sh | sh
seh init --global --agents claude,codex --yes
cd your-project
seh init --tech typescript --yes
seh sync
This gives you a ~/.seh/AGENTS.md
global ruleset symlinked into your
agents' config paths, plus a project AGENTS.md
(and CLAUDE.md
,
GEMINI.md
, …) that every supported agent reads automatically.
seh
produces the context files that AI coding agents (Claude Code, Codex,
Gemini, Pi, OpenCode, Copilot, …) read: a single global ruleset on your
machine plus a per-project index of focused, technology-specific
guideline modules. Skills from a harness package are distributed to every
agent that supports them. Edit one source of truth, run seh sync
, and
every tool-specific file regenerates in lockstep — no more copy-pasting the
same rules into CLAUDE.md
, GEMINI.md
, and .github/copilot-instructions.md
separately.
| Layer | Location | What it is |
|---|---|---|
| L0 — Core | ||
| bundled in the CLI | The authored source content (global sections + per-technology catalog). Fallback when no package is active. | |
| L1 — Global | ||
~/.seh/ |
||
A single unified with your cross-cutting rules. Authored once per machine; optional agent symlinks. Not copied into repos.AGENTS.md |
||
| L2 — Project | ||
<repo>/AGENTS.md + .seh/ |
||
| A thin index linking project + per-technology modules. Committed to the repo. | ||
| Package | ||
<your-harness>/ |
||
| A versioned git repo of global rules, stack modules, templates, and skills. Takes precedence over L0/L1 when active. |
Resolution order for any file: package → ~/.seh/ → seh bundled core.
Global rules apply everywhere; project layers extend — never contradict them.
Generated files must NOT be hand-edited. Edit the .seh/
sources and run
seh sync
to regenerate.
Global (— every guardrail inlined in a single document, led by a forced~/.seh/AGENTS.md
) is one self-contained fileCraftsmanship principle (keep it small and sharp, write elegant code, seek the most minimal better-working design, introduce no slop). Tools that auto-load a global instructions file get the whole ruleset directly. -
Project (— a short directive preamble plus a progressive index (linked table of contents) pointing at focused modules under<repo>/.seh/AGENTS.md
) is the canonical file.seh/
, loaded on demand:.seh/project.md
— mission, constraints, out-of-scope (read-first).seh/domain/*.md
— architecture, glossary.seh/stack/<tech>.md
— per-technology best practices
Tool-specific files (
AGENTS.md
,CLAUDE.md
,GEMINI.md
,.github/copilot-instructions.md
, etc.) aregenerated symlinks to.seh/AGENTS.md
, gitignored, and regenerated byseh sync
.
seh init --global # interactive: choose which agents to symlink
seh init --global --agents claude,codex --yes # non-interactive
Creates:
~/.seh/AGENTS.md
— the unified global ruleset (Craftsmanship first, then security, quality gates, testing, commits, branching, dependencies, error handling, observability, data & privacy, documentation, refactoring, workflow, session startup, reporting, boundaries, code principles).~/.seh/config.json
— which agents are symlinked.
Optionally wire agents to auto-load it (see seh link
).
cd your-project
seh init # detects technologies, interactive multi-select
seh init --tech typescript,python --yes # non-interactive (≥1 required)
Creates:
AGENTS.md
— the project index (links to the modules below).seh/project.md
,.seh/domain/architecture.md
,.seh/domain/glossary.md
.seh/stack/<tech>.md
for each selected technologyseh.lock
— records the selected technologies (commit it)
Supported technologies: javascript
, typescript
, python
, go
, c
,
rust
, java
. No generic fallback — pick at least one.
Then fill in .seh/project.md
and .seh/domain/*
and re-sync.
seh sync
Rewrites the project AGENTS.md
index and .seh/stack/*
from seh.lock
. Idempotent (no change on re-run with unchanged sources).
seh check
Exit 0 if the generated files match the sources; exit 1 (with a message) if
AGENTS.md
or a stack module is stale or missing. Suitable for pre-commit/CI.
seh link --add claude # symlink ~/.claude/CLAUDE.md -> ~/.seh/AGENTS.md
seh link --remove claude # remove it
AGENTS.md
stays the single source of truth; symlinks are pure pointers, so there is no per-agent content to drift.
Supported agents: claude
, codex
, pi
, gemini
, opencode
, copilot
, agents
The agents
target manages the cross-agent interoperability path (~/.agents/
,
.agents/
) used as an alias by Gemini CLI, Pi, Copilot, and others.
| Agent | Target |
|---|---|
claude |
|
~/.claude/CLAUDE.md |
|
codex |
|
~/.codex/AGENTS.md |
|
pi |
|
~/.pi/agent/AGENTS.md |
|
gemini |
|
~/.gemini/GEMINI.md |
|
opencode |
|
~/.config/opencode/AGENTS.md |
|
copilot |
|
~/.copilot/copilot-instructions.md |
|
agents |
|
~/.agents/AGENTS.md |
| Agent | Target | Canonical |
|---|---|---|
claude |
||
CLAUDE.md |
||
.seh/AGENTS.md |
||
codex |
||
AGENTS.md |
||
.seh/AGENTS.md |
||
pi |
||
AGENTS.md |
||
.seh/AGENTS.md |
||
gemini |
||
GEMINI.md |
||
.seh/AGENTS.md |
||
opencode |
||
AGENTS.md |
||
.seh/AGENTS.md |
||
copilot |
||
.github/copilot-instructions.md |
||
.seh/AGENTS.md |
||
agents |
||
.agents/AGENTS.md |
||
.seh/AGENTS.md |
A harness package is a plain directory the user versions with git, carries
between machines, and shares with teammates. seh
scaffolds and reads it; git is fully external and never wrapped.
my-harness/
├── harness.json — package metadata (name, version, modelTag)
├── CHANGELOG.md — harness decisions and reasoning (human-authored)
├── global/
│ ├── AGENTS.md — global ruleset (replaces ~/.seh/AGENTS.md)
│ └── config.json — agent symlink config
├── templates/
│ ├── stack/ — per-technology structural patterns
│ └── project/ — full project scaffolds
├── projects/ — per-repo overlays matched by repo name
└── skills/ — skills to distribute (vendored or referenced)
├── brainstorming/ — vendored skill (committed to package repo)
└── caveman/ — referenced skill (fetched on install)
Scaffolds a new harness package at path
(default: ./my-harness
). Creates
the full directory structure, copies bundled stack modules as a starting point,
writes harness.json
and an empty CHANGELOG.md
.
seh package init ~/my-harness
cd ~/my-harness && git init && git add . && git commit -m "init harness"
Points seh
at an existing package. Writes packagePath
into ~/.seh/config.json
.
git clone git@github.com:you/my-harness.git ~/my-harness
seh package use ~/my-harness
Shows the currently active package path, name/version from harness.json
, and whether each expected directory exists.
Installs artifacts from the active package onto the host machine.
seh package install --harness # write ~/.seh/AGENTS.md + agent symlinks
seh package install --skills # symlink skills into ~/.seh/skills/ + agent dirs
seh package install --all # both of the above
seh package install --all --agents claude,gemini # non-interactive agent selection
| Flag | Action |
|---|---|
--harness |
|
Writes ~/.seh/AGENTS.md from package/global/AGENTS.md ; updates agent symlinks |
|
--skills |
|
Fetches referenced skills, symlinks package/skills/<name>/ → ~/.seh/skills/<name>/ → agent skill dirs |
|
--all |
|
| Both of the above | |
--agents <list> |
|
| Comma-separated agents to receive skill symlinks (prompts interactively if omitted) | |
--force |
|
| Overwrite existing files |
New machine workflow:
git clone git@github.com:you/my-harness.git ~/my-harness
seh package use ~/my-harness
seh package install --all
Skills (reusable SKILL.md
-based capability packages) are a first-class layer
in the harness package. seh
distributes them from the package to every agent that supports a skill directory.
<package>/skills/<name>/ ← source (vendored or referenced)
↓ symlink
~/.seh/skills/<name>/ ← stable intermediate on this machine
↓ symlinks
~/.claude/skills/<name>/ ← Claude Code
~/.codex/skills/<name>/ ← Codex CLI
~/.gemini/skills/<name>/ ← Gemini CLI
~/.config/opencode/skills/<name>/ ← OpenCode
~/.pi/agent/skills/<name>/ ← Pi
~/.copilot/skills/<name>/ ← GitHub Copilot
~/.agents/skills/<name>/ ← cross-agent interoperability path
~/.seh/skills/
is the stable intermediate: if the package moves, agent symlinks remain intact until re-pointed.
Adds a skill from a GitHub URL to the active package.
seh skills add https://github.com/JuliusBrussee/caveman --reference
seh skills add github:you/my-skill --vendor --ref v1.2
--vendor
: clones files into<package>/skills/<name>/
(committed to git)--reference
: records the URL inharness.json
only; appendsskills/<name>/
to.gitignore
; files are fetched at install time- Prompts for type if neither flag is given
- Infers skill name from the repo name
Routing flags tell agents when to invoke the skill. Exactly one may be used:
| Flag | When agent invokes |
|---|---|
--always [label] |
|
| Every response | |
--when <condition> |
|
| When the described scenario matches | |
--optional |
|
| Agent decides based on context |
seh skills add github:you/caveman --vendor --always "every response"
seh skills add github:you/systematic-debugging --vendor --when "bug / test failure / unexpected behavior"
seh skills add github:you/xlsx --vendor --optional
Routing is stored in harness.json
and rendered into a ## Skills
section in
both the project AGENTS.md
(by seh sync
) and the global ~/.seh/AGENTS.md
(by seh package install --harness
), so agents always know which skills to invoke and when.
Re-fetches referenced skill(s) from their source. No arguments updates all referenced skills. Errors if the named skill is vendored.
Shows skills in the active package with their routing mode:
✓ brainstorming [vendor] always: before any implementation
✓ systematic-debugging [vendor] when: bug / test failure
✗ caveman [reference] https://github.com/JuliusBrussee/caveman (ref: main)
✓ xlsx [vendor] optional
✓
= files present on disk, ✗
= reference not yet fetched (run
seh package install --skills
to fetch).
{
"name": "my-harness",
"version": "1.0.0",
"skills": {
"brainstorming": {
"type": "vendor",
"invoke": { "mode": "always", "label": "before any implementation" }
},
"systematic-debugging": {
"type": "vendor",
"invoke": { "mode": "when", "condition": "bug / test failure / unexpected behavior" }
},
"caveman": {
"type": "reference",
"source": "https://github.com/JuliusBrussee/caveman",
"ref": "main",
"invoke": { "mode": "always", "label": "every response" }
},
"xlsx": {
"type": "vendor",
"invoke": { "mode": "optional" }
}
}
}
The same ## Skills
section is appended to the project .seh/AGENTS.md
(by
seh sync
) and to the global ~/.seh/AGENTS.md
(by
seh package install --harness
) whenever a skill has routing configured:
## Skills
Always invoke:
- `brainstorming` — before any implementation
- `caveman` — every response
Invoke when:
- `systematic-debugging` — bug / test failure / unexpected behavior
Optional:
- `xlsx`
Skills with no invoke
field are omitted from this section. If no skills have routing, the section is omitted entirely.
.seh/memory/
stores typed markdown files that agents read for persistent project context — decisions made, constraints discovered, learnings earned, problems still open. Files are committed to the repo so the whole team (and every agent) shares the same memory.
---
type: decision
---
Chose JWT over sessions. Sessions required sticky routing which complicates
the Docker setup. JWT is stateless and works across all replicas.
Types:
| Type | When to use |
|---|---|
decision |
|
| A choice made and why (architecture, tech, approach) | |
constraint |
|
| A hard rule discovered (never do X, always do Y) | |
learning |
|
| Something non-obvious that cost time to figure out | |
problem |
|
| Unresolved issue to pick up next session |
Creates .seh/memory/<name>.md
with the correct frontmatter and opens
$EDITOR
(prints the file path if $EDITOR
is unset). Default type is
decision
. Does not overwrite an existing file.
seh memory add auth-strategy # type: decision (default)
seh memory add rate-limiting --problem
seh memory add jwt-expiry --learning
seh memory add url-structure --constraint
Shows all memory files grouped by type:
Decisions
auth-strategy Chose JWT over sessions
db-migrations Use Flyway, not Liquibase
Constraints
url-structure Never expose user IDs in URLs
Learnings
jwt-expiry Access tokens must be short-lived (<15m)
Open problems
rate-limiting Strategy unresolved — Redis vs in-process
Deletes .seh/memory/<name>.md
.
seh sync
appends a ## Memory
section to .seh/AGENTS.md
whenever
.seh/memory/
exists. It always includes a protocol block instructing agents to write memory at session end, plus an index of existing files grouped by type:
## Memory
Write to `.seh/memory/` at end of every session:
- **decision** — a choice made and why (architecture, tech, approach)
- **constraint** — a hard rule discovered (never do X, always do Y)
- **learning** — something non-obvious that cost time to figure out
- **problem** — unresolved issue to pick up next session
Run: `seh memory add <name> [--decision|--constraint|--learning|--problem]`
### Decisions
- [Auth strategy](.seh/memory/auth-strategy.md) — Chose JWT over sessions
### Open problems
- [Rate limiting](.seh/memory/rate-limiting.md) — Strategy unresolved
If .seh/memory/
is empty the protocol block is still rendered (so new agents know how to populate it). If the directory doesn't exist the section is omitted.
All supported agents have confirmed user-level skill directories (as of 2026-07):
| Agent | User skill directory |
|---|---|
claude |
|
~/.claude/skills/<name> |
|
codex |
|
~/.codex/skills/<name> |
|
gemini |
|
~/.gemini/skills/<name> |
|
opencode |
|
~/.config/opencode/skills/<name> |
|
pi |
|
~/.pi/agent/skills/<name> |
|
copilot |
|
~/.copilot/skills/<name> |
|
agents |
|
~/.agents/skills/<name> |
seh is distributed from GitHub — no npm registry account needed.
One command installs a self-contained build (deps bundled) and puts seh
on
your PATH — no npm, no build step, no global node_modules
:
curl -fsSL https://raw.githubusercontent.com/manuuuel/seh/main/scripts/install.sh | sh
Update: re-run the same command.Pin a version:curl -fsSL .../scripts/install.sh | SEH_REF=v0.4.1 sh
- Installs to
~/.local/share/seh
, symlinks~/.local/bin/seh
(override viaSEH_HOME
/SEH_BIN
). Requiresnode
on PATH. Uninstall:rm -rf ~/.local/share/seh ~/.local/bin/seh
npm install -g github:manuuuel/seh # latest main
npm install -g github:manuuuel/seh#v0.4.1 # a tag
npm installs go through npm's git-dep preparation, which can fail with ENOTDIR
if a previous global install left a broken entry. If that happens, remove the
stale .../lib/node_modules/se-harness
, run npm cache clean --force
, and retry — or just use the curl installer above, which avoids npm entirely.
git clone git@github.com:manuuuel/seh.git ~/pocs/seh
cd ~/pocs/seh
npm install
npm run build
npm link # makes `seh` available in $PATH
To uninstall: npm unlink -g se-harness
.
npm install --save-dev github:manuuuel/seh
npx seh init
Runs the whole flow against a throwaway HOME
— your real ~/.seh
and
~/.claude
are untouched:
npm run try
npm install
npm run build # compile to dist/
npm test # run the test suite (155 tests)
npm run dev # run the CLI via tsx without building