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.
Files changed (186) hide show
  1. package/CHANGELOG.md +57 -0
  2. package/DESIGN.md +1 -1
  3. package/README.md +26 -44
  4. package/SHIPPED.md +2 -2
  5. package/adapters/bob/README.md +1 -1
  6. package/adapters/claude-code/README.md +17 -12
  7. package/adapters/openclaude/README.md +1 -1
  8. package/adapters/opencode/README.md +4 -4
  9. package/bin/build-driver.mjs +2 -0
  10. package/bin/geneseed-cli.mjs +17 -0
  11. package/bin/geneseed-hook.mjs +2 -0
  12. package/docs/README.md +42 -0
  13. package/docs/_groups.json +18 -0
  14. package/docs/concepts/agents.md +44 -0
  15. package/docs/concepts/collaboration.md +62 -0
  16. package/docs/concepts/exclusions.md +55 -0
  17. package/docs/concepts/footprint.md +52 -0
  18. package/docs/concepts/foreman-mode.md +69 -0
  19. package/docs/concepts/hooks.md +101 -0
  20. package/docs/concepts/hosts.md +55 -0
  21. package/docs/concepts/lsp.md +50 -0
  22. package/docs/{web → concepts}/memory.md +2 -2
  23. package/docs/{web → concepts}/notebook.md +2 -2
  24. package/docs/concepts/rules.md +52 -0
  25. package/docs/concepts/skills.md +49 -0
  26. package/docs/concepts/themes.md +50 -0
  27. package/docs/extending.md +27 -21
  28. package/docs/guides/autostart.md +70 -0
  29. package/docs/guides/choose-your-setup.md +120 -0
  30. package/docs/guides/headless.md +22 -0
  31. package/docs/guides/install.md +161 -0
  32. package/docs/guides/mcp.md +195 -0
  33. package/docs/guides/migrate.md +41 -0
  34. package/docs/guides/project-context.md +87 -0
  35. package/docs/guides/run-anywhere.md +45 -0
  36. package/docs/guides/uninstall.md +51 -0
  37. package/docs/guides/upgrade.md +65 -0
  38. package/docs/guides/verify.md +65 -0
  39. package/docs/guides/wiki.md +69 -0
  40. package/docs/guides/worktree.md +47 -0
  41. package/docs/reference/about.md +7 -0
  42. package/docs/reference/cli.md +7 -0
  43. package/docs/reference/environment.md +99 -0
  44. package/docs/reference/glossary.md +33 -0
  45. package/docs/reference/opencode-plugins.md +131 -0
  46. package/docs/reference/troubleshooting.md +350 -0
  47. package/docs/understand/a-day.md +77 -0
  48. package/docs/understand/enforced-vs-asked.md +64 -0
  49. package/docs/understand/harness.md +36 -0
  50. package/docs/understand/on-your-machine.md +76 -0
  51. package/docs/web-ui.md +1 -1
  52. package/harness.config.json +1 -1
  53. package/js/README.md +3 -2
  54. package/js/build/generate.mjs +12 -1
  55. package/js/build/source.mjs +6 -0
  56. package/js/cli-table.json +1 -1
  57. package/js/hosts/mcp.mjs +1 -1
  58. package/js/hosts/settings.mjs +13 -1
  59. package/js/inspect/checks-authoring.mjs +5 -3
  60. package/js/inspect/doctor.mjs +1 -1
  61. package/js/inspect/inventory.mjs +1 -1
  62. package/js/inspect/registry.mjs +20 -3
  63. package/js/inspect/status.mjs +7 -2
  64. package/js/lib/node-floor.mjs +30 -0
  65. package/js/maintain/setup.mjs +109 -21
  66. package/js/maintain/update.mjs +4 -15
  67. package/js/ui/cli.mjs +2 -2
  68. package/js/web/api.mjs +3 -0
  69. package/js/web/daemon.mjs +52 -0
  70. package/js/web/docs.mjs +149 -65
  71. package/js/web/server.mjs +5 -2
  72. package/package.json +6 -4
  73. package/registry.json +7 -0
  74. package/src/AGENT.md.tmpl +4 -0
  75. package/src/postures/mentor.md +1 -0
  76. package/src/skills/learn-mode.md +89 -0
  77. package/src/skills/pipeline.md +2 -2
  78. package/src/skills/quiz.md +2 -1
  79. package/src/skills/teach.md +2 -1
  80. package/themes/_TEMPLATE.json +1 -0
  81. package/themes/biker.json +1 -0
  82. package/themes/commentator.json +1 -0
  83. package/themes/cyberpunk.json +1 -0
  84. package/themes/gamer.json +1 -0
  85. package/themes/imperial.json +1 -0
  86. package/themes/joker.json +1 -0
  87. package/themes/marvin.json +1 -0
  88. package/themes/mean.json +1 -0
  89. package/themes/military.json +1 -0
  90. package/themes/neutral.json +1 -0
  91. package/themes/pirate.json +1 -0
  92. package/themes/sports.json +1 -0
  93. package/themes/verstappen.json +1 -0
  94. package/themes/wizard.json +1 -0
  95. package/web/dist/assets/Activity-C52LEb-2.js +1 -0
  96. package/web/dist/assets/ActivityDetail-CjNLRvXg.js +1 -0
  97. package/web/dist/assets/Dashboard-B6_sSCHi.js +2 -0
  98. package/web/dist/assets/Docs-Dj7BmCSA.js +5 -0
  99. package/web/dist/assets/{GreenhouseView-D0cbCJ5m.js → GreenhouseView-BALwjQsA.js} +1 -1
  100. package/web/dist/assets/Installs-BbffDQm3.js +2 -0
  101. package/web/dist/assets/JournalView-JpAQ8Hqe.js +1 -0
  102. package/web/dist/assets/Laws-DK7eCWSm.js +3 -0
  103. package/web/dist/assets/Library-CoamHelE.js +1 -0
  104. package/web/dist/assets/{Markdown-CkFyfgNf.js → Markdown-qjM2_ofS.js} +5 -5
  105. package/web/dist/assets/{OperatorHudView-CiAkAkQL.js → OperatorHudView-DVx1HlBx.js} +1 -1
  106. package/web/dist/assets/Personal-eaXb1zcj.js +1 -0
  107. package/web/dist/assets/{Tabs-B4HNrrCs.js → Tabs-BmGtt8E2.js} +1 -1
  108. package/web/dist/assets/api-Dc8f3ca-.js +1 -0
  109. package/web/dist/assets/drawable-Du_PZrQj.js +1 -0
  110. package/web/dist/assets/index-Bz_KMRDH.css +1 -0
  111. package/web/dist/assets/index-CNFH7o55.js +2 -0
  112. package/web/dist/index.html +3 -2
  113. package/QUICKSTART.md +0 -50
  114. package/SETUP.md +0 -1148
  115. package/docs/web/_groups.json +0 -45
  116. package/docs/web/about.md +0 -6
  117. package/docs/web/adapters-claude-code.md +0 -8
  118. package/docs/web/adapters-opencode-loads.md +0 -8
  119. package/docs/web/adapters-opencode-spec.md +0 -8
  120. package/docs/web/adapters-opencode.md +0 -8
  121. package/docs/web/agents.md +0 -8
  122. package/docs/web/authoring.md +0 -11
  123. package/docs/web/autostart.md +0 -9
  124. package/docs/web/claude-hooks.md +0 -37
  125. package/docs/web/cli.md +0 -6
  126. package/docs/web/collaboration.md +0 -27
  127. package/docs/web/configure-wiki.md +0 -9
  128. package/docs/web/design.md +0 -7
  129. package/docs/web/env-knobs.md +0 -9
  130. package/docs/web/exclusions.md +0 -26
  131. package/docs/web/first-session.md +0 -28
  132. package/docs/web/footprint.md +0 -38
  133. package/docs/web/foreman-mode.md +0 -33
  134. package/docs/web/glossary.md +0 -6
  135. package/docs/web/harnesses.md +0 -30
  136. package/docs/web/headless.md +0 -9
  137. package/docs/web/ingest-docs.md +0 -9
  138. package/docs/web/install-paths.md +0 -9
  139. package/docs/web/install-quick.md +0 -35
  140. package/docs/web/lsp-overview.md +0 -37
  141. package/docs/web/mcp-claude-code.md +0 -10
  142. package/docs/web/mcp-filesystem.md +0 -9
  143. package/docs/web/mcp-gitlab.md +0 -9
  144. package/docs/web/mcp-markitdown.md +0 -9
  145. package/docs/web/mcp-overview.md +0 -34
  146. package/docs/web/mcp-trouble.md +0 -9
  147. package/docs/web/mcp-verify.md +0 -9
  148. package/docs/web/migrate.md +0 -39
  149. package/docs/web/model.md +0 -20
  150. package/docs/web/pipelines.md +0 -24
  151. package/docs/web/plugin-activity.md +0 -23
  152. package/docs/web/plugin-context.md +0 -26
  153. package/docs/web/plugin-guard.md +0 -24
  154. package/docs/web/plugin-learn.md +0 -27
  155. package/docs/web/plugin-notify.md +0 -24
  156. package/docs/web/plugin-ponytail.md +0 -23
  157. package/docs/web/plugin-setup.md +0 -7
  158. package/docs/web/plugin-workflow.md +0 -25
  159. package/docs/web/plugins.md +0 -17
  160. package/docs/web/project-context.md +0 -9
  161. package/docs/web/rules.md +0 -30
  162. package/docs/web/run-anywhere.md +0 -9
  163. package/docs/web/self-improve.md +0 -8
  164. package/docs/web/setup-choices.md +0 -64
  165. package/docs/web/skills.md +0 -8
  166. package/docs/web/themes-author.md +0 -20
  167. package/docs/web/themes.md +0 -9
  168. package/docs/web/token-footprint.md +0 -7
  169. package/docs/web/trouble.md +0 -38
  170. package/docs/web/upgrade.md +0 -9
  171. package/docs/web/verify.md +0 -30
  172. package/docs/web/wiki.md +0 -7
  173. package/docs/web/worktree.md +0 -10
  174. package/docs/wiki.md +0 -43
  175. package/web/dist/assets/Activity-BjVp522q.js +0 -1
  176. package/web/dist/assets/ActivityDetail-8ep1bspW.js +0 -1
  177. package/web/dist/assets/Dashboard-OkC_PCH6.js +0 -2
  178. package/web/dist/assets/Docs-CKPWz00o.js +0 -2
  179. package/web/dist/assets/Installs-BtGGdoTt.js +0 -2
  180. package/web/dist/assets/JournalView-Ckl4dmzR.js +0 -1
  181. package/web/dist/assets/Laws-CLpdRRk8.js +0 -3
  182. package/web/dist/assets/Library-wPPuKQrI.js +0 -1
  183. package/web/dist/assets/Personal-D8CnDo9v.js +0 -1
  184. package/web/dist/assets/drawable-BiwaOo6x.js +0 -1
  185. package/web/dist/assets/index-C1yil5j1.js +0 -2
  186. 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).