geneseed 3.10.0 → 3.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +57 -0
- package/DESIGN.md +1 -1
- package/README.md +26 -44
- package/SHIPPED.md +2 -2
- package/adapters/bob/README.md +1 -1
- package/adapters/claude-code/README.md +17 -12
- package/adapters/openclaude/README.md +1 -1
- package/adapters/opencode/README.md +4 -4
- package/bin/build-driver.mjs +2 -0
- package/bin/geneseed-cli.mjs +17 -0
- package/bin/geneseed-hook.mjs +2 -0
- package/docs/README.md +42 -0
- package/docs/_groups.json +18 -0
- package/docs/concepts/agents.md +44 -0
- package/docs/concepts/collaboration.md +62 -0
- package/docs/concepts/exclusions.md +55 -0
- package/docs/concepts/footprint.md +52 -0
- package/docs/concepts/foreman-mode.md +69 -0
- package/docs/concepts/hooks.md +101 -0
- package/docs/concepts/hosts.md +55 -0
- package/docs/concepts/lsp.md +50 -0
- package/docs/{web → concepts}/memory.md +2 -2
- package/docs/{web → concepts}/notebook.md +2 -2
- package/docs/concepts/rules.md +52 -0
- package/docs/concepts/skills.md +49 -0
- package/docs/concepts/themes.md +50 -0
- package/docs/extending.md +27 -21
- package/docs/guides/autostart.md +70 -0
- package/docs/guides/choose-your-setup.md +120 -0
- package/docs/guides/headless.md +22 -0
- package/docs/guides/install.md +161 -0
- package/docs/guides/mcp.md +195 -0
- package/docs/guides/migrate.md +41 -0
- package/docs/guides/project-context.md +87 -0
- package/docs/guides/run-anywhere.md +45 -0
- package/docs/guides/uninstall.md +51 -0
- package/docs/guides/upgrade.md +65 -0
- package/docs/guides/verify.md +65 -0
- package/docs/guides/wiki.md +69 -0
- package/docs/guides/worktree.md +47 -0
- package/docs/reference/about.md +7 -0
- package/docs/reference/cli.md +7 -0
- package/docs/reference/environment.md +99 -0
- package/docs/reference/glossary.md +33 -0
- package/docs/reference/opencode-plugins.md +131 -0
- package/docs/reference/troubleshooting.md +350 -0
- package/docs/understand/a-day.md +77 -0
- package/docs/understand/enforced-vs-asked.md +64 -0
- package/docs/understand/harness.md +36 -0
- package/docs/understand/on-your-machine.md +76 -0
- package/docs/web-ui.md +1 -1
- package/harness.config.json +1 -1
- package/js/README.md +3 -2
- package/js/build/generate.mjs +12 -1
- package/js/build/source.mjs +6 -0
- package/js/cli-table.json +1 -1
- package/js/hosts/mcp.mjs +1 -1
- package/js/hosts/settings.mjs +13 -1
- package/js/inspect/checks-authoring.mjs +5 -3
- package/js/inspect/doctor.mjs +1 -1
- package/js/inspect/inventory.mjs +1 -1
- package/js/inspect/registry.mjs +20 -3
- package/js/inspect/status.mjs +7 -2
- package/js/lib/node-floor.mjs +30 -0
- package/js/maintain/setup.mjs +109 -21
- package/js/maintain/update.mjs +4 -15
- package/js/ui/cli.mjs +2 -2
- package/js/web/api.mjs +3 -0
- package/js/web/daemon.mjs +52 -0
- package/js/web/docs.mjs +149 -65
- package/js/web/server.mjs +5 -2
- package/package.json +6 -4
- package/registry.json +7 -0
- package/src/AGENT.md.tmpl +4 -0
- package/src/postures/mentor.md +1 -0
- package/src/skills/learn-mode.md +89 -0
- package/src/skills/pipeline.md +2 -2
- package/src/skills/quiz.md +2 -1
- package/src/skills/teach.md +2 -1
- package/themes/_TEMPLATE.json +1 -0
- package/themes/biker.json +1 -0
- package/themes/commentator.json +1 -0
- package/themes/cyberpunk.json +1 -0
- package/themes/gamer.json +1 -0
- package/themes/imperial.json +1 -0
- package/themes/joker.json +1 -0
- package/themes/marvin.json +1 -0
- package/themes/mean.json +1 -0
- package/themes/military.json +1 -0
- package/themes/neutral.json +1 -0
- package/themes/pirate.json +1 -0
- package/themes/sports.json +1 -0
- package/themes/verstappen.json +1 -0
- package/themes/wizard.json +1 -0
- package/web/dist/assets/Activity-C52LEb-2.js +1 -0
- package/web/dist/assets/ActivityDetail-CjNLRvXg.js +1 -0
- package/web/dist/assets/Dashboard-B6_sSCHi.js +2 -0
- package/web/dist/assets/Docs-Dj7BmCSA.js +5 -0
- package/web/dist/assets/{GreenhouseView-D0cbCJ5m.js → GreenhouseView-BALwjQsA.js} +1 -1
- package/web/dist/assets/Installs-BbffDQm3.js +2 -0
- package/web/dist/assets/JournalView-JpAQ8Hqe.js +1 -0
- package/web/dist/assets/Laws-DK7eCWSm.js +3 -0
- package/web/dist/assets/Library-CoamHelE.js +1 -0
- package/web/dist/assets/{Markdown-CkFyfgNf.js → Markdown-qjM2_ofS.js} +5 -5
- package/web/dist/assets/{OperatorHudView-CiAkAkQL.js → OperatorHudView-DVx1HlBx.js} +1 -1
- package/web/dist/assets/Personal-eaXb1zcj.js +1 -0
- package/web/dist/assets/{Tabs-B4HNrrCs.js → Tabs-BmGtt8E2.js} +1 -1
- package/web/dist/assets/api-Dc8f3ca-.js +1 -0
- package/web/dist/assets/drawable-Du_PZrQj.js +1 -0
- package/web/dist/assets/index-Bz_KMRDH.css +1 -0
- package/web/dist/assets/index-CNFH7o55.js +2 -0
- package/web/dist/index.html +3 -2
- package/QUICKSTART.md +0 -50
- package/SETUP.md +0 -1148
- package/docs/web/_groups.json +0 -45
- package/docs/web/about.md +0 -6
- package/docs/web/adapters-claude-code.md +0 -8
- package/docs/web/adapters-opencode-loads.md +0 -8
- package/docs/web/adapters-opencode-spec.md +0 -8
- package/docs/web/adapters-opencode.md +0 -8
- package/docs/web/agents.md +0 -8
- package/docs/web/authoring.md +0 -11
- package/docs/web/autostart.md +0 -9
- package/docs/web/claude-hooks.md +0 -37
- package/docs/web/cli.md +0 -6
- package/docs/web/collaboration.md +0 -27
- package/docs/web/configure-wiki.md +0 -9
- package/docs/web/design.md +0 -7
- package/docs/web/env-knobs.md +0 -9
- package/docs/web/exclusions.md +0 -26
- package/docs/web/first-session.md +0 -28
- package/docs/web/footprint.md +0 -38
- package/docs/web/foreman-mode.md +0 -33
- package/docs/web/glossary.md +0 -6
- package/docs/web/harnesses.md +0 -30
- package/docs/web/headless.md +0 -9
- package/docs/web/ingest-docs.md +0 -9
- package/docs/web/install-paths.md +0 -9
- package/docs/web/install-quick.md +0 -35
- package/docs/web/lsp-overview.md +0 -37
- package/docs/web/mcp-claude-code.md +0 -10
- package/docs/web/mcp-filesystem.md +0 -9
- package/docs/web/mcp-gitlab.md +0 -9
- package/docs/web/mcp-markitdown.md +0 -9
- package/docs/web/mcp-overview.md +0 -34
- package/docs/web/mcp-trouble.md +0 -9
- package/docs/web/mcp-verify.md +0 -9
- package/docs/web/migrate.md +0 -39
- package/docs/web/model.md +0 -20
- package/docs/web/pipelines.md +0 -24
- package/docs/web/plugin-activity.md +0 -23
- package/docs/web/plugin-context.md +0 -26
- package/docs/web/plugin-guard.md +0 -24
- package/docs/web/plugin-learn.md +0 -27
- package/docs/web/plugin-notify.md +0 -24
- package/docs/web/plugin-ponytail.md +0 -23
- package/docs/web/plugin-setup.md +0 -7
- package/docs/web/plugin-workflow.md +0 -25
- package/docs/web/plugins.md +0 -17
- package/docs/web/project-context.md +0 -9
- package/docs/web/rules.md +0 -30
- package/docs/web/run-anywhere.md +0 -9
- package/docs/web/self-improve.md +0 -8
- package/docs/web/setup-choices.md +0 -64
- package/docs/web/skills.md +0 -8
- package/docs/web/themes-author.md +0 -20
- package/docs/web/themes.md +0 -9
- package/docs/web/token-footprint.md +0 -7
- package/docs/web/trouble.md +0 -38
- package/docs/web/upgrade.md +0 -9
- package/docs/web/verify.md +0 -30
- package/docs/web/wiki.md +0 -7
- package/docs/web/worktree.md +0 -10
- package/docs/wiki.md +0 -43
- package/web/dist/assets/Activity-BjVp522q.js +0 -1
- package/web/dist/assets/ActivityDetail-8ep1bspW.js +0 -1
- package/web/dist/assets/Dashboard-OkC_PCH6.js +0 -2
- package/web/dist/assets/Docs-CKPWz00o.js +0 -2
- package/web/dist/assets/Installs-BtGGdoTt.js +0 -2
- package/web/dist/assets/JournalView-Ckl4dmzR.js +0 -1
- package/web/dist/assets/Laws-CLpdRRk8.js +0 -3
- package/web/dist/assets/Library-wPPuKQrI.js +0 -1
- package/web/dist/assets/Personal-D8CnDo9v.js +0 -1
- package/web/dist/assets/drawable-BiwaOo6x.js +0 -1
- package/web/dist/assets/index-C1yil5j1.js +0 -2
- package/web/dist/assets/index-CDPDk2vj.css +0 -1
package/SETUP.md
DELETED
|
@@ -1,1148 +0,0 @@
|
|
|
1
|
-
<div align="center">
|
|
2
|
-
|
|
3
|
-
# 🧬 Geneseed — Setup Guide
|
|
4
|
-
|
|
5
|
-
**From bare repository to a disciplined agent in a few minutes.**
|
|
6
|
-
|
|
7
|
-
[← Back to README](README.md) · [Design](DESIGN.md) · [OpenCode adapter](adapters/opencode/README.md) · [Claude Code adapter](adapters/claude-code/README.md)
|
|
8
|
-
|
|
9
|
-
</div>
|
|
10
|
-
|
|
11
|
-
> **In a hurry?** The 5-minute recommended path is **[QUICKSTART.md](QUICKSTART.md)**.
|
|
12
|
-
> This page is the full reference: every install path, knob, and troubleshooting step.
|
|
13
|
-
|
|
14
|
-
---
|
|
15
|
-
|
|
16
|
-
You pick a **theme** — the voice and vocabulary the harness wears — and an **install mode**;
|
|
17
|
-
the build implants the gene-seed and the agent wakes speaking in that voice. Pick the path
|
|
18
|
-
that matches your tool, then configure and verify. For the conceptual overview see the
|
|
19
|
-
[README](README.md); for OpenCode internals see [adapters/opencode/](adapters/opencode/README.md).
|
|
20
|
-
|
|
21
|
-
## 📋 Prerequisites
|
|
22
|
-
|
|
23
|
-
- **Node ≥ 22.3** — the only hard requirement. Geneseed ships as an npm package with
|
|
24
|
-
**zero dependencies**; `npx geneseed` needs nothing else.
|
|
25
|
-
- **Your agent tool** — OpenCode (recommended), Claude Code, Bob, OpenClaude, or anything
|
|
26
|
-
that reads a root instructions file.
|
|
27
|
-
- *Only for a git checkout:* **git**. Nothing else — a checkout runs the same Node
|
|
28
|
-
entry points the npm package installs.
|
|
29
|
-
- *Optional, for the `ingest` skill:* a document converter — **MarkItDown**, Pandoc,
|
|
30
|
-
or Docling — if you want the agent to read PDFs/Office files (see
|
|
31
|
-
[Reading non-markdown docs](#reading-non-markdown-docs)).
|
|
32
|
-
|
|
33
|
-
### 🟩 One runtime — Node, and nothing else
|
|
34
|
-
|
|
35
|
-
Nothing in this guide needs a second interpreter. Three things are worth stating plainly,
|
|
36
|
-
because each is a live constraint rather than a footnote:
|
|
37
|
-
|
|
38
|
-
- **Every command runs on Node.** There is no full-screen browse panel: `geneseed tui`
|
|
39
|
-
and `geneseed menu` are verbs that say the panel is not here and print the command list
|
|
40
|
-
instead. Bare `geneseed` — from the launchers and from an npm install alike — runs
|
|
41
|
-
`home`, which opens the web console when it can and otherwise prints the command list;
|
|
42
|
-
`geneseed --help` lists every command.
|
|
43
|
-
- **Nothing you install needs an interpreter.** The `token-report` skill is a script
|
|
44
|
-
rather than prose, and it ships as `scripts/token_report.mjs`, run with `node`;
|
|
45
|
-
`daydream` and `herdr` hand their inline code to `node -e`.
|
|
46
|
-
So **every bundle carries** nothing that needs one: no Python file, and no skill that
|
|
47
|
-
shells out to an interpreter — on any host, any theme, either footprint. Three tests
|
|
48
|
-
freeze that, down to a byte-for-byte replay of the report script over seeded
|
|
49
|
-
transcripts for all four hosts.
|
|
50
|
-
- **The self-update commands are for a git checkout.** `upgrade`, `update`, `sync-self`
|
|
51
|
-
and `bootstrap` `git pull` the install's own origin. From an npm install they stop
|
|
52
|
-
before touching anything and name `npm install -g geneseed@latest` instead.
|
|
53
|
-
|
|
54
|
-
One more, in the web console rather than the CLI: the **"browse…" folder picker** would
|
|
55
|
-
open an OS-native dialog on the machine running the daemon, and the server declines to.
|
|
56
|
-
The button reports itself unavailable and the path field beside it stays editable.
|
|
57
|
-
|
|
58
|
-
## 🛣️ Choose your path
|
|
59
|
-
|
|
60
|
-
**Easiest:** `npx geneseed setup` — no clone, nothing installed permanently.
|
|
61
|
-
It runs the same guided wizard as a checkout does: it asks for a theme and an install
|
|
62
|
-
mode, runs the right build, and offers a health check. To keep the command around, put
|
|
63
|
-
it on PATH with `npm install -g geneseed`.
|
|
64
|
-
|
|
65
|
-
**From a clone:** `./geneseed setup` on macOS/Linux, `.\geneseed.cmd setup` on Windows.
|
|
66
|
-
It is the same dependency-free wizard the npx route runs — plain text prompts, every
|
|
67
|
-
console, every OS.
|
|
68
|
-
|
|
69
|
-
**Already installed from a clone, and moving to npm?** `geneseed migrate` re-emits every
|
|
70
|
-
install you already have onto the npm shape in a single all-or-nothing pass, keeping each
|
|
71
|
-
one's own theme, emit, footprint, posture and mode. `--dry-run` prints the plan and
|
|
72
|
-
writes nothing. It **reports rather than rewrites** anything it did not create — your own
|
|
73
|
-
hooks, third-party hooks, and the login autostart entry you hand-wrote. Your old clone
|
|
74
|
-
keeps working for a full release; there is no cliff.
|
|
75
|
-
See [Migrate an existing install](docs/web/migrate.md).
|
|
76
|
-
|
|
77
|
-
As you move through the theme picker the wizard **previews each theme live** — its
|
|
78
|
-
tagline, loaded-sigil, and voice — so you hear the flavour before you choose; once
|
|
79
|
-
you pick, it speaks in that theme's accent through confirm and build, and the
|
|
80
|
-
install ends on the theme's own **banner and benediction**.
|
|
81
|
-
|
|
82
|
-
**Already installed?** Bare **`geneseed`** (a checkout: `./geneseed`, Windows: `.\geneseed.cmd`) opens the
|
|
83
|
-
**web console**, which is where browsing, local edits, rebuilds, memory, status, MCP
|
|
84
|
-
servers and uninstall all live — see [The web console](docs/web-ui.md). `GENESEED_NO_WEB=1`
|
|
85
|
-
suppresses that and prints the command list instead. Uninstall from the CLI is
|
|
86
|
-
`geneseed uninstall --target <repo>` (bare `--target` runs against whichever project
|
|
87
|
-
install the cwd sits in). **`./geneseed bootstrap`** jumps straight to
|
|
88
|
-
update-then-setup; **`./geneseed setup`** straight to the wizard. Prefer to do it by
|
|
89
|
-
hand? Pick a path below.
|
|
90
|
-
|
|
91
|
-
| Path | Use when |
|
|
92
|
-
| --- | --- |
|
|
93
|
-
| [A — OpenCode, global](#path-a--opencode-global-recommended) | **Recommended.** One install, every repo inherits it, nothing committed into projects. |
|
|
94
|
-
| [B — OpenCode, per-repo](#path-b--opencode-per-repo) | You want a committed `.opencode/` layer in one repository. |
|
|
95
|
-
| [C — Claude Code](#path-c--claude-code) | You drive Claude Code and want the lifecycle hooks. |
|
|
96
|
-
| [C′ — OpenClaude](#path-c--openclaude) | You drive OpenClaude, the any-model Claude Code fork. |
|
|
97
|
-
| [D — Any `AGENT.md` tool](#path-d--any-agentmd-tool) | Cursor, Aider, or any tool that reads a root instructions file. |
|
|
98
|
-
| [E — No runtime on the target at all](#path-e--no-runtime-on-the-target-at-all) | The machine that *uses* the harness cannot run Node. |
|
|
99
|
-
|
|
100
|
-
> **Every `geneseed-build …` below is the generator.** `npm install -g geneseed` puts it
|
|
101
|
-
> on your `PATH`; without installing anything, `npx -p geneseed geneseed-build --emit
|
|
102
|
-
> opencode-global` is the same command. From a checkout it is
|
|
103
|
-
> `node bin/build-driver.mjs` with the same flags. Every commit re-emits with it across every
|
|
104
|
-
> theme × host × footprint combination and checks the result with `doctor --all`, on Linux
|
|
105
|
-
> and Windows both. Until 2026-08-17 that output was also compared byte for byte against
|
|
106
|
-
> recordings taken from the Python implementation; those were retired (see the 2.0.0 entry
|
|
107
|
-
> in [CHANGELOG.md](CHANGELOG.md)).
|
|
108
|
-
|
|
109
|
-
---
|
|
110
|
-
|
|
111
|
-
### Path A — OpenCode, global (recommended)
|
|
112
|
-
|
|
113
|
-
Installs the whole harness into OpenCode's config dir; every repo you open inherits it.
|
|
114
|
-
|
|
115
|
-
```
|
|
116
|
-
# from inside the Geneseed folder
|
|
117
|
-
geneseed-build --emit opencode-global # add --theme imperial for the 40k voice
|
|
118
|
-
# GENESEED_HARNESS is optional — the learn plugin auto-locates the in-config memory
|
|
119
|
-
# store. Set it only to pin the location explicitly (and persist it to your rc):
|
|
120
|
-
export GENESEED_HARNESS="$HOME/.config/opencode"
|
|
121
|
-
echo 'export GENESEED_HARNESS="$HOME/.config/opencode"' >> ~/.zshrc
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
**Windows (PowerShell)** — identical, no bash/WSL needed:
|
|
125
|
-
```powershell
|
|
126
|
-
# from inside the Geneseed folder
|
|
127
|
-
geneseed-build --emit opencode-global # add --theme imperial for the 40k voice
|
|
128
|
-
setx GENESEED_HARNESS "$env:USERPROFILE\.config\opencode" # optional; pins the memory store
|
|
129
|
-
```
|
|
130
|
-
On Windows the config dir is the same homedir-relative path,
|
|
131
|
-
`C:\Users\<user>\.config\opencode` — OpenCode uses `~/.config/opencode` on every OS.
|
|
132
|
-
|
|
133
|
-
This writes into `$OPENCODE_CONFIG_DIR` (else `$XDG_CONFIG_HOME/opencode`, else
|
|
134
|
-
`~/.config/opencode`): `AGENT.md`, `agents/`, `skills/<name>/SKILL.md`, a single
|
|
135
|
-
`plugins/` copy, the `memory/` store, and a merged `opencode.json` pointing
|
|
136
|
-
`instructions` at the absolute `AGENT.md`. No `context.json` — the context plugin
|
|
137
|
-
auto-discovers each repo's docs.
|
|
138
|
-
|
|
139
|
-
It is **non-destructive**: a `.geneseed-manifest.json` tracks only the files it owns
|
|
140
|
-
and prunes stale ones on re-emit; your own agents/skills/plugins and the memory store
|
|
141
|
-
are never touched. Full design + checklist:
|
|
142
|
-
[GLOBAL-HARNESS-SPEC.md](adapters/opencode/GLOBAL-HARNESS-SPEC.md).
|
|
143
|
-
|
|
144
|
-
### Path B — OpenCode, per-repo
|
|
145
|
-
|
|
146
|
-
```
|
|
147
|
-
geneseed-build --emit opencode --target /path/to/your-repo
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
Writes the full bundle (`AGENT.md`, `agents/`, `skills/`, `memory/`, `notebook/`)
|
|
151
|
-
plus the OpenCode-native layer (`opencode.json` and `.opencode/{agents,skills,plugins,workflows}`)
|
|
152
|
-
into the target dir. Commit them or not. **Want the bundle in a subfolder?** add `--root`
|
|
153
|
-
so instruction paths resolve from the project root:
|
|
154
|
-
|
|
155
|
-
```
|
|
156
|
-
geneseed-build --emit opencode --out /path/to/repo/Harness --root /path/to/repo
|
|
157
|
-
```
|
|
158
|
-
|
|
159
|
-
Depth, native mapping, and the manual fallback: [adapters/opencode/](adapters/opencode/README.md).
|
|
160
|
-
|
|
161
|
-
### Path C — Claude Code
|
|
162
|
-
|
|
163
|
-
Merge [`adapters/claude-code/settings.json`](adapters/claude-code/settings.json) into
|
|
164
|
-
your repo's `.claude/settings.json` (paths assume the bundle is at the repo root).
|
|
165
|
-
It wires:
|
|
166
|
-
|
|
167
|
-
- **PreToolUse** (matcher `Bash`) — runs `harness git-gate`, a tool-boundary backstop
|
|
168
|
-
for Doctrine `process 5`. The hook inspects the command and forces an `ask` on every
|
|
169
|
-
`git commit` or `git push` (even chained or `-C`-flagged), un-suppressible by a
|
|
170
|
-
one-time "don't ask again". Every other Bash command is deferred to the normal
|
|
171
|
-
permission flow. It is wired only when **Doctrine process 5 itself** is active — build
|
|
172
|
-
with `--doctrines` leaving `process` out, or with `--exclude-rules "process 5"`, and this
|
|
173
|
-
hook is not installed at all. The prompt and the boundary move together by construction:
|
|
174
|
-
the gate is keyed on the rule, not on its pack.
|
|
175
|
-
- **SessionStart** (`startup`/`clear`) — prints `AGENT.md` and injects the project
|
|
176
|
-
context (`harness context`, which auto-discovers the repo's docs);
|
|
177
|
-
- **SessionStart** (`resume`/`compact`) — refreshes the project context only, without
|
|
178
|
-
re-printing the static `AGENT.md`. `compact` matters: auto-compaction summarises away the
|
|
179
|
-
injected context, memory index and notebook TOC, and this re-seeds them;
|
|
180
|
-
- Every gate **ask** appends one line to `notebook/gates.jsonl` in the install (rule and
|
|
181
|
-
timestamp, never the command); `geneseed status` counts them by rule and says when an
|
|
182
|
-
`excludes.json` entry has the gates standing down for the current directory. A defer
|
|
183
|
-
writes nothing. The OpenCode guard plugin writes the same file on every **block**, so
|
|
184
|
-
the count spans every host.
|
|
185
|
-
- **Stop** — runs `harness learn` to capture durable memory. Opt in by setting
|
|
186
|
-
`GENESEED_LLM` (e.g. `claude -p`); unset, it's a harmless no-op. Geneseed never
|
|
187
|
-
embeds an API key.
|
|
188
|
-
- **PreCompact** — runs `harness learn` once more, right before auto-compaction
|
|
189
|
-
summarises the transcript tail that `learn` distils from. Memory is captured before
|
|
190
|
-
the summary; the SessionStart `compact` matcher re-seeds context after it.
|
|
191
|
-
|
|
192
|
-
All the hooks are emitted as one stable path — the **hook shim** at
|
|
193
|
-
`~/.geneseed/bin/geneseed-hook` (`geneseed-hook.cmd` on Windows) — instead of writing
|
|
194
|
-
this machine's runtime and this checkout into your `settings.json`. The shim
|
|
195
|
-
carries those two volatile paths itself, so moving or replacing the clone no longer
|
|
196
|
-
breaks the hooks in every install at once: one `geneseed build` rewrites the shim and
|
|
197
|
-
every install is live again. It is refreshed on every emit, and `geneseed doctor`
|
|
198
|
-
reports it if it was ever stale. `GENESEED_HOME` relocates it.
|
|
199
|
-
|
|
200
|
-
Detail: [adapters/claude-code/](adapters/claude-code/README.md).
|
|
201
|
-
|
|
202
|
-
### Sovereign repos — excluding folders from the global harness
|
|
203
|
-
|
|
204
|
-
Some repos are complete agent harnesses of their own (an Obsidian vault with its
|
|
205
|
-
own laws, hooks and memory conventions). Inside such a repo the global Geneseed
|
|
206
|
-
layer would stack on top of the local one — conflicting doctrine and wasted
|
|
207
|
-
tokens. Exclude the folder instead:
|
|
208
|
-
|
|
209
|
-
harness exclude add ~/Documents/git/Terra
|
|
210
|
-
harness exclude list
|
|
211
|
-
harness exclude remove ~/Documents/git/Terra
|
|
212
|
-
|
|
213
|
-
Inside an excluded folder the global install is fully dormant: the context,
|
|
214
|
-
learn and git-gate hooks exit silently (they check `<config dir>/excludes.json`
|
|
215
|
-
on every call — edits take effect immediately, no re-emit), and the global
|
|
216
|
-
preamble is suppressed natively (Claude: `claudeMdExcludes` written to the
|
|
217
|
-
repo's own `.claude/settings.local.json`, and OpenClaude's in `.openclaude/settings.local.json`;
|
|
218
|
-
Bob: the workspace rules shadow stub;
|
|
219
|
-
OpenCode: the plugins stand down). Everything is reversed by `exclude remove`.
|
|
220
|
-
|
|
221
|
-
Limitation: globally installed skills/subagents remain listed by the host (no
|
|
222
|
-
native per-repo disable exists). A global install emitted later starts with an empty list — re-run
|
|
223
|
-
`harness exclude add` (`exclude list` flags installs that diverge).
|
|
224
|
-
|
|
225
|
-
### Path C′ — OpenClaude
|
|
226
|
-
|
|
227
|
-
```
|
|
228
|
-
geneseed-build --emit openclaude-global # render into ~/.openclaude
|
|
229
|
-
geneseed-build --emit openclaude --out . --root . # per-repo: .openclaude/, committed
|
|
230
|
-
```
|
|
231
|
-
|
|
232
|
-
[OpenClaude](https://openclaude.gitlawb.com/) grew out of the Claude Code codebase, so this
|
|
233
|
-
is Path C with another config dir: the same agents, skills, hook groups and `ask` verdicts.
|
|
234
|
-
It never reads `~/.claude` or a project `.claude/`, so a Claude Code install does not reach
|
|
235
|
-
it. Both installs can live side by side. Two differences:
|
|
236
|
-
|
|
237
|
-
- **The per-repo preamble is `.openclaude/CLAUDE.md`**, not a root file. OpenClaude skips a
|
|
238
|
-
root `CLAUDE.md` whenever the repo has an `AGENTS.md`, and reads `.openclaude/CLAUDE.md`
|
|
239
|
-
always. Hooks go in `.openclaude/settings.local.json` (gitignored) with a
|
|
240
|
-
`claudeMdExcludes` for the global preamble, as on Claude Code.
|
|
241
|
-
- **`$OPENCLAUDE_CONFIG_DIR` relocates the global dir.** It is OpenClaude's own variable.
|
|
242
|
-
MCP servers go in `~/.openclaude.json`, or in `.openclaude.json` inside that dir when it is
|
|
243
|
-
set. Per repo they go in `.mcp.json`.
|
|
244
|
-
|
|
245
|
-
Details in [adapters/openclaude/](adapters/openclaude/README.md).
|
|
246
|
-
|
|
247
|
-
### Path D — Any `AGENT.md` tool
|
|
248
|
-
|
|
249
|
-
```
|
|
250
|
-
geneseed-build # renders the plain bundle to ./Harness
|
|
251
|
-
```
|
|
252
|
-
|
|
253
|
-
Point your tool's instructions/rules setting at `Harness/AGENT.md`. If the tool only
|
|
254
|
-
auto-loads a specific name, rename or symlink (`AGENT.md` → `AGENTS.md` / `CLAUDE.md`).
|
|
255
|
-
The rules work on agent self-discipline alone; the plugins (context, memory) are an
|
|
256
|
-
OpenCode convenience.
|
|
257
|
-
|
|
258
|
-
Three tools on this path read more than the instructions file, by their own docs:
|
|
259
|
-
|
|
260
|
-
- **Codex CLI** auto-loads a repo-root `AGENTS.md` and `~/.codex/AGENTS.md`, and
|
|
261
|
-
discovers skills in `~/.codex/skills` or `.agents/skills`.
|
|
262
|
-
- **Cursor** auto-loads `AGENTS.md` (root and nested) and skills from `.cursor/skills`,
|
|
263
|
-
`.agents/skills` — and, for compatibility, `.claude/skills`, so a Claude project
|
|
264
|
-
install already gives Cursor the skill catalogue.
|
|
265
|
-
- **Gemini CLI** reads `GEMINI.md` by default; set `context.fileName` in its
|
|
266
|
-
`settings.json` to include `AGENTS.md`. Skills load from `.gemini/skills` or
|
|
267
|
-
`.agents/skills`.
|
|
268
|
-
|
|
269
|
-
Copy or symlink the bundle's `skills/` to `.agents/skills/` and all three see it. None
|
|
270
|
-
of these is a wired host yet — what each would take is costed in
|
|
271
|
-
[`docs/candidate-hosts.md`](docs/candidate-hosts.md).
|
|
272
|
-
|
|
273
|
-
### Path E — No runtime on the target at all
|
|
274
|
-
|
|
275
|
-
A maintainer runs it once, on a machine that can run Node:
|
|
276
|
-
|
|
277
|
-
```
|
|
278
|
-
npx geneseed prompt --theme neutral > install-geneseed.md
|
|
279
|
-
```
|
|
280
|
-
|
|
281
|
-
That emits a self-contained prompt that recreates the entire file tree verbatim.
|
|
282
|
-
Paste it into any capable agent on the target machine — nothing to install, no build step.
|
|
283
|
-
Any theme works the same way — substitute its name after `--theme`. The prompt is
|
|
284
|
-
always rendered fresh from `src/`, so it can never drift from the current harness.
|
|
285
|
-
|
|
286
|
-
---
|
|
287
|
-
|
|
288
|
-
## 🎛 Configure
|
|
289
|
-
|
|
290
|
-
### Theme
|
|
291
|
-
|
|
292
|
-
Choose any of the 14 themes in `themes/` — `neutral` (plain), `imperial` (Warhammer 40k),
|
|
293
|
-
`military`, `pirate`, `wizard`, `cyberpunk`, `gamer`, `sports` (play-by-play),
|
|
294
|
-
`biker`, `commentator`, `joker`, `marvin`, `mean`, or `verstappen` — with
|
|
295
|
-
`--theme NAME` (the wizard lists them all with live previews). It is remembered in a
|
|
296
|
-
`.geneseed-theme` marker, so later upgrades keep it. Adding your own is one JSON file
|
|
297
|
-
of voice tokens; `doctor` checks every theme defines the same keys.
|
|
298
|
-
|
|
299
|
-
Adding a new voice token to `themes/_TEMPLATE.json` means all 14 theme files need it
|
|
300
|
-
too, or the parity check fails. `geneseed-build --sync-themes` does the mechanical
|
|
301
|
-
part: it copies any key the template has but a theme is missing into that theme
|
|
302
|
-
(filled with the template's placeholder text), in template order, and prints exactly
|
|
303
|
-
which keys were added so you can restyle them in that theme's voice. It never deletes
|
|
304
|
-
a key a theme has that the template doesn't — those are only reported. The edit is
|
|
305
|
-
surgical (only the inserted lines change; nothing is reformatted), and the exit code
|
|
306
|
-
doubles as a CI drift check: `1` when it had to change files, `0` when every theme was
|
|
307
|
-
already in sync, and `2` when `_TEMPLATE.json` itself is missing or unreadable — the one
|
|
308
|
-
case where a `0` would have meant "in sync" without having checked anything.
|
|
309
|
-
|
|
310
|
-
### Doctrine packs
|
|
311
|
-
|
|
312
|
-
The constitution is three tiers, and only one of them is a choice. The **Ontology** (how the
|
|
313
|
-
agent thinks — Telos, Evidence, Decisions, Conduct) and the nine **Rules** (what it never
|
|
314
|
-
trades away) are always on and cannot be switched off. The **Doctrines** are practices rather
|
|
315
|
-
than principles, and they ship as five packs:
|
|
316
|
-
|
|
317
|
-
| Pack | What it governs |
|
|
318
|
-
| --- | --- |
|
|
319
|
-
| **craft** | how code is written — reuse first, house conventions, docs in the same change, the smallest diff |
|
|
320
|
-
| **rigor** | how work is proven — idempotence, honest tests, cover-and-verify, gates that can actually fail |
|
|
321
|
-
| **ops** | how the machine is driven — tool discovery, commands that return, complete teardowns, restart is not reload |
|
|
322
|
-
| **process** | how a session runs — planning, context economy, docs first, bounded loops, and the consent gate on every commit and push |
|
|
323
|
-
| **comms** | how answers are presented — stable reference codes on tracked items, a diagram or a table only where it earns its place |
|
|
324
|
-
|
|
325
|
-
They are picked **at build time**, once, on the generator — there is no runtime toggle — and
|
|
326
|
-
the default is all five:
|
|
327
|
-
|
|
328
|
-
geneseed-build --doctrines craft,rigor # two packs
|
|
329
|
-
geneseed-build --doctrines none # ontology and the nine Rules only
|
|
330
|
-
geneseed-build # all five (the default)
|
|
331
|
-
|
|
332
|
-
`harness.config.json`'s `doctrines` array sets this checkout's own default, and `doctor`
|
|
333
|
-
refuses one that names a pack the checkout does not ship. Order is fixed by the harness
|
|
334
|
-
(craft → rigor → ops → process → comms) regardless of the order you type.
|
|
335
|
-
|
|
336
|
-
### One rule at a time
|
|
337
|
-
|
|
338
|
-
A pack is coarse: `--doctrines` can only keep all of **process** or none of it.
|
|
339
|
-
`--exclude-rules` is the finer axis, and it takes rule addresses:
|
|
340
|
-
|
|
341
|
-
geneseed-build --exclude-rules "process 7" # keep the pack, drop one rule
|
|
342
|
-
geneseed-build --exclude-rules "process 5,craft 2" # several
|
|
343
|
-
geneseed-build --exclude-rules none # exclude nothing (the default)
|
|
344
|
-
|
|
345
|
-
Both spellings of an address work — `process 7` as the constitution writes it, or `process.7`
|
|
346
|
-
as the console addresses it. The two axes compose: a pack whose every rule is excluded drops
|
|
347
|
-
out of `Active packs:` entirely, so you never get a pack header with nothing under it.
|
|
348
|
-
|
|
349
|
-
An install records what it excluded in a second marker line, `Excluded rules: process 7`,
|
|
350
|
-
written **only when something is excluded** — so a build with the default keeps every byte it
|
|
351
|
-
had before this axis existed. `upgrade`, `rebuild-all` and the web console all read that line
|
|
352
|
-
back and preserve it, exactly as they preserve the pack list.
|
|
353
|
-
|
|
354
|
-
⚠ **`process 5` is special**: excluding it also unwires the commit/push consent hook, because
|
|
355
|
-
the tool boundary is keyed on that rule. That is by design — the prompt and the boundary must
|
|
356
|
-
never disagree — and both the console and the wizard say so before applying it.
|
|
357
|
-
|
|
358
|
-
The web console has the switches: **Constitution → Doctrines**, one per rule, staged locally
|
|
359
|
-
with a single **Apply** that rebuilds the install once.
|
|
360
|
-
|
|
361
|
-
The setup wizard asks too — one *all* / *choose* gate, then a yes/no per pack with its
|
|
362
|
-
one-line description — and it **pre-selects what the install already carries**, read off the
|
|
363
|
-
`Active packs:` marker line in the deployed `AGENT.md`. So re-running the wizard and holding
|
|
364
|
-
Enter cannot silently widen a set you deliberately narrowed.
|
|
365
|
-
|
|
366
|
-
**The whole catalogue always ships.** Every pack file lands under `doctrines/` beside
|
|
367
|
-
`AGENT.md` at both footprints whether or not it was built in, so a rule that cites a pack you
|
|
368
|
-
left out is still readable on disk — only the rendered `AGENT.md` is narrower. `doctor` reports
|
|
369
|
-
such citations as a `[note]`, printed and not counted, because a narrowed build is a
|
|
370
|
-
configuration you chose rather than a defect.
|
|
371
|
-
|
|
372
|
-
⚠ **Turning `process` off also removes the commit/push consent gate.** Doctrine `process 5`
|
|
373
|
-
(*Consent Before Push*) is enforced twice: as prose in `AGENT.md`, and at the tool boundary —
|
|
374
|
-
the `PreToolUse` gate hook on Claude Code and Bob, and the `git commit*` / `git push*`
|
|
375
|
-
permission entries on OpenCode. A build without the `process` pack wires neither, and
|
|
376
|
-
rebuilding an install that had them takes the Claude hook back out of `settings.json`. That is
|
|
377
|
-
deliberate and it is the rule the tiering rests on: **prompt and boundary must never
|
|
378
|
-
disagree.** A gate that stops every command to ask consent for a rule the install did not adopt
|
|
379
|
-
is a gate the agent cannot explain and you did not ask for. Two details worth knowing:
|
|
380
|
-
|
|
381
|
-
- **What stays in every build regardless:** `rm -rf *`, `git push --force*` and `git push -f*`.
|
|
382
|
-
Those are Rule IV's territory — an always-on invariant — not the process pack's.
|
|
383
|
-
- **On OpenCode, an existing `opencode.json` is not stripped.** That file is co-owned, nothing
|
|
384
|
-
on disk records who wrote a given permission entry, and Geneseed will not delete a line you
|
|
385
|
-
might have typed yourself. A pack-off rebuild leaves an already-written `git commit*` in
|
|
386
|
-
place and *reports* it instead. A fresh install has no git gate at all.
|
|
387
|
-
|
|
388
|
-
`process` is the only pack whose removal changes what the machine does rather than only what
|
|
389
|
-
the agent reads — which is why the wizard's blurb for it says so.
|
|
390
|
-
|
|
391
|
-
### Footprint (lean vs full)
|
|
392
|
-
|
|
393
|
-
**Footprint** sets how much of the constitution `AGENT.md` carries *inline* on every turn — a
|
|
394
|
-
token-cost dial, not a change to which Rules apply. Both states keep all Rules in force:
|
|
395
|
-
|
|
396
|
-
- **lean** (default) — Sections 1–2 carry the heading and the authored short form of each Rule
|
|
397
|
-
and each active doctrine rule, then a pointer to the full text. Lighter every turn; the complete
|
|
398
|
-
`laws/universal.md`, `ontology/` and `doctrines/` still ship beside `AGENT.md` and the agent
|
|
399
|
-
reads them on demand (and is told to before acting on secrets, deletion, git history, scope,
|
|
400
|
-
or untrusted content).
|
|
401
|
-
- **full** — Sections 1–2 inline every Rule's and every active doctrine rule's complete text
|
|
402
|
-
*and* rationale. Maximum guidance density; the largest always-loaded block in the harness.
|
|
403
|
-
|
|
404
|
-
**Nothing at lean is truncated — it is written.** Every tier carries a hand-authored short form
|
|
405
|
-
beside its full text: the Ontology (whose four flowing sections would have read as four orphan
|
|
406
|
-
sentences if cut), each Rule, and each doctrine rule. What lean ships is decided by an author
|
|
407
|
-
rather than by where a sentence happens to end — so a short form is judged on whether an agent
|
|
408
|
-
can act on it, which is something a reviewer can see.
|
|
409
|
-
|
|
410
|
-
**Why:** context is scarce and metered. Lean reclaims that budget — and the tokens you
|
|
411
|
-
pay for it — for the task, moving the *rationale* one read away while keeping the rules
|
|
412
|
-
themselves present. **Pros & cons:** full = always-present reasoning (better for smaller
|
|
413
|
-
models, zero indirection) at the highest token cost; lean = cheaper, leaner context every
|
|
414
|
-
turn at the cost of one extra fetch when a rule's nuance matters. Prefer **lean** for long
|
|
415
|
-
sessions, large repos, or cost-sensitive runs; keep **full** when cost is a non-issue or
|
|
416
|
-
you run a smaller model.
|
|
417
|
-
|
|
418
|
-
**Same harness, either way.** Footprint changes neither what the harness *is* nor what it
|
|
419
|
-
can *do*: lean and full emit identical files (same agents, skills, plugins, commands, memory,
|
|
420
|
-
notebook, hooks) and every Rule is present and binding. The only structural difference is
|
|
421
|
-
that a lean install on a global / Claude / Bob / OpenClaude target also ships the standalone
|
|
422
|
-
`laws/universal.md` and `ontology/` (project bundles already carry them, and `doctrines/`
|
|
423
|
-
ships at both footprints on every target); the only behavioural difference is that the
|
|
424
|
-
reasoning loads on demand instead of every turn. Lean is the default; full, with the rationale
|
|
425
|
-
always in front of the model, applies a rule's nuance more reliably on subtle edge cases or
|
|
426
|
-
with a weaker model, and is one flag away.
|
|
427
|
-
|
|
428
|
-
Set it with `--footprint lean|full` (alongside any `--emit`), the **Footprint** toggle in
|
|
429
|
-
the web Settings, the per-harness dropdown in the Harnesses tab, or the setup wizard. It is
|
|
430
|
-
remembered in a `.geneseed-footprint` marker and preserved across every rebuild, on every
|
|
431
|
-
host (OpenCode, Claude Code, Bob, OpenClaude).
|
|
432
|
-
|
|
433
|
-
### Dry-run a build (`validate`)
|
|
434
|
-
|
|
435
|
-
```
|
|
436
|
-
geneseed validate --theme imperial --emit opencode --out /path/to/repo/Harness
|
|
437
|
-
```
|
|
438
|
-
|
|
439
|
-
(It is a verb on the CLI rather than a flag on the generator because it runs `doctor`, and
|
|
440
|
-
the generator is deliberately unable to start a process — `geneseed-build` refuses
|
|
441
|
-
`--validate-only` outright.)
|
|
442
|
-
|
|
443
|
-
Renders and emits the requested `--theme`/`--emit`/`--out`/`--root`/`--footprint`
|
|
444
|
-
combination into a throwaway sandbox — nothing under the real `--out`/`--root` is
|
|
445
|
-
written, no marker files, no settings merge, no install-registry record — then runs
|
|
446
|
-
every doctor-grade check against it (unresolved tokens, dead/non-hermetic links, theme
|
|
447
|
-
parity, authoring gates, AGENT.md table parity). Prints a per-layer file count of what
|
|
448
|
-
would have been written (`-v`/`--verbose` for the full path list) and exits non-zero on
|
|
449
|
-
any problem, `0` when clean. Useful in CI, or before pointing a real deploy at a repo you
|
|
450
|
-
don't want to touch yet.
|
|
451
|
-
|
|
452
|
-
### Project context (usually nothing)
|
|
453
|
-
|
|
454
|
-
On OpenCode the context plugin auto-discovers a repo's docs every session:
|
|
455
|
-
|
|
456
|
-
- **Eager** (injected in full, budget-capped): root `AGENTS.md`/`AGENT.md`/`CLAUDE.md`/
|
|
457
|
-
`.cursorrules`, `README.md`, `CONTRIBUTING.md`.
|
|
458
|
-
- **Lazy** (listed, read on demand): `docs/`, `doc/`, `documentation/`, `architecture/`,
|
|
459
|
-
`adr/`, `ADR/`, monorepo `packages/*/README.md` and `apps/*/README.md`, other root
|
|
460
|
-
`*.md`. `node_modules`, `.git`, `dist`, `build`, `vendor`, `.next`, `target`,
|
|
461
|
-
`.venv`, `__pycache__`, `.opencode`, and `.harness` are never scanned.
|
|
462
|
-
|
|
463
|
-
Override only when the convention doesn't fit — drop a `.harness/context.json` (or
|
|
464
|
-
`./context.json`, or point `$GENESEED_CONTEXT`):
|
|
465
|
-
|
|
466
|
-
```json
|
|
467
|
-
{
|
|
468
|
-
"extend": true,
|
|
469
|
-
"context": [
|
|
470
|
-
{ "path": "docs/house-rules.md", "load": "eager", "description": "Branch policy, DoD." },
|
|
471
|
-
{ "path": "docs/**/*.md", "load": "lazy" },
|
|
472
|
-
{ "path": "internal/secrets.md", "load": "exclude" }
|
|
473
|
-
]
|
|
474
|
-
}
|
|
475
|
-
```
|
|
476
|
-
|
|
477
|
-
`path` is absolute, repo-relative, or a glob; `load` is `eager` | `lazy` | `exclude`;
|
|
478
|
-
`"extend": true` layers the manifest on top of discovery. Schema:
|
|
479
|
-
[GLOBAL-HARNESS-SPEC.md §3](adapters/opencode/GLOBAL-HARNESS-SPEC.md).
|
|
480
|
-
|
|
481
|
-
#### 📌 Worked example — a monorepo's `context.json`
|
|
482
|
-
|
|
483
|
-
The harness stays lean because project knowledge does not go into it — it goes
|
|
484
|
-
into this per-repo manifest, which the context plugin auto-loads at session
|
|
485
|
-
start. A monorepo with docs scattered across packages might write:
|
|
486
|
-
|
|
487
|
-
```json
|
|
488
|
-
{
|
|
489
|
-
"extend": true,
|
|
490
|
-
"context": [
|
|
491
|
-
{ "path": "docs/architecture.md", "load": "eager", "description": "system map" },
|
|
492
|
-
{ "path": "api/README.md", "load": "eager" },
|
|
493
|
-
{ "path": "web/README.md", "load": "eager" }
|
|
494
|
-
]
|
|
495
|
-
}
|
|
496
|
-
```
|
|
497
|
-
|
|
498
|
-
`"extend": true` keeps auto-discovery running (so `README.md`, `AGENT.md`, and
|
|
499
|
-
the rest of the convention still apply) and layers these three eager entries on
|
|
500
|
-
top. Keep the eager list to the few files a new teammate would read first —
|
|
501
|
-
each `eager` entry is injected in full into every session in this repo, so it
|
|
502
|
-
has a permanent token cost; prefer three sharp docs over ten broad ones, and
|
|
503
|
-
reach for `"load": "lazy"` for anything a session should only read on demand.
|
|
504
|
-
|
|
505
|
-
**Self-orientation extras.** The same injected block also carries two best-effort
|
|
506
|
-
lines so the agent starts oriented: the repo's **runnable commands** (targets from
|
|
507
|
-
`Makefile`, `package.json` scripts — with the right runner per lockfile — `justfile`,
|
|
508
|
-
and `Taskfile`), and the session's **current model** (read from the transcript, or
|
|
509
|
-
`GENESEED_MODEL=provider/model` as a fallback). Both degrade silently when absent —
|
|
510
|
-
no commands file, no known model → the line is simply omitted.
|
|
511
|
-
|
|
512
|
-
**Delivery — invisible by default.** The plugin delivers the context by prepending
|
|
513
|
-
it to each outgoing request via OpenCode's `experimental.chat.messages.transform`
|
|
514
|
-
hook: nothing shows in the conversation, and the context survives compaction
|
|
515
|
-
inherently because it is re-sent per request. The hook is experimental — on an
|
|
516
|
-
OpenCode build that lacks it, the plugin notices the first time a request completes
|
|
517
|
-
without it and **falls back automatically** to the classic visible delivery (the
|
|
518
|
-
`PROJECT CONTEXT` block posted as a session message), so no build is ever left
|
|
519
|
-
without context; `GENESEED_DEBUG=1` logs the fallback when it engages. Prefer to
|
|
520
|
-
*see* what the agent received? Set `GENESEED_CONTEXT_VISIBLE=1` (persist with
|
|
521
|
-
`export` in your rc, or `setx` on Windows) to force the visible block up front —
|
|
522
|
-
legacy `GENESEED_CONTEXT_TRANSFORM=0`/`off` does the same, while `=1`, the old
|
|
523
|
-
opt-in, now simply matches the default. To drop injection entirely, set
|
|
524
|
-
`GENESEED_CONTEXT_INJECT=off` and rely on the AGENT.md law.
|
|
525
|
-
|
|
526
|
-
### Wiki — your own knowledge base (optional)
|
|
527
|
-
|
|
528
|
-
If you keep a personal knowledge base on this machine — an Obsidian vault, or any
|
|
529
|
-
folder of interlinked markdown — declare it once in **`wiki.jsonc`** and the agent
|
|
530
|
-
becomes a citizen of it: entry notes load each session (eager) or on demand (lazy),
|
|
531
|
-
and it reads *and writes* notes under your vault's own conventions (AGENT.md §8,
|
|
532
|
-
the `wiki` skill). Unlike `context.json` this is **per machine, not per repo**.
|
|
533
|
-
|
|
534
|
-
The build seeds `wiki.jsonc` beside `AGENT.md` (for a global install:
|
|
535
|
-
`~/.config/opencode/wiki.jsonc`) and never overwrites it. The file is **JSONC** —
|
|
536
|
-
comments and trailing commas are fine — and the seeded stub carries this very
|
|
537
|
-
example commented out, ready to copy and edit in place. Resolution:
|
|
538
|
-
`$GENESEED_WIKI` → `$GENESEED_HARNESS/wiki.jsonc` → beside the installed `AGENT.md`
|
|
539
|
-
(a `wiki.json` from an earlier install is still honoured at each location).
|
|
540
|
-
Fill it in:
|
|
541
|
-
|
|
542
|
-
```json
|
|
543
|
-
{
|
|
544
|
-
"wikis": [{
|
|
545
|
-
"name": "Brain",
|
|
546
|
-
"path": "/home/me/Documents/Brain",
|
|
547
|
-
"description": "my machine-wide knowledge base",
|
|
548
|
-
"entries": [
|
|
549
|
-
{ "path": "ARCHITECTURE.md", "load": "eager", "description": "the root map" },
|
|
550
|
-
{ "path": ".", "load": "lazy" }
|
|
551
|
-
],
|
|
552
|
-
"conventions": "STYLE.md",
|
|
553
|
-
"inbox": "Inbox/",
|
|
554
|
-
"protected": ["Journal/"]
|
|
555
|
-
}]
|
|
556
|
-
}
|
|
557
|
-
```
|
|
558
|
-
|
|
559
|
-
`path` is the vault root (absolute; on Windows use forward slashes —
|
|
560
|
-
`C:/Users/me/Brain`); entry paths are relative to it, with the same `eager`/`lazy`
|
|
561
|
-
semantics as `context.json`. An entry may name a single note **or a folder**: a
|
|
562
|
-
folder applies its mode to every note beneath it (`"."` = the whole vault,
|
|
563
|
-
dot-folders like `.obsidian` skipped), a file entry overrides its folder's mode
|
|
564
|
-
whatever the order, and `"load": "exclude"` prunes a note or folder from the
|
|
565
|
-
listing. The example above is the canonical shape — root index eager, everything
|
|
566
|
-
else on demand. A big vault's lazy listing truncates at 200 lines with a visible
|
|
567
|
-
count (`GENESEED_WIKI_LAZY_LIMIT` adjusts it). `conventions` names the note the agent must read before
|
|
568
|
-
its first write; `inbox` is where it drops notes it cannot confidently file;
|
|
569
|
-
`protected` folders are write-blocked by the guard plugin at the tool boundary
|
|
570
|
-
(`GENESEED_GUARD` modes apply). Several wikis may be declared; an empty `wikis`
|
|
571
|
-
list keeps the feature off. The file may hold private paths — it is host-specific,
|
|
572
|
-
covered by the bundle `.gitignore`, and never committed.
|
|
573
|
-
|
|
574
|
-
On tools without the plugins (plain `AGENT.md`, Claude Code), the same contract
|
|
575
|
-
holds through prose: AGENT.md §8 instructs the agent to read `wiki.jsonc` at session
|
|
576
|
-
start and honour it.
|
|
577
|
-
|
|
578
|
-
### Memory
|
|
579
|
-
|
|
580
|
-
Durable facts live as one-file-per-fact under the memory store, indexed by `MEMORY.md`
|
|
581
|
-
(git-ignored — personal to the machine). The learn plugin writes to the first that
|
|
582
|
-
resolves: `$GENESEED_MEMORY` → `$GENESEED_HARNESS/memory` → `./memory` or
|
|
583
|
-
`./Harness/memory`. For a global install, set `GENESEED_HARNESS` once (Path A).
|
|
584
|
-
Convention: [src/memory/README.md](src/memory/README.md).
|
|
585
|
-
|
|
586
|
-
### Reading non-markdown docs
|
|
587
|
-
|
|
588
|
-
The `ingest` skill teaches the agent to convert a PDF/Word/PPTX/Excel/HTML file or a
|
|
589
|
-
URL to markdown before reading it — discovery and the read-the-docs law only see
|
|
590
|
-
markdown. Install one converter and the skill uses it:
|
|
591
|
-
|
|
592
|
-
- **MarkItDown** (Microsoft) — broadest (`pip install markitdown`), or its MCP server
|
|
593
|
-
(see [MarkItDown via MCP](#markitdown-via-mcp) below — preferred on an
|
|
594
|
-
MCP-capable host: zero per-call install, one low-cost tool);
|
|
595
|
-
- **Pandoc** — excellent for Office/HTML (single binary);
|
|
596
|
-
- **Docling** (IBM) — best for complex tables / scanned PDFs.
|
|
597
|
-
|
|
598
|
-
The skill never installs a converter silently — if none is present it reports which to add.
|
|
599
|
-
|
|
600
|
-
### MCP servers
|
|
601
|
-
|
|
602
|
-
Beyond document conversion, Geneseed ships ready-to-wire MCP server presets —
|
|
603
|
-
**MarkItDown** (below), **GitLab** (two slots, `gitlab` and `gitlab-2`, so you can
|
|
604
|
-
point at two instances), and **Filesystem** — four preset entries in total. Each
|
|
605
|
-
is a *local* server the agent launches on demand: registering one only points the agent
|
|
606
|
-
at a command — *you* install the tool (or let `npx`/`pipx` fetch it) and supply any
|
|
607
|
-
credentials. On OpenCode they live under the `mcp` key of an `opencode.json`, each entry
|
|
608
|
-
shaped:
|
|
609
|
-
|
|
610
|
-
```json
|
|
611
|
-
"<name>": { "type": "local", "command": ["…"], "environment": {}, "enabled": true }
|
|
612
|
-
```
|
|
613
|
-
|
|
614
|
-
> **Never commit a real token.** The presets and the reference
|
|
615
|
-
> [`adapters/opencode/opencode.json`](adapters/opencode/opencode.json) carry **empty**
|
|
616
|
-
> `GITLAB_PERSONAL_ACCESS_TOKEN` placeholders (and a sample filesystem path) — fill them
|
|
617
|
-
> in your own config, never in a tracked file (universal Law I — secrets).
|
|
618
|
-
|
|
619
|
-
**Don't want to hand-edit JSON?** `./geneseed` → **Settings** → **MCP servers** toggles
|
|
620
|
-
any preset into your project or global `opencode.json` — and enables, disables, or
|
|
621
|
-
removes them — for you. The reference config ships MarkItDown enabled and the GitLab /
|
|
622
|
-
Filesystem entries disabled, so a merge never activates a credential-less server: fill
|
|
623
|
-
the blanks, then flip the one(s) you want on.
|
|
624
|
-
|
|
625
|
-
#### MarkItDown via MCP
|
|
626
|
-
|
|
627
|
-
Wire Microsoft's MarkItDown in as a **local MCP server** so the agent can convert
|
|
628
|
-
PDF / Word / Excel / PowerPoint / HTML → Markdown on demand, exposing a single tool
|
|
629
|
-
`convert_to_markdown(uri)` (`uri` accepts `file:`, `http:`, `https:`, or `data:`).
|
|
630
|
-
The server runs locally and, once cached, does not hit PyPI again.
|
|
631
|
-
|
|
632
|
-
> **A config entry alone does nothing.** A `local` MCP server is just a command your
|
|
633
|
-
> agent launches — if that command isn't on PATH in the shell the agent starts from, the
|
|
634
|
-
> server still *appears* in the list but never connects ("shown but not working"). The
|
|
635
|
-
> `uvx` form below is the zero-install way to guarantee it resolves.
|
|
636
|
-
|
|
637
|
-
**1. Make the command resolve.** Pick one:
|
|
638
|
-
|
|
639
|
-
- **`uvx` (recommended, zero-install).** If you have [uv](https://docs.astral.sh/uv/)
|
|
640
|
-
(`uvx` on PATH), nothing to install — `uvx markitdown-mcp` fetches and caches the
|
|
641
|
-
server on first call. This is the command the reference config and the harness toggle
|
|
642
|
-
now use.
|
|
643
|
-
- **`pipx` (pinned install).** No uv? `pipx install markitdown-mcp` puts a
|
|
644
|
-
`markitdown-mcp` binary on PATH; then use `"command": ["markitdown-mcp"]` instead.
|
|
645
|
-
Verify with `markitdown-mcp --help`.
|
|
646
|
-
|
|
647
|
-
```
|
|
648
|
-
# uv route (recommended) — confirm it resolves:
|
|
649
|
-
uvx markitdown-mcp --help
|
|
650
|
-
# pipx route — only if you don't have uv:
|
|
651
|
-
brew install pipx && pipx ensurepath # macOS; Debian/Ubuntu: sudo apt install pipx && pipx ensurepath
|
|
652
|
-
pipx install markitdown-mcp && markitdown-mcp --help
|
|
653
|
-
```
|
|
654
|
-
|
|
655
|
-
Optional OCR / image / audio extras (needed for scanned/image-only PDFs, which
|
|
656
|
-
otherwise return empty): `uvx --with "markitdown[all]" markitdown-mcp` for the uv route,
|
|
657
|
-
or `pipx inject markitdown-mcp "markitdown[all]"` for the pipx route (same venv).
|
|
658
|
-
|
|
659
|
-
**2. Corporate TLS (only on a network with SSL inspection).** uv ships its own root CAs
|
|
660
|
-
and ignores the OS trust store, so a proxy's internal CA fails with `invalid peer
|
|
661
|
-
certificate: UnknownIssuer`. Point uv at the OS trust store — don't disable verification:
|
|
662
|
-
|
|
663
|
-
```
|
|
664
|
-
echo 'export UV_SYSTEM_CERTS=true' >> ~/.zshrc && source ~/.zshrc # older uv: UV_NATIVE_TLS=true
|
|
665
|
-
# fallback: export SSL_CERT_FILE=/path/to/corporate-root-ca.pem
|
|
666
|
-
```
|
|
667
|
-
|
|
668
|
-
**3. Register it in your host's MCP config** — add the server entry to the file your
|
|
669
|
-
agent reads, alongside any servers you already have:
|
|
670
|
-
|
|
671
|
-
<!--harness:opencode-->
|
|
672
|
-
On OpenCode that's `opencode.json` (global `~/.config/opencode/opencode.json`, the
|
|
673
|
-
`.jsonc` variant if you keep one — the file OpenCode reads — or per-repo), under the
|
|
674
|
-
`mcp` key. Geneseed's
|
|
675
|
-
[`adapters/opencode/opencode.json`](adapters/opencode/opencode.json) already carries
|
|
676
|
-
this block:
|
|
677
|
-
|
|
678
|
-
```json
|
|
679
|
-
{
|
|
680
|
-
"$schema": "https://opencode.ai/config.json",
|
|
681
|
-
"mcp": {
|
|
682
|
-
"markitdown": { "type": "local", "command": ["uvx", "markitdown-mcp"], "enabled": true }
|
|
683
|
-
}
|
|
684
|
-
}
|
|
685
|
-
```
|
|
686
|
-
|
|
687
|
-
On the pipx route, swap the command to `["markitdown-mcp"]`. Prefer not to hand-edit
|
|
688
|
-
JSON? `./geneseed` → **Settings** → **MCP servers** toggles this exact block in for you.
|
|
689
|
-
<!--/harness-->
|
|
690
|
-
<!--harness:claude-->
|
|
691
|
-
On Claude Code that's `.mcp.json` under `mcpServers`:
|
|
692
|
-
|
|
693
|
-
```json
|
|
694
|
-
{ "mcpServers": { "markitdown": { "command": "uvx", "args": ["markitdown-mcp"] } } }
|
|
695
|
-
```
|
|
696
|
-
|
|
697
|
-
See the **Claude Code** section for the GitLab / Filesystem shapes.
|
|
698
|
-
<!--/harness-->
|
|
699
|
-
|
|
700
|
-
**4. Verify.** Restart your agent; its MCP list should show `markitdown` **connected**
|
|
701
|
-
(not just listed). The `ingest` skill auto-prefers an MCP
|
|
702
|
-
converter when one is exposed,
|
|
703
|
-
so a prompt like *"convert file:///path/to/spec.pdf to markdown"* now just works. Still
|
|
704
|
-
not connecting? See [MCP server won't connect](#mcp-server-wont-connect) below.
|
|
705
|
-
|
|
706
|
-
#### GitLab (one entry per instance)
|
|
707
|
-
|
|
708
|
-
Wire GitLab in via [`@zereight/mcp-gitlab`](https://github.com/zereight/gitlab-mcp) —
|
|
709
|
-
repo, merge-request, issue, and CI tools over the GitLab API, run through `npx` (nothing
|
|
710
|
-
installed globally; the first run fetches it). It is self-hosted ready, so the same
|
|
711
|
-
command serves gitlab.com and any private instance.
|
|
712
|
-
|
|
713
|
-
**1. Mint a Personal Access Token** on *each* instance — User Settings → Access Tokens,
|
|
714
|
-
scopes `api` and `read_repository`. Treat it like a password.
|
|
715
|
-
|
|
716
|
-
**2. Register one entry per instance** — same command, different `GITLAB_API_URL`
|
|
717
|
-
and token. Two instances (e.g. gitlab.com plus a self-hosted server) → two entries.
|
|
718
|
-
The MCP screen ships a one-click row for the **first** entry only; a second instance is a
|
|
719
|
-
hand-added copy of that block, which is all it ever was:
|
|
720
|
-
|
|
721
|
-
<!--harness:opencode-->
|
|
722
|
-
On OpenCode, under the `mcp` key of `opencode.json`:
|
|
723
|
-
|
|
724
|
-
```json
|
|
725
|
-
{
|
|
726
|
-
"mcp": {
|
|
727
|
-
"gitlab": {
|
|
728
|
-
"type": "local",
|
|
729
|
-
"command": ["npx", "-y", "@zereight/mcp-gitlab"],
|
|
730
|
-
"environment": {
|
|
731
|
-
"GITLAB_PERSONAL_ACCESS_TOKEN": "glpat-…",
|
|
732
|
-
"GITLAB_API_URL": "https://gitlab.com/api/v4"
|
|
733
|
-
},
|
|
734
|
-
"enabled": true
|
|
735
|
-
},
|
|
736
|
-
"gitlab-2": {
|
|
737
|
-
"type": "local",
|
|
738
|
-
"command": ["npx", "-y", "@zereight/mcp-gitlab"],
|
|
739
|
-
"environment": {
|
|
740
|
-
"GITLAB_PERSONAL_ACCESS_TOKEN": "glpat-…",
|
|
741
|
-
"GITLAB_API_URL": "https://gitlab.example.com/api/v4"
|
|
742
|
-
},
|
|
743
|
-
"enabled": true
|
|
744
|
-
}
|
|
745
|
-
}
|
|
746
|
-
}
|
|
747
|
-
```
|
|
748
|
-
<!--/harness-->
|
|
749
|
-
<!--harness:claude-->
|
|
750
|
-
On Claude Code, under `mcpServers` in `.mcp.json` — same command, but `env` (not
|
|
751
|
-
`environment`) and `command` + `args` split. See the **Claude Code** section for the
|
|
752
|
-
exact block; add one `mcpServers` entry per instance.
|
|
753
|
-
<!--/harness-->
|
|
754
|
-
|
|
755
|
-
The entry key is just a label — name them `gitlab` / `gitlab-2`, or after each instance
|
|
756
|
-
(`gitlab`, `gitlab-acme`). What separates the two is the `GITLAB_API_URL` + token pair;
|
|
757
|
-
keep the `/api/v4` suffix on the URL.
|
|
758
|
-
|
|
759
|
-
**Don't know where this file lives?** Run `geneseed web`, open **Harnesses**, and expand an
|
|
760
|
-
active install — each MCP target prints the full path of the config file it writes, right
|
|
761
|
-
above its server rows. That is the file the token and the URL go into. From the terminal,
|
|
762
|
-
`geneseed mcp` prints the same paths without starting anything.
|
|
763
|
-
|
|
764
|
-
#### Filesystem
|
|
765
|
-
|
|
766
|
-
Give the agent scoped file access via
|
|
767
|
-
[`@modelcontextprotocol/server-filesystem`](https://github.com/modelcontextprotocol/servers/tree/main/src/filesystem),
|
|
768
|
-
also through `npx`. The **allowed directories are command-line arguments** — the server
|
|
769
|
-
can touch *only* the paths you list, so grant the narrowest set that works:
|
|
770
|
-
|
|
771
|
-
<!--harness:opencode-->
|
|
772
|
-
On OpenCode, under the `mcp` key of `opencode.json`:
|
|
773
|
-
|
|
774
|
-
```json
|
|
775
|
-
{
|
|
776
|
-
"mcp": {
|
|
777
|
-
"filesystem": {
|
|
778
|
-
"type": "local",
|
|
779
|
-
"command": [
|
|
780
|
-
"npx", "-y", "@modelcontextprotocol/server-filesystem",
|
|
781
|
-
"/path/to/project", "/path/to/another/allowed/dir"
|
|
782
|
-
],
|
|
783
|
-
"enabled": true
|
|
784
|
-
}
|
|
785
|
-
}
|
|
786
|
-
}
|
|
787
|
-
```
|
|
788
|
-
<!--/harness-->
|
|
789
|
-
<!--harness:claude-->
|
|
790
|
-
On Claude Code, under `mcpServers` in `.mcp.json` (`command` + `args` split):
|
|
791
|
-
|
|
792
|
-
```json
|
|
793
|
-
{ "mcpServers": { "filesystem": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/project"] } } }
|
|
794
|
-
```
|
|
795
|
-
<!--/harness-->
|
|
796
|
-
|
|
797
|
-
> **Replace the placeholder.** The reference config and the harness toggle ship the
|
|
798
|
-
> literal arg `/path/to/allowed/dir`. Enabling the server without swapping that for a
|
|
799
|
-
> real path leaves it running but able to touch nothing — the classic "filesystem MCP
|
|
800
|
-
> sees nothing." Edit the path(s) before (or right after) you flip it on.
|
|
801
|
-
|
|
802
|
-
> **Least privilege.** Prefer the narrowest set of dirs the task needs over `$HOME` or
|
|
803
|
-
> `/` — the server refuses any path outside them, and a broad grant lets the agent reach
|
|
804
|
-
> everything under it.
|
|
805
|
-
|
|
806
|
-
#### Claude Code
|
|
807
|
-
|
|
808
|
-
Claude Code reads the same servers from a `.mcp.json` `mcpServers` map — note the key is
|
|
809
|
-
`env` (not `environment`) and the command and its args are split into `command` +
|
|
810
|
-
`args`:
|
|
811
|
-
|
|
812
|
-
```json
|
|
813
|
-
{
|
|
814
|
-
"mcpServers": {
|
|
815
|
-
"gitlab": {
|
|
816
|
-
"command": "npx",
|
|
817
|
-
"args": ["-y", "@zereight/mcp-gitlab"],
|
|
818
|
-
"env": {
|
|
819
|
-
"GITLAB_PERSONAL_ACCESS_TOKEN": "glpat-…",
|
|
820
|
-
"GITLAB_API_URL": "https://gitlab.com/api/v4"
|
|
821
|
-
}
|
|
822
|
-
},
|
|
823
|
-
"filesystem": {
|
|
824
|
-
"command": "npx",
|
|
825
|
-
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/allowed/dir"]
|
|
826
|
-
},
|
|
827
|
-
"markitdown": { "command": "uvx", "args": ["markitdown-mcp"] }
|
|
828
|
-
}
|
|
829
|
-
}
|
|
830
|
-
```
|
|
831
|
-
|
|
832
|
-
Register it with `claude mcp add` or by editing `.mcp.json` directly; the same
|
|
833
|
-
token-safety rule applies.
|
|
834
|
-
|
|
835
|
-
#### Verify
|
|
836
|
-
|
|
837
|
-
Restart your agent.
|
|
838
|
-
<!--harness:opencode-->
|
|
839
|
-
On OpenCode, `opencode mcp` lists each server and whether it **connected**.
|
|
840
|
-
<!--/harness-->
|
|
841
|
-
<!--harness:claude-->
|
|
842
|
-
On Claude Code, `/mcp` lists each server and whether it connected.
|
|
843
|
-
<!--/harness-->
|
|
844
|
-
Listed ≠ working — a `local` server
|
|
845
|
-
appears in the list whether or not its command actually launches.
|
|
846
|
-
|
|
847
|
-
#### MCP server won't connect
|
|
848
|
-
|
|
849
|
-
A `local` MCP entry is just a command OpenCode/Claude Code runs. If it's listed but
|
|
850
|
-
not connected, walk these in order:
|
|
851
|
-
|
|
852
|
-
1. **Does the command resolve?** Run the exact command from a fresh terminal —
|
|
853
|
-
`uvx markitdown-mcp --help`, `npx -y @modelcontextprotocol/server-filesystem --help`.
|
|
854
|
-
"command not found" means the binary isn't on PATH in the shell your agent launches
|
|
855
|
-
from. Fix: use the `uvx`/`npx` zero-install form (these only need uv / Node), or
|
|
856
|
-
install the tool and point at the absolute path. This is the #1 cause of
|
|
857
|
-
"shown but not working" for **markitdown** (no `markitdown-mcp` on PATH, no pipx).
|
|
858
|
-
2. **Filesystem sees nothing?** The allowed-dir arg is still the placeholder
|
|
859
|
-
`/path/to/allowed/dir`, or points somewhere that doesn't exist. Swap in a real path.
|
|
860
|
-
3. **GitLab won't connect?** Almost always a missing / over-scoped token or the wrong
|
|
861
|
-
`GITLAB_API_URL` — keep the `/api/v4` suffix.
|
|
862
|
-
<!--harness:opencode-->
|
|
863
|
-
4. **Right file?** OpenCode reads `opencode.jsonc` if present, else `opencode.json`, at
|
|
864
|
-
the project root and `~/.config/opencode/`. Editing the wrong one is silent. Use
|
|
865
|
-
`./geneseed` → **Settings** → **MCP servers** to write to the file OpenCode actually reads.
|
|
866
|
-
<!--/harness-->
|
|
867
|
-
<!--harness:claude-->
|
|
868
|
-
4. **Right file?** Claude Code reads `.mcp.json` (project) and the `mcpServers` block in
|
|
869
|
-
`~/.claude.json` / settings. Editing the wrong one is silent — `claude mcp list`
|
|
870
|
-
shows which servers actually loaded.
|
|
871
|
-
<!--/harness-->
|
|
872
|
-
|
|
873
|
-
### Environment knobs
|
|
874
|
-
|
|
875
|
-
| Variable | Used by | Effect |
|
|
876
|
-
| --- | --- | --- |
|
|
877
|
-
| `GENESEED_HOME` | emit / hooks | dir holding the hook shim `bin/geneseed-hook` (default: `~/.geneseed`). Change it and re-run the build, so emitted hooks point at the new location |
|
|
878
|
-
| `GENESEED_HARNESS` | learn plugin | base whose `memory/` the plugin writes to (optional — the plugin auto-locates the in-config store; set to pin it) |
|
|
879
|
-
| `GENESEED_MEMORY` | learn plugin / CLI | explicit memory dir (overrides the above) |
|
|
880
|
-
| `GENESEED_CONTEXT` | context plugin / CLI | explicit `context.json` path |
|
|
881
|
-
| `GENESEED_WIKI` | context + guard plugins | explicit `wiki.jsonc` path (default: `$GENESEED_HARNESS/wiki.jsonc`, else beside the installed `AGENT.md`) |
|
|
882
|
-
| `GENESEED_ROOT` | `harness context` | repo root to discover docs from (default: cwd) |
|
|
883
|
-
| `GENESEED_MODEL` | learn + context plugins | `provider/model` fallback if the session model can't be read (learn distils with it; context shows it in the self-awareness line) |
|
|
884
|
-
| `GENESEED_LLM` | `harness learn` (Claude) | model CLI for distillation, e.g. `claude -p` |
|
|
885
|
-
| `GENESEED_EMIT` | `geneseed upgrade` | `opencode-global` \| `opencode` \| unset (plain bundle) |
|
|
886
|
-
| `GENESEED_OUT` / `GENESEED_ROOT` | `geneseed upgrade` | bundle / project-root locations |
|
|
887
|
-
| `GENESEED_DEBUG` | context + notify + ponytail plugins | `1` re-enables discovery/inject logs (context), decision/delivery logs (notify), and level-switch logs (ponytail) |
|
|
888
|
-
| `GENESEED_CONTEXT_INJECT` | context plugin | `off` disables the injected block (rely on the AGENT.md law) |
|
|
889
|
-
| `GENESEED_EAGER_FILE_KB` / `GENESEED_EAGER_TOTAL_KB` | context plugin | per-file / total eager injection budget (default 16 / 48) |
|
|
890
|
-
| `GENESEED_LAZY_HEADINGS` | context plugin | cap on lazy-file heading reads per session (default 64) |
|
|
891
|
-
| `GENESEED_WIKI_LAZY_LIMIT` | context plugin | cap on lazy notes LISTED per wiki per session (default 200; beyond it the listing truncates with a count) |
|
|
892
|
-
| `GENESEED_CONTEXT_VISIBLE` | context plugin | `1` shows the classic visible `PROJECT CONTEXT` block instead of the invisible per-request delivery (see [Project context](#project-context-usually-nothing)) |
|
|
893
|
-
| `GENESEED_CONTEXT_TRANSFORM` | context plugin | legacy — `0`/`off` forces the visible delivery (same as `GENESEED_CONTEXT_VISIBLE=1`); `1` matches the default |
|
|
894
|
-
| `GENESEED_LEARN_DEBOUNCE_MS` | learn plugin | quiet period before distilling (default 60000) |
|
|
895
|
-
| `GENESEED_GUARD` | guard plugin | `warn` downgrades blocks to warnings; `off` disables the safety guard |
|
|
896
|
-
| `GENESEED_WORKFLOWS_DIR` | workflow plugin | override the directory the `workflow` tool reads saved scripts from |
|
|
897
|
-
| `GENESEED_NOTIFY` | notify plugin | `off` disables end-of-run desktop notifications |
|
|
898
|
-
| `GENESEED_NOTIFY_MIN_SECONDS` | notify plugin | minimum turn length, in seconds, before notifying (default 30; `0` = every turn) |
|
|
899
|
-
| `GENESEED_NOTIFY_TITLE` | notify plugin | override the notification title (default `Geneseed`) |
|
|
900
|
-
| `GENESEED_PONYTAIL` | ponytail plugin | default minimal-code level for new installs: `lite` \| `full` \| `ultra` \| `off` (default `off`; switch live with `/ponytail <level>`) |
|
|
901
|
-
| `GENESEED_PRIMARY` | `geneseed-build` | `1` also emits the primary orchestrator agent |
|
|
902
|
-
| `GENESEED_COMMANDS` | `geneseed-build` | `1` also emits the `/slash` command layer |
|
|
903
|
-
| `GENESEED_TUI_ASCII` / `GENESEED_TUI_PLAIN` | terminal output | force pure-ASCII / drop emoji + animation in what the CLI prints |
|
|
904
|
-
| `GENESEED_NO_ANIM` | install animation | disable the themed install animation |
|
|
905
|
-
| `GENESEED_LOG` | `geneseed upgrade` | override the install/upgrade log path |
|
|
906
|
-
| `GENESEED_NET_TIMEOUT` | `upgrade` | seconds before download attempts give up (default 20, floor 5) |
|
|
907
|
-
| `GENESEED_NO_WEB` | `home` | `1` disables the web-first default of bare `geneseed` — it prints the command list instead |
|
|
908
|
-
| `GENESEED_STACK_GLOBAL` | context hook | `1` disables project-bypasses-global: a project install of the same host no longer makes the global install's hook stand down, so both inject |
|
|
909
|
-
| `OPENCODE_CONFIG_DIR` / `XDG_CONFIG_HOME` | global emit | where the global install is written |
|
|
910
|
-
| `OPENCLAUDE_CONFIG_DIR` | `openclaude-global` emit | OpenClaude's own config dir variable (default `~/.openclaude`); also moves `.openclaude.json` |
|
|
911
|
-
| `OPENCODE_DISABLE_LSP_DOWNLOAD` | OpenCode (LSP) | `true` stops OpenCode auto-downloading built-in language servers (typescript, pyright, jdtls) — set it on air-gapped machines and pre-install each server yourself |
|
|
912
|
-
|
|
913
|
-
---
|
|
914
|
-
|
|
915
|
-
## ✅ Verify it works
|
|
916
|
-
|
|
917
|
-
1. **Sigil** — the agent's first reply opens with the readiness line (the `✅`/`🧬`
|
|
918
|
-
sigil for neutral/imperial). If it's missing, the instructions aren't pointed at
|
|
919
|
-
`AGENT.md`.
|
|
920
|
-
2. **Context (OpenCode)** — start a session; with `GENESEED_DEBUG=1` the context
|
|
921
|
-
plugin logs what it discovered and injected.
|
|
922
|
-
3. **Memory (OpenCode)** — do a little work and end the session; after the debounce
|
|
923
|
-
the learn plugin logs `wrote N memory file(s)` or a skip reason to stderr. Total
|
|
924
|
-
silence means it didn't load — re-check the filename, `.js` extension, and that it
|
|
925
|
-
sits in the plugins dir.
|
|
926
|
-
4. **Harness health** — `geneseed doctor` should print `ok` (`npx geneseed doctor` without
|
|
927
|
-
installing). From a checkout, `node bin/geneseed-cli.mjs doctor` runs the same checks.
|
|
928
|
-
To run the full suite the way CI does: `node --test "tests/**/*.test.mjs"`.
|
|
929
|
-
|
|
930
|
-
Browsing agents, skills and laws, and running build/doctor/diff without retyping a
|
|
931
|
-
command, is what the web console is for — bare `./geneseed` opens it.
|
|
932
|
-
|
|
933
|
-
## 🚀 Run `geneseed` from anywhere
|
|
934
|
-
|
|
935
|
-
**From npm this is already done.** `npm install -g geneseed` puts `geneseed`,
|
|
936
|
-
`geneseed-hook` and `geneseed-build` on your `PATH` through npm's own bin linking; there
|
|
937
|
-
is nothing to link and `geneseed link` is not needed. The rest of this section is for a
|
|
938
|
-
git checkout.
|
|
939
|
-
|
|
940
|
-
By default you invoke the launcher as `./geneseed` from inside the repo. To call it
|
|
941
|
-
like any other command — plain `geneseed` from any directory — put it on your `PATH`:
|
|
942
|
-
|
|
943
|
-
```
|
|
944
|
-
./geneseed link # a launcher shim in ~/.local/bin (no sudo); pass a dir to override
|
|
945
|
-
./geneseed link /usr/local/bin # e.g. a system-wide bin dir (may prompt for sudo)
|
|
946
|
-
```
|
|
947
|
-
|
|
948
|
-
(Or, in the web console: **Settings** → the Maintenance card's PATH link / unlink.)
|
|
949
|
-
|
|
950
|
-
`link` writes a small `#!/bin/sh` shim that runs this checkout by absolute path, and
|
|
951
|
-
tells you whether the target dir is on your `PATH` (and, if not, the one line to add
|
|
952
|
-
it). The shim names this checkout's CLI entry point by absolute path, so it finds the
|
|
953
|
-
harness no matter where the shim itself lives — the same shape the Windows arm has
|
|
954
|
-
always used. Once it's on `PATH`, drop the `./`:
|
|
955
|
-
|
|
956
|
-
```
|
|
957
|
-
geneseed # the web console (else the command list), from any directory
|
|
958
|
-
geneseed build # …and every subcommand
|
|
959
|
-
```
|
|
960
|
-
|
|
961
|
-
Remove it with `./geneseed unlink` (it clears the `geneseed` shims it wrote — and any
|
|
962
|
-
symlink an older version left — from `PATH` and the common bin dirs; a `geneseed` it
|
|
963
|
-
did not write is left alone). Prefer a shell function? Add one to your rc instead —
|
|
964
|
-
it does the same job:
|
|
965
|
-
|
|
966
|
-
```
|
|
967
|
-
echo 'geneseed() { "'"$PWD"'/geneseed" "$@"; }' >> ~/.zshrc # or ~/.bashrc
|
|
968
|
-
```
|
|
969
|
-
|
|
970
|
-
**Windows** — use the native launcher `geneseed.cmd`, which routes to the same Node CLI with
|
|
971
|
-
no bash. PowerShell runs a `.cmd` directly, so it is the PowerShell spelling too:
|
|
972
|
-
|
|
973
|
-
```powershell
|
|
974
|
-
.\geneseed.cmd setup
|
|
975
|
-
.\geneseed.cmd link # writes a geneseed.cmd shim into %LOCALAPPDATA%\Geneseed\bin
|
|
976
|
-
# and adds that dir to your user PATH (no admin / symlink needed)
|
|
977
|
-
```
|
|
978
|
-
|
|
979
|
-
Open a new terminal after `link`, then call `geneseed` from any directory. Remove it
|
|
980
|
-
again with `.\geneseed.cmd unlink`.
|
|
981
|
-
|
|
982
|
-
## 🔌 Start the web UI at login
|
|
983
|
-
|
|
984
|
-
The web UI is the only long-running Geneseed process. `geneseed web **start**`
|
|
985
|
-
spawns a **detached daemon** on `127.0.0.1:4747` and returns immediately, so a login
|
|
986
|
-
hook that runs `geneseed web start --no-browser` once — no browser tab — leaves the
|
|
987
|
-
UI ready whenever you open [http://127.0.0.1:4747](http://127.0.0.1:4747). It is
|
|
988
|
-
**per-user and per-machine**: each laptop runs its own daemon on its own loopback, so
|
|
989
|
-
Windows and macOS are set up independently and never collide. The daemon is a
|
|
990
|
-
singleton — a second `start` just no-ops — so re-running it (or logging in twice) is
|
|
991
|
-
harmless.
|
|
992
|
-
|
|
993
|
-
> **Use `web start`, not bare `web`, in every launcher below.** Without the
|
|
994
|
-
> `start` action the server runs in the **foreground** and writes no
|
|
995
|
-
> `.geneseed-web.json` record, so it becomes invisible to `web stop`, `web restart`
|
|
996
|
-
> and `web status` — they report "no live server" while it keeps serving, and a
|
|
997
|
-
> `restart` will orphan a second daemon that cannot bind the taken port. Recovering
|
|
998
|
-
> then means finding it by port and killing it by hand.
|
|
999
|
-
|
|
1000
|
-
> **These are files YOU create, and Geneseed never writes one.** Nothing in this project
|
|
1001
|
-
> has ever created a Startup entry or a LaunchAgent, and nothing ever edits one — including
|
|
1002
|
-
> `geneseed migrate`, which detects a login item still naming an old checkout, prints the
|
|
1003
|
-
> path and the line to put there, and leaves the file alone. It is your login
|
|
1004
|
-
> configuration; deleting the file is the only uninstall it has.
|
|
1005
|
-
|
|
1006
|
-
**Windows** — drop a hidden VBS launcher in the Startup folder (runs at login, no
|
|
1007
|
-
console flash, removed by deleting the file). Open the folder with **Win+R** →
|
|
1008
|
-
`shell:startup`, then create `geneseed-web.vbs`:
|
|
1009
|
-
|
|
1010
|
-
```vbs
|
|
1011
|
-
' geneseed-web.vbs — start the Geneseed web daemon at login (hidden, no browser).
|
|
1012
|
-
CreateObject("WScript.Shell").Run "cmd /c ""%LOCALAPPDATA%\Geneseed\bin\geneseed.cmd"" web start --no-browser", 0, False
|
|
1013
|
-
```
|
|
1014
|
-
|
|
1015
|
-
Expand `%LOCALAPPDATA%` to its real path (e.g. `C:\Users\you\AppData\Local`) — VBS
|
|
1016
|
-
does not expand environment variables inside a string. **Disable** by deleting the
|
|
1017
|
-
file. Prefer a scheduled task (runs hidden, can restart on failure)? Use:
|
|
1018
|
-
|
|
1019
|
-
```powershell
|
|
1020
|
-
schtasks /Create /TN "Geneseed Web" /SC ONLOGON /TR "\"%LOCALAPPDATA%\Geneseed\bin\geneseed.cmd\" web start --no-browser" /RL LIMITED /F
|
|
1021
|
-
schtasks /Delete /TN "Geneseed Web" /F # to remove
|
|
1022
|
-
```
|
|
1023
|
-
|
|
1024
|
-
**macOS** — the launcher is the `geneseed` shim that `./geneseed link` writes (default
|
|
1025
|
-
`~/.local/bin/geneseed`). Use a **LaunchAgent** with `RunAtLoad` — and **no**
|
|
1026
|
-
`KeepAlive`, because the launcher exits after spawning the detached daemon (the
|
|
1027
|
-
daemon runs in its own session and survives). Write
|
|
1028
|
-
`~/Library/LaunchAgents/dev.geneseed.web.plist`:
|
|
1029
|
-
|
|
1030
|
-
```xml
|
|
1031
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
1032
|
-
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
|
|
1033
|
-
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
1034
|
-
<plist version="1.0">
|
|
1035
|
-
<dict>
|
|
1036
|
-
<key>Label</key> <string>dev.geneseed.web</string>
|
|
1037
|
-
<key>ProgramArguments</key>
|
|
1038
|
-
<array>
|
|
1039
|
-
<string>/Users/you/.local/bin/geneseed</string>
|
|
1040
|
-
<string>web</string>
|
|
1041
|
-
<string>start</string>
|
|
1042
|
-
<string>--no-browser</string>
|
|
1043
|
-
</array>
|
|
1044
|
-
<key>RunAtLoad</key> <true/>
|
|
1045
|
-
</dict>
|
|
1046
|
-
</plist>
|
|
1047
|
-
```
|
|
1048
|
-
|
|
1049
|
-
Use the **absolute** path to your `geneseed` launcher (LaunchAgents don't see your
|
|
1050
|
-
shell `PATH`). Then load it — it also runs it once now:
|
|
1051
|
-
|
|
1052
|
-
```bash
|
|
1053
|
-
launchctl load ~/Library/LaunchAgents/dev.geneseed.web.plist # enable + start now
|
|
1054
|
-
launchctl unload ~/Library/LaunchAgents/dev.geneseed.web.plist # disable
|
|
1055
|
-
```
|
|
1056
|
-
|
|
1057
|
-
On either OS, `geneseed web stop` stops the running daemon without touching the
|
|
1058
|
-
login hook, and `geneseed web status` reports whether it's up.
|
|
1059
|
-
|
|
1060
|
-
## 🤖 Headless / CI (OpenCode)
|
|
1061
|
-
|
|
1062
|
-
Once the harness is installed (Path A or B), OpenCode can run **non-interactively** —
|
|
1063
|
-
no TUI — so the harness's agents, rules, and skills apply in scripts and pipelines:
|
|
1064
|
-
|
|
1065
|
-
```
|
|
1066
|
-
opencode run "review the staged diff and list any correctness bugs" # one-shot, prints to stdout
|
|
1067
|
-
opencode run -m anthropic/claude-sonnet-4-5 "…" # pin a model for the run
|
|
1068
|
-
cat issue.md | opencode run "triage this and propose a fix plan" # pipe input in
|
|
1069
|
-
```
|
|
1070
|
-
|
|
1071
|
-
`opencode run` loads the same `opencode.json` (so `instructions` → `AGENT.md`, the
|
|
1072
|
-
permission gates, and any per-agent overrides all take effect) and the same
|
|
1073
|
-
`.opencode/` agents/skills/plugins. Useful for CI checks, cron jobs, or scripting a
|
|
1074
|
-
capability agent. Notes:
|
|
1075
|
-
|
|
1076
|
-
- **Permissions still gate.** The consent-before-commit/push / `rm -rf` `ask` rules
|
|
1077
|
-
will *block* in a non-interactive run (nothing to answer the prompt). Both
|
|
1078
|
-
`git commit` and `git push` are gated on every branch whenever the **process** pack
|
|
1079
|
-
is active (Doctrine `process 5`; a build without it wires neither), so a CI job that
|
|
1080
|
-
commits must opt those commands back to `"allow"` in its own `permission.bash` map,
|
|
1081
|
-
or scope the run to read-only work — don't blanket-disable the guards.
|
|
1082
|
-
- **`--pure`** runs OpenCode ignoring local/global config — handy to reproduce a bug
|
|
1083
|
-
without the harness in the way, or to confirm a behaviour is the harness's doing.
|
|
1084
|
-
- The **learn** plugin (`session.idle` → memory) and **context** plugin still load in
|
|
1085
|
-
headless runs; set `GENESEED_GUARD=warn`/`off` or `GENESEED_DEBUG=1` per the
|
|
1086
|
-
[adapter README](adapters/opencode/README.md) if a run needs different behaviour.
|
|
1087
|
-
|
|
1088
|
-
This is a usage note, not an emitted feature — the harness writes nothing for it.
|
|
1089
|
-
|
|
1090
|
-
## Upgrade
|
|
1091
|
-
|
|
1092
|
-
**Installed from npm:**
|
|
1093
|
-
|
|
1094
|
-
```
|
|
1095
|
-
npm install -g geneseed@latest # get the new version
|
|
1096
|
-
geneseed rebuild-all # re-render every active install in its own theme + mode
|
|
1097
|
-
```
|
|
1098
|
-
|
|
1099
|
-
`upgrade` / `update` / `sync-self` / `bootstrap` are the *git checkout* route — they pull
|
|
1100
|
-
the install's own origin. Run one from an npm install and it stops before touching
|
|
1101
|
-
anything, naming the `npm install -g` line above instead.
|
|
1102
|
-
|
|
1103
|
-
**Installed from a clone:**
|
|
1104
|
-
|
|
1105
|
-
```
|
|
1106
|
-
./geneseed upgrade # track the checkout's current branch; keep theme + emit mode
|
|
1107
|
-
./geneseed upgrade imperial # force a theme
|
|
1108
|
-
```
|
|
1109
|
-
|
|
1110
|
-
It git-pulls the install's own origin (fast-forward only), validates it (a blocking
|
|
1111
|
-
`doctor` pass, rolling back on failure), then re-renders in place — leaving host state
|
|
1112
|
-
(memory, `context.json`, markers) untouched. Theme and emit mode are remembered between
|
|
1113
|
-
runs. `./geneseed update` and `./geneseed sync-self` are aliases of `upgrade` (one pull
|
|
1114
|
-
refreshes launchers and factory together), and `./geneseed bootstrap` continues into the
|
|
1115
|
-
setup wizard. A dirty tree or a non-git checkout is reported, not force-updated.
|
|
1116
|
-
|
|
1117
|
-
**Reviewing local edits** — if the deployed harness was tweaked in place (you, or the
|
|
1118
|
-
agent's own self-improvement loops) and you want to see what diverged from source:
|
|
1119
|
-
|
|
1120
|
-
```
|
|
1121
|
-
./geneseed diff # summary — --full for line-level diffs
|
|
1122
|
-
./geneseed diff --out improvements.md # export a markdown improvements file
|
|
1123
|
-
```
|
|
1124
|
-
|
|
1125
|
-
The `--out` file is a self-contained back-port artifact: hand it to an agent in the
|
|
1126
|
-
Geneseed source repo and ask it to fold the changes into `src/`. You rarely need to
|
|
1127
|
-
run it by hand — **setup, re-theme, and upgrade auto-export one** whenever the
|
|
1128
|
-
harness they are about to overwrite carries local edits, so a rebuild never silently
|
|
1129
|
-
destroys what the agent learned. The auto-export lands in `improvements/` **inside
|
|
1130
|
-
the deployed harness dir** (e.g. `~/.config/opencode/improvements/`) — beside the
|
|
1131
|
-
install it describes; it is not in the manifest, so re-emits never clobber it, diff
|
|
1132
|
-
never reports it, and uninstall leaves it in place (the same contract as memory).
|
|
1133
|
-
The web console's **Changes** page exports the same file.
|
|
1134
|
-
|
|
1135
|
-
## 🩺 Troubleshooting
|
|
1136
|
-
|
|
1137
|
-
| Symptom | Fix |
|
|
1138
|
-
| --- | --- |
|
|
1139
|
-
| No readiness sigil | Instructions not pointed at `AGENT.md` — check `opencode.json` `instructions` (or your tool's rules setting). |
|
|
1140
|
-
| `PROJECT CONTEXT` block appears twice | Two copies of the context plugin (global + a leftover `.opencode/plugins/`). Remove the project copy. |
|
|
1141
|
-
| Full `PROJECT CONTEXT` block visible in the terminal | Either `GENESEED_CONTEXT_VISIBLE=1` (or legacy `GENESEED_CONTEXT_TRANSFORM=0/off`) is set, or your OpenCode build lacks the experimental transform hook and the plugin fell back to visible delivery — run with `GENESEED_DEBUG=1` to see which (see [Project context](#project-context-usually-nothing)). |
|
|
1142
|
-
| Learn plugin silent / no memory written | Set `GENESEED_HARNESS` (or `GENESEED_MEMORY`); confirm the `.js` files are in the plugins dir. |
|
|
1143
|
-
| `could not determine a model` | Set `GENESEED_MODEL=provider/model`. |
|
|
1144
|
-
| PDFs / Office docs ignored | Use the `ingest` skill and install a converter (MarkItDown / Pandoc / Docling). |
|
|
1145
|
-
| A "read-only" agent won't run a command | By design — read-only agents are denied `bash`. Agents that must run read-only commands (reviewer, security) allow it via a spec marker. |
|
|
1146
|
-
| Skills not tracked in git | A parent `.gitignore` blanket-ignores the bundle dir — remove the bare `Harness/` line; the bundle's own `.gitignore` scopes correctly. |
|
|
1147
|
-
|
|
1148
|
-
More OpenCode-specific notes (why a file loads twice, plugin loading): [HOW-OPENCODE-LOADS.md](adapters/opencode/HOW-OPENCODE-LOADS.md).
|