# Se-harness – portable, tool-agnostic AI coding harness generator

> Source: <https://github.com/manuuuel/seh>
> Published: 2026-08-11 06:14:29+00:00

Portable, tool-agnostic AI coding harness generator. One source of truth,
`AGENTS.md`

as the entrypoint, no vendor lock-in.

[Quick Start](#quick-start)[Why seh](#why-seh)[Layers](#layers)[The two shapes of](#the-two-shapes-of-agentsmd)`AGENTS.md`

[Commands](#commands)[Harness Packages](#harness-packages)[Skills](#skills)[Memory](#memory)[Agent skill directories](#agent-skill-directories)[Installation](#installation)[Try it (sandboxed demo)](#try-it-sandboxed-demo)[Development](#development)

```
curl -fsSL https://raw.githubusercontent.com/manuuuel/seh/main/scripts/install.sh | sh

# Once per machine: unified global ruleset + agent symlinks
seh init --global --agents claude,codex --yes

# Per project: detect stack, scaffold AGENTS.md + .seh/
cd your-project
seh init --tech typescript --yes

# Regenerate generated files after editing .seh/ sources
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 file**Craftsmanship** 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.) are**generated symlinks** to`.seh/AGENTS.md`

, gitignored, and regenerated by`seh 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 technology`seh.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.

``` php
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 in`harness.json`

only; appends`skills/<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
---

# Auth strategy

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 via`SEH_HOME`

/`SEH_BIN`

). Requires`node`

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
```


