mixdog 0.7.11 → 0.7.13

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 (67) hide show
  1. package/.claude-plugin/marketplace.json +5 -2
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +28 -74
  4. package/README.md +193 -249
  5. package/bin/statusline-launcher.mjs +5 -1
  6. package/bin/statusline-lib.mjs +14 -6
  7. package/bin/statusline.mjs +14 -6
  8. package/bun.lock +128 -3
  9. package/defaults/hidden-roles.json +3 -0
  10. package/defaults/user-workflow.json +1 -2
  11. package/defaults/user-workflow.md +5 -1
  12. package/hooks/lib/settings-loader.cjs +4 -3
  13. package/hooks/pre-tool-subagent.cjs +7 -2
  14. package/hooks/session-start.cjs +52 -24
  15. package/lib/mixdog-debug.cjs +163 -0
  16. package/native/prebuilt/linux-aarch64/mixdog-shim +0 -0
  17. package/native/prebuilt/linux-x86_64/mixdog-shim +0 -0
  18. package/native/prebuilt/macos-aarch64/mixdog-shim +0 -0
  19. package/native/prebuilt/macos-x86_64/mixdog-shim +0 -0
  20. package/native/prebuilt/windows-x86_64/mixdog-shim.exe +0 -0
  21. package/package.json +9 -2
  22. package/scripts/builtin-utils-smoke.mjs +14 -8
  23. package/scripts/bump.mjs +80 -0
  24. package/scripts/doctor.mjs +8 -3
  25. package/scripts/ensure-deps.mjs +2 -2
  26. package/scripts/mutation-io-smoke.mjs +17 -1
  27. package/scripts/permission-eval-smoke.mjs +18 -1
  28. package/scripts/run-mcp.mjs +65 -9
  29. package/scripts/statusline-launcher-smoke.mjs +2 -2
  30. package/scripts/webhook-selfheal-smoke.mjs +1 -3
  31. package/server-main.mjs +57 -3
  32. package/setup/install.mjs +574 -574
  33. package/setup/launch-core.mjs +0 -1
  34. package/setup/setup-server.mjs +90 -35
  35. package/setup/setup.html +44 -11
  36. package/skills/setup/SKILL.md +12 -2
  37. package/src/agent/index.mjs +1 -1
  38. package/src/agent/orchestrator/config.mjs +58 -6
  39. package/src/agent/orchestrator/providers/model-catalog.mjs +1 -1
  40. package/src/agent/orchestrator/providers/openai-oauth.mjs +9 -2
  41. package/src/agent/orchestrator/providers/openai-ws.mjs +23 -0
  42. package/src/agent/orchestrator/session/loop.mjs +3 -3
  43. package/src/agent/orchestrator/smart-bridge/bridge-llm.mjs +6 -2
  44. package/src/agent/orchestrator/tools/bash-session.mjs +1 -0
  45. package/src/agent/orchestrator/tools/builtin/builtin-tools.mjs +1 -1
  46. package/src/agent/orchestrator/tools/builtin/glob-walk.mjs +29 -6
  47. package/src/agent/orchestrator/tools/builtin/list-tool.mjs +8 -4
  48. package/src/agent/orchestrator/tools/builtin/native-edit-runner.mjs +29 -8
  49. package/src/agent/orchestrator/tools/builtin.mjs +5 -2
  50. package/src/agent/orchestrator/tools/cwd-tool.mjs +17 -17
  51. package/src/agent/orchestrator/tools/graph-manifest.json +11 -11
  52. package/src/agent/orchestrator/tools/patch-manifest.json +11 -11
  53. package/src/agent/tool-defs.mjs +1 -1
  54. package/src/channels/index.mjs +39 -9
  55. package/src/channels/lib/event-queue.mjs +24 -1
  56. package/src/channels/lib/hook-pipe-server.mjs +21 -8
  57. package/src/channels/lib/webhook.mjs +159 -20
  58. package/src/memory/index.mjs +5 -1
  59. package/src/memory/lib/core-memory-store.mjs +1 -1
  60. package/src/memory/lib/memory-cycle1.mjs +8 -4
  61. package/src/memory/lib/memory-cycle2.mjs +1 -1
  62. package/src/memory/lib/memory-cycle3.mjs +1 -1
  63. package/src/memory/lib/memory-recall-store.mjs +27 -10
  64. package/src/search/lib/backends/openai-oauth.mjs +6 -2
  65. package/src/search/lib/cache.mjs +55 -7
  66. package/tools.json +2 -2
  67. package/scripts/test-config-rmw-restore.mjs +0 -122
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
4
4
   [![Runtime: bun](https://img.shields.io/badge/runtime-bun-black.svg)](https://bun.sh)
5
-  ![Version: 0.7.1](https://img.shields.io/badge/version-0.7.1-blue.svg)
5
+  [![npm](https://img.shields.io/npm/v/mixdog.svg)](https://www.npmjs.com/package/mixdog)
6
6
 
7
7
  All-in-one agent plugin for the Claude Code CLI — autonomous sub-agents,
8
8
  continuous memory, multi-provider routing, and syntax-aware code tools,
@@ -13,42 +13,10 @@ behind a single MCP server. Zero telemetry; all state under
13
13
  - **Continuous memory** — conversations, decisions, and work persist across sessions; a prebuilt Postgres + pgvector runtime is auto-downloaded and supervised, with no database to install
14
14
  - **Lower cost** — session-spanning prompt cache with per-provider / per-role token tracking
15
15
  - **Natural-language search** — web search and URL scraping in one tool
16
- - **Syntax-aware code tools** — AST-based symbol / reference / caller lookup, keyword→symbol search via `code_graph` `search`, and precise edits
16
+ - **Syntax-aware code tools** — AST-based symbol / reference / caller lookup, keyword→symbol search via `code_graph`, and precise edits
17
17
  - **Channels & automation** — Discord front-end, cron schedules, and inbound webhooks
18
18
 
19
- ## Contents
20
-
21
- - [Why mixdog](#why-mixdog)
22
- - [Install](#install) · [Quick start](#quick-start)
23
- - [Modules & tools](#modules--tools)
24
- - [Skills & commands](#skills--commands)
25
- - [Providers](#providers)
26
- - [Channels & automation](#channels--automation)
27
- - [Configuration](#configuration)
28
- - [Architecture & hooks](#architecture--hooks)
29
- - [Safety](#safety) · [Windows support](#windows-support)
30
- - [Contributing](#contributing) · [License](#license)
31
-
32
- ## Why mixdog
33
-
34
- Claude Code is powerful, but out of the box it forgets everything between
35
- sessions, treats every request as a fresh context, and has no built-in way
36
- to delegate to cheaper or specialised models. Cost runs high, answers
37
- drift, and long-lived projects lose the thread.
38
-
39
- mixdog replaces that pattern with a single MCP server that bundles four
40
- cooperating modules — **agent**, **memory**, **search**, and **channels** —
41
- so your Claude Code session gains persistent memory, multi-provider
42
- sub-agents, web lookup, and an optional Discord front-end,
43
- all behind one install.
44
-
45
- The goal is deployment-grade: plain ESM, zero build step for runtime
46
- code, documented local state, and every configuration surface readable
47
- as JSON you can diff.
48
-
49
- ## Install
50
-
51
- **From npm (terminal):**
19
+ ## Quickstart
52
20
 
53
21
  ```bash
54
22
  npm i -g mixdog # install the `mixdog` command
@@ -59,91 +27,88 @@ mixdog --dangerously-skip-permissions # launch with full permissions
59
27
  `npm i -g mixdog` adds the `mixdog` command to your PATH; `mixdog` then launches
60
28
  Claude Code with mixdog pre-loaded. The first `mixdog` run walks you through
61
29
  setup (logins + plugin registration) and launches the moment it finishes — no
62
- second run needed. Any extra Claude flags (e.g. `--dangerously-skip-permissions`)
63
- pass straight through; the `claude` CLI must be on your PATH. (If `mixdog` isn't
64
- recognized right after install, open a new terminal and run it again.)
30
+ second run needed. Any extra Claude flags pass straight through; the `claude`
31
+ CLI must be on your PATH. (If `mixdog` isn't recognized right after install,
32
+ open a new terminal and run it again.)
65
33
 
66
- Other entry points: `npx mixdog` (one-off, no global install leaves no
67
- persistent `mixdog` command); `mixdog install` / `--dry-run` / `--demo` (run
68
- setup only, or preview the steps without writing).
34
+ Anthropic OAuth (the Claude Code login) is the default provider, so
35
+ `bridge` / `recall` / `explore` / `memory` work immediately — no API keys
36
+ required. Configure providers, presets, and role bindings in the in-browser
37
+ config UI — open it any time with `/mixdog:config`. (The config server is
38
+ pre-warmed in the background each session, so the window opens instantly.)
69
39
 
70
- **Inside Claude Code (slash commands):**
40
+ **Or install from inside Claude Code:**
71
41
 
72
42
  ```
73
43
  /plugin marketplace add trib-plugin/mixdog
74
44
  /plugin install mixdog@trib-plugin
75
45
  ```
76
46
 
77
- Claude Code will register the repository as a marketplace, clone it,
78
- run `bun install --frozen-lockfile`, and register the MCP server declared in
79
- `.mcp.json`. bun is auto-installed on first launch if missing (node + npm
80
- provided by Claude Code). To skip the first-boot install step, install bun
81
- manually: https://bun.sh
82
-
83
- First-launch flow: `scripts/bootstrap.mjs` (node, no deps) locates bun via
84
- system PATH, falls back to plugin-local `node_modules/.bin/bun`, and finally
85
- runs `npm install --no-save bun` if neither is present. node + npm are
86
- provided by Claude Code, so the npm fallback works on a clean machine.
87
-
88
- ## Quick start
89
-
90
- 1. **Install.**
91
- ```
92
- /plugin marketplace add trib-plugin/mixdog
93
- /plugin install mixdog@trib-plugin
94
- ```
95
-
96
- 2. **Restart Claude Code.** The node bootstrap layer locates or installs
97
- bun, then bun installs runtime dependencies into a shared data
98
- directory and seeds working defaults under
99
- `~/.claude/plugins/data/mixdog-trib-plugin/`. On first boot the memory
100
- runtime (a prebuilt Postgres + pgvector build) is also downloaded and
101
- checksum-verified once, then reused on every later boot. First boot
102
- takes 10-15 extra seconds if bun was not pre-installed, plus the
103
- one-time runtime download; subsequent boots are unaffected.
104
-
105
- First boot also reconfigures two Claude Code surfaces, with the
106
- originals preserved for restore: the built-in `autoMemoryEnabled` and
107
- `awaySummaryEnabled` settings are turned off in `~/.claude/settings.json`
108
- (mixdog's continuous memory and recap replace both), and rules
109
- persistence takes over `~/.claude/CLAUDE.md` (see **Configuration**).
110
- Prior values and the original file are snapshotted under
111
- `~/.claude/backups/mixdog-user-data/install-restore/`, and
112
- `node scripts/uninstall.mjs` restores them (`CLAUDE.md` + the two
113
- settings keys; see UNINSTALL.md for the full manual teardown).
114
-
115
- 3. **That's it.** Anthropic OAuth (the Claude Code login) is the default
116
- provider, so `bridge` / `recall` / `explore` / `memory` work immediately —
117
- no API keys required.
118
-
119
- 4. **Config UI.** On first launch the config UI opens automatically at
120
- `http://localhost:3458` for providers, presets, and role bindings.
121
- You can re-open it any time with `/mixdog:config`.
122
-
123
- 5. **Optional external web search.** Add a Firecrawl / Tavily / Exa key in
124
- the config UI (or edit the `search` section of `mixdog-config.json`
125
- directly in the data directory). xAI search uses the Agent xAI key (set
126
- in the config UI / keychain), not a separate search key.
127
-
128
- 6. **Optional channels.** To enable Discord / voice / schedule / webhook
129
- channels, restart Claude Code with the development channel flag
130
- (see **Channels & automation** below), then set the Discord bot token and
131
- channel IDs in the config UI — the token is stored in the OS keychain,
132
- not a file — and enable channels.
47
+ <details>
48
+ <summary>Other entry points & what first boot does</summary>
49
+
50
+ ```bash
51
+ npx mixdog # one-off run without a global install (leaves no persistent `mixdog` command)
52
+ mixdog install # (re)run setup only: detect Claude CLI, register plugin, OAuth login, prewarm deps
53
+ mixdog install --dry-run # preview the steps (no writes, prompts, or installs)
54
+ mixdog install --demo # preview in an isolated sandbox (no writes to your real config)
55
+ ```
56
+
57
+ Claude Code clones the repo as a marketplace, runs `bun install --frozen-lockfile`,
58
+ and registers the MCP server in `.mcp.json`. On first boot, `scripts/bootstrap.mjs`
59
+ locates bun (system PATH → plugin-local → `npm install --no-save bun` fallback),
60
+ installs runtime deps into the shared data dir, and seeds defaults under
61
+ `~/.claude/plugins/data/mixdog-trib-plugin/`. The memory runtime (a prebuilt
62
+ Postgres + pgvector build) is downloaded and checksum-verified once, then reused.
63
+ First boot takes 10–15 extra seconds if bun wasn't pre-installed, plus the
64
+ one-time runtime download; later boots are unaffected.
65
+
66
+ First boot also reconfigures two Claude Code surfaces, originals preserved for
67
+ restore: the built-in `autoMemoryEnabled` and `awaySummaryEnabled` settings are
68
+ turned off in `~/.claude/settings.json` (mixdog's continuous memory and recap
69
+ replace both), and rules persistence takes over `~/.claude/CLAUDE.md` (see
70
+ Configuration). Prior values are snapshotted under
71
+ `~/.claude/backups/mixdog-user-data/install-restore/`, and
72
+ `node scripts/uninstall.mjs` restores them (see UNINSTALL.md for full teardown).
73
+
74
+ To enable Discord / voice / schedule / webhook channels, launch with the
75
+ development channel flag (see Channels & automation) and set the Discord token
76
+ and channel IDs in the config UI.
77
+
78
+ </details>
79
+
80
+ ## Why mixdog
81
+
82
+ Claude Code is powerful, but out of the box it forgets everything between
83
+ sessions, treats every request as a fresh context, and has no built-in way
84
+ to delegate to cheaper or specialised models. Cost runs high, answers drift,
85
+ and long-lived projects lose the thread.
86
+
87
+ mixdog replaces that pattern with a single MCP server that bundles four
88
+ cooperating modules — **agent**, **memory**, **search**, and **channels** — so
89
+ your Claude Code session gains persistent memory, multi-provider sub-agents,
90
+ web lookup, and an optional Discord front-end, all behind one install. The goal
91
+ is deployment-grade: plain ESM, zero build step for runtime code, documented
92
+ local state, and every configuration surface readable as JSON you can diff.
133
93
 
134
94
  ## Modules & tools
135
95
 
136
- mixdog is one MCP server composing four user-facing modules. Code and
137
- filesystem tools are shared across all of them.
96
+ One MCP server composes four user-facing modules, plus code and filesystem
97
+ tools shared across all of them:
98
+
99
+ - **agent** — a session orchestrator with a single `bridge` entry point: delegated sub-agent sessions, role → preset bindings, multi-provider routing, and session-spanning cache / cost handling.
100
+ - **memory** — native Postgres + `pgvector` + `pg_trgm` hybrid store; a prebuilt runtime is fetched and supervised automatically. A three-cycle pipeline scores, dedupes, and promotes durable knowledge to core memory.
101
+ - **search** — one natural-language entry point routing across providers, scraping URLs through a Readability + Puppeteer pipeline, formatted for model consumption.
102
+ - **channels** — Discord, cron schedules, inbound webhooks, voice STT, and a heartbeat status surface (requires the channel flag).
103
+
104
+ <details>
105
+ <summary>Full tool reference</summary>
138
106
 
139
107
  ### agent
140
108
 
141
- A session orchestrator with a single `bridge` entry point: delegated
142
- sub-agent sessions, role preset bindings (`user-workflow.json`),
143
- multi-provider routing, and session-spanning cache / cost handling.
144
- Sessions run as long-lived loops with trim / compress, a stream
145
- watchdog, and background job tracking. A `<final-answer>` tag protocol
146
- separates a worker's final reply from its internal deliberation.
109
+ Sessions run as long-lived loops with trim / compress, a stream watchdog, and
110
+ background job tracking. A `<final-answer>` tag protocol separates a worker's
111
+ final reply from its internal deliberation.
147
112
 
148
113
  | Tool | Purpose |
149
114
  | --- | --- |
@@ -154,17 +119,12 @@ separates a worker's final reply from its internal deliberation.
154
119
 
155
120
  ### memory
156
121
 
157
- Native PostgreSQL with `pgvector` and `pg_trgm` backs a hybrid FTS +
158
- vector store; a prebuilt runtime is fetched from the release manifest on
159
- first boot, checksum-verified, and supervised automatically there is no
160
- separate database to install or configure. Every conversation chunk is
161
- scored, deduped, and if durable promoted to core memory. A three-cycle
162
- pipeline keeps it compact: cycle 1 extracts and scores chunks, cycle 2 is a
163
- unified curator gate that holds the active set to a cap (~100 entries), and
164
- cycle 3 reviews user-curated core memory. Keep/discard decisions follow a
165
- 3-layer framework — L1 relationship/communication, L2 behavior rules, L3
166
- current project map — so only durable standing knowledge survives. SessionStart
167
- injects durable context plus a recent recap.
122
+ Every conversation chunk is scored, deduped, and if durable promoted to core
123
+ memory. Cycle 1 extracts and scores chunks, cycle 2 is a unified curator gate
124
+ that holds the active set to a cap (~100 entries), and cycle 3 reviews
125
+ user-curated core memory. Keep/discard decisions follow a 3-layer framework
126
+ (L1 relationship/communication, L2 behavior rules, L3 current project map).
127
+ SessionStart injects durable context plus a recent recap.
168
128
 
169
129
  | Tool | Purpose |
170
130
  | --- | --- |
@@ -173,11 +133,6 @@ injects durable context plus a recent recap.
173
133
 
174
134
  ### search
175
135
 
176
- One natural-language entry point routes across multiple search
177
- providers and scrapes URLs through a Readability + Puppeteer pipeline.
178
- Results are cached and formatted for model
179
- consumption, not browser consumption.
180
-
181
136
  | Tool | Purpose |
182
137
  | --- | --- |
183
138
  | `search` | Web SERP search (string or array of queries) |
@@ -185,10 +140,8 @@ consumption, not browser consumption.
185
140
 
186
141
  ### channels
187
142
 
188
- Discord, cron schedules, inbound webhooks, voice STT, and a heartbeat
189
- status surface. Inbound chat / webhook events drive a turn, schedules
190
- fire on cadence, and the status feed keeps long-running sessions
191
- observable. (Requires the channel flag — see **Channels & automation**.)
143
+ Inbound chat / webhook events drive a turn, schedules fire on cadence, and the
144
+ status feed keeps long-running sessions observable.
192
145
 
193
146
  | Tool | Purpose |
194
147
  | --- | --- |
@@ -199,16 +152,13 @@ observable. (Requires the channel flag — see **Channels & automation**.)
199
152
  ### Code & filesystem tools
200
153
 
201
154
  Shared across all modules — AST navigation (`@ast-grep/cli`) plus
202
- content-addressed edits with a session read-dedup cache, so navigation
203
- stays syntax-correct without dumping whole files into context. Tool
204
- results are compressed before they hit the model (head/tail truncation,
205
- ANSI / repeated-line dedup, file-grouped grep output). The `Module` column
206
- matches the `module` tag in `tools.json`. `apply_patch` accepts unified and
207
- V4A hunks with order-independent matching, so multi-hunk patches apply
208
- regardless of the order the hunks are listed. `read` decodes UTF-8 and
209
- UTF-16 (LE/BE, with or without BOM). `bash` auto-backgrounds a foreground
210
- command that outlives 30s into a tracked job and streams live progress over
211
- MCP, so long commands never block the session.
155
+ content-addressed edits with a session read-dedup cache, so navigation stays
156
+ syntax-correct without dumping whole files into context. Tool results are
157
+ compressed before they hit the model (head/tail truncation, ANSI / repeated-line
158
+ dedup, file-grouped grep output). `apply_patch` accepts unified and V4A hunks
159
+ with order-independent matching. `read` decodes UTF-8 and UTF-16 (LE/BE, with or
160
+ without BOM). `bash` auto-backgrounds a foreground command that outlives 30s into
161
+ a tracked job and streams live progress over MCP.
212
162
 
213
163
  | Tool | Module | Purpose |
214
164
  | --- | --- | --- |
@@ -221,9 +171,19 @@ MCP, so long commands never block the session.
221
171
  | `inject_input` | `host_input` | Inject input into the host Claude Code session (Windows only) |
222
172
  | `cwd` | `cwd` | Get / set / list the session working directory for relative-path resolution |
223
173
 
174
+ </details>
175
+
224
176
  ## Skills & commands
225
177
 
226
- **Skills** (auto-triggered by intent; Claude Code also surfaces them by name):
178
+ **Skills** are auto-triggered by intent (Claude Code also surfaces them by name):
179
+ `setup` (onboarding & config), `schedule-add`, `webhook-add`, `retro-skill-proposer`.
180
+
181
+ **Commands:** `/mixdog:setup` (prerequisites + config UI), `/mixdog:doctor`
182
+ (health diagnostics), `/mixdog:config` (open the in-browser settings UI — **the
183
+ primary way to change any configuration**).
184
+
185
+ <details>
186
+ <summary>Details</summary>
227
187
 
228
188
  | Skill | Use |
229
189
  | --- | --- |
@@ -232,30 +192,42 @@ MCP, so long commands never block the session.
232
192
  | `setup` | Onboarding and config editing (channels, presets, roles, memory) |
233
193
  | `retro-skill-proposer` | Propose a reusable skill draft after a session |
234
194
 
235
- **Commands** (`/mixdog:<name>`):
236
-
237
195
  | Command | Purpose |
238
196
  | --- | --- |
239
197
  | `/mixdog:setup` | Check prerequisites and open the config UI |
240
198
  | `/mixdog:doctor` | Health diagnostics (versions, runtime, cache, deps, log count/size, Postgres `pgdata` size, hook-pipe reachability) |
241
- | `/mixdog:config` | Open the in-browser config page directly |
199
+ | `/mixdog:config` | Open the in-browser settings UI the primary way to change configuration (providers, presets, roles, channels, memory) |
242
200
 
243
201
  **Hidden maintenance roles** (under `agents/`, not user-invoked):
244
202
  `scheduler-task`, `webhook-handler`, `maintenance`, `memory-classification`.
245
- Any public roles (worker, reviewer, debugger, etc.) are defined locally in
203
+ Public roles (worker, reviewer, debugger, etc.) are defined locally in
246
204
  `user-workflow.json`, not bundled.
247
205
 
206
+ </details>
207
+
248
208
  ## Providers
249
209
 
250
- Anthropic (direct or OAuth), OpenAI (direct or OAuth), Google Gemini,
251
- and any OpenAI-compatible endpoint (LM Studio, Ollama, vLLM, LiteLLM)
252
- are first-class providers. Switch a role to a cheaper or faster model by
253
- editing one line in `user-workflow.json`. A shared-prefix cache strategy
254
- propagates Anthropic and OpenAI prompt caching across every role in a
255
- session, and token usage is logged per provider and per role so you can
256
- see where cost lands before the bill arrives.
210
+ Anthropic (direct or OAuth), OpenAI (direct or OAuth), Google Gemini, and any
211
+ OpenAI-compatible endpoint (LM Studio, Ollama, vLLM, LiteLLM) are first-class
212
+ providers. Switch a role to a cheaper or faster model by editing one line in
213
+ `user-workflow.json`. A shared-prefix cache strategy propagates Anthropic and
214
+ OpenAI prompt caching across every role in a session, and token usage is logged
215
+ per provider and per role so you can see where cost lands before the bill arrives.
216
+
217
+ ## Safety
218
+
219
+ - **Zero telemetry.** No outbound calls beyond the providers you configure and the search endpoints you opt into.
220
+ - **Protected paths.** Destructive shell patterns (recursive root deletes, force pushes, disk formatting) are hard-blocked, unconditionally, with no override flag.
221
+ - **Approval gates & tool scope.** Out-of-workspace writes by sub-agents require confirmation; system paths are hard-denied; each role has an explicit tool preset (`readonly` / `full` / custom).
222
+ - **Untrusted inbound data.** Webhook payloads are fenced as untrusted data, never executed as instructions.
223
+ - **Fail-open hooks.** Permission hooks are a guard layer, not a sandbox: if the daemon or hook pipe is down, decisions default to allow (`/mixdog:doctor` warns explicitly).
224
+
225
+ Full local-state, secret, and network model: [SECURITY.md](SECURITY.md) and
226
+ [DATA-FLOW.md](DATA-FLOW.md). To restore the pre-install `CLAUDE.md` and Claude
227
+ Code settings, run `node scripts/uninstall.mjs` ([UNINSTALL.md](UNINSTALL.md)).
257
228
 
258
- ## Channels & automation
229
+ <details>
230
+ <summary>Channels & automation</summary>
259
231
 
260
232
  Channel-driven features require launching Claude Code with the channel flag.
261
233
  mixdog is not in Anthropic's curated channel allowlist, so `--channels` is
@@ -267,139 +239,111 @@ claude --dangerously-load-development-channels plugin:mixdog@trib-plugin
267
239
 
268
240
  This activates the Discord backend, voice STT, schedule runner, and webhook
269
241
  receiver. Without the flag the plugin still works for direct tools (`recall`,
270
- `memory`, `bridge`, `explore`, `search`, `bash`, etc.) — channel inbound
271
- events are silently disabled.
242
+ `memory`, `bridge`, `explore`, `search`, `bash`, etc.) — channel inbound events
243
+ are silently disabled.
272
244
 
273
245
  **Schedules and webhooks** each live as a per-entry directory under the data
274
246
  directory (`schedules/<name>/`, `webhooks/<name>/`), holding `config.json`
275
- (cron `time` / `secret` / optional `channel` / `model`) and `instructions.md`
276
- (what to do on fire / delivery). Routing is decided purely by **channel
277
- presence**:
247
+ (cron `time` / `secret` / optional `channel` / `model`) and `instructions.md`.
248
+ Routing is decided purely by **channel presence**:
278
249
 
279
- - **No `channel`** → the delivery is **injected into the current (Lead)
280
- session**, which handles it with full context.
281
- - **`channel` set** → it is **dispatched directly to that Discord channel** by
282
- a standalone handler (which then requires a `model` preset).
250
+ - **No `channel`** → injected into the current (Lead) session, which handles it with full context.
251
+ - **`channel` set** → dispatched directly to that Discord channel by a standalone handler (which then requires a `model` preset).
283
252
 
284
253
  When a handler has nothing to report (no code change, non-default branch,
285
- docs-only, dedup), it emits `[meta:silent]` as the first line — the
286
- notification is then dropped entirely (no session turn, no channel post).
254
+ docs-only, dedup), it emits `[meta:silent]` as the first line — the notification
255
+ is dropped entirely (no session turn, no channel post).
287
256
 
288
- Outbound notifications respect a shared quiet-hours window (timezone-aware,
289
- with weekend and holiday handling); each channel system can opt out of
290
- quieting via its own `respectQuiet` flag in the config UI's DND tab.
257
+ Outbound notifications respect a shared quiet-hours window (timezone-aware, with
258
+ weekend and holiday handling); each channel can opt out via its `respectQuiet`
259
+ flag in the config UI's DND tab.
291
260
 
292
261
  To switch to plain `--channels`, either submit mixdog to
293
262
  `claude-plugins-official` (Anthropic curates the allowlist), or add
294
263
  `{marketplace: "trib-plugin", plugin: "mixdog"}` to your organization's
295
264
  `allowedChannelPlugins` managed setting (Team / Enterprise).
296
265
 
297
- ## Configuration
266
+ </details>
267
+
268
+ <details>
269
+ <summary>Configuration</summary>
298
270
 
299
271
  All user-editable config lives in the plugin data directory
300
- (`~/.claude/plugins/data/mixdog-trib-plugin/`), NOT in the repository.
301
- The easiest way to edit it is `/mixdog:config` this opens the in-browser
302
- UI. Editing the JSON files directly is also fully supported.
303
-
304
- New installs default to `CLAUDE.md` mode: mixdog persists its rules block
305
- into `~/.claude/CLAUDE.md`. On the first takeover of an existing file, the
306
- original is backed up once to
307
- `~/.claude/backups/mixdog-user-data/install-restore/claude-md-original.md`
308
- and the file is replaced with the marker-delimited managed block; if that
309
- backup cannot be written, mixdog appends the block instead and leaves your
310
- content in place. If you prefer ephemeral injection, switch to SessionStart
311
- hook mode in the config UI — that mode never writes to `~/.claude/CLAUDE.md`.
272
+ (`~/.claude/plugins/data/mixdog-trib-plugin/`), NOT in the repository. The
273
+ easiest way to edit it is `/mixdog:config` (the in-browser UI); editing the JSON
274
+ files directly is also fully supported.
275
+
276
+ New installs default to `CLAUDE.md` mode: mixdog persists its rules block into
277
+ `~/.claude/CLAUDE.md`. On the first takeover of an existing file, the original is
278
+ backed up once to
279
+ `~/.claude/backups/mixdog-user-data/install-restore/claude-md-original.md` and
280
+ the file is replaced with the marker-delimited managed block; if that backup
281
+ can't be written, mixdog appends the block instead and leaves your content in
282
+ place. Prefer ephemeral injection? Switch to SessionStart hook mode in the config
283
+ UI — that mode never writes to `~/.claude/CLAUDE.md`.
312
284
 
313
285
  First install also disables Claude Code's built-in `autoMemoryEnabled` and
314
- `awaySummaryEnabled` in `~/.claude/settings.json` mixdog's memory and
315
- recap replace both after snapshotting the prior values to
286
+ `awaySummaryEnabled` in `~/.claude/settings.json` (mixdog's memory and recap
287
+ replace both) after snapshotting the prior values to
316
288
  `install-restore/claude-settings-original.json`. Run
317
- `node scripts/uninstall.mjs` to restore the original file and settings.
318
-
319
- The following files are managed in the data directory:
289
+ `node scripts/uninstall.mjs` to restore.
320
290
 
321
291
  | File | How it gets there | Purpose |
322
292
  | --- | --- | --- |
323
- | `mixdog-config.json` | Auto-seeded on first boot | All user-configurable settings under named sections (`channels`, `memory`, `agent`, `search`, plus UI-managed extras). See `src/shared/seed.mjs` for the default structure. |
293
+ | `mixdog-config.json` | Auto-seeded on first boot | All user-configurable settings under named sections (`channels`, `memory`, `agent`, `search`, plus UI-managed extras). See `src/shared/seed.mjs`. |
324
294
  | `user-workflow.json` | Seeded by the setup server when missing | Role → preset bindings for delegated agents |
325
- | `user-workflow.md` | Auto-generated on first launch | Human-readable workflow description derived from `user-workflow.json`; used by the Lead as a role reference |
295
+ | `user-workflow.md` | Auto-generated on first launch | Human-readable workflow description derived from `user-workflow.json` |
326
296
  | `schedules/<name>/` | Created via config UI or `schedule-add` | Per-schedule `config.json` + `instructions.md` |
327
297
  | `webhooks/<name>/` | Created via config UI or `webhook-add` | Per-webhook `config.json` + `instructions.md` |
328
298
 
329
- Seed defaults and templates live under `defaults/`
330
- (`mixdog-config.template.json`, `user-workflow.json`) useful as a
331
- reference or for diffing after manual edits.
332
-
333
- **Discord setup (optional).** Set the Discord bot token in the config UI
334
- (`/mixdog:config`) — it is stored in the OS keychain, not a file — and add
335
- your channel IDs there, then enable channels.
336
-
337
- ## Architecture & hooks
338
-
339
- The MCP server starts via `scripts/bootstrap.mjs scripts/run-mcp.mjs`
340
- (stdio supervisor) `→ server.mjs` (thin client or shared daemon) `→
341
- server-main.mjs`. Hooks are declared in `hooks/hooks.json` and routed through
342
- a native shim + CJS files. SessionStart is split into three parts — `rules`
343
- (workflow / rules injection + first-boot setup), `core` (durable memory
344
- context), and `recap` (recent-session recap); PreToolUse / PostToolUse enforce
345
- permission gates, sandbox checks, and status updates. Session state is
346
- journalled every turn, so a mid-session crash resumes cleanly on next boot.
347
- SessionStart also installs a version-independent status line: a stable launcher
348
- is copied into the data directory and registered in `~/.claude/settings.json`
349
- (tagged `"source": "mixdog-auto"`), so the status line survives plugin version
350
- bumps and self-heals without a restart. A genuine user-configured `statusLine`
351
- is left untouched.
299
+ Seed defaults and templates live under `defaults/`. **Discord setup (optional):**
300
+ set the bot token in the config UI (stored in the OS keychain, not a file) and
301
+ add channel IDs there, then enable channels.
302
+
303
+ </details>
304
+
305
+ <details>
306
+ <summary>Architecture & hooks</summary>
307
+
308
+ The MCP server starts via `scripts/bootstrap.mjs → scripts/run-mcp.mjs` (stdio
309
+ supervisor) `→ server.mjs` (thin client or shared daemon) `→ server-main.mjs`.
310
+ Hooks are declared in `hooks/hooks.json` and routed through a native shim + CJS
311
+ files. SessionStart is split into three parts — `rules` (workflow / rules
312
+ injection + first-boot setup), `core` (durable memory context), and `recap`
313
+ (recent-session recap); PreToolUse / PostToolUse enforce permission gates,
314
+ sandbox checks, and status updates. Session state is journalled every turn, so a
315
+ mid-session crash resumes cleanly on next boot. SessionStart also installs a
316
+ version-independent status line (a stable launcher tagged
317
+ `"source": "mixdog-auto"` in `~/.claude/settings.json`) that survives version
318
+ bumps and self-heals; a genuine user-configured `statusLine` is left untouched.
319
+
352
320
  See [ARCHITECTURE.md](ARCHITECTURE.md) and [DATA-FLOW.md](DATA-FLOW.md).
353
321
 
354
- ## Safety
322
+ </details>
323
+
324
+ <details>
325
+ <summary>Windows support</summary>
326
+
327
+ mixdog is developed on Windows and tested on Windows + Linux. All scripts use
328
+ forward slashes or `path.join`, line endings are normalised to LF via
329
+ `.gitattributes` (except `.cmd` / `.bat` / `.ps1`, which stay CRLF), and Node
330
+ child-process calls resolve binaries through `process.platform`-aware shims.
355
331
 
356
- - **Protected paths.** The MCP server hard-blocks destructive shell
357
- patterns (recursive root deletes, force pushes, disk formatting)
358
- these are unconditional, with no override flag.
359
- - **Approval gates.** Out-of-workspace filesystem writes by sub-agents
360
- require a confirmation prompt, and system paths are hard-denied.
361
- - **Tool scope.** Each role has an explicit tool preset
362
- (`readonly` / `full` / custom) — there is no ambient access.
363
- - **Untrusted inbound data.** Webhook payloads are fenced as untrusted
364
- data and never executed as instructions.
365
- - **No background exfiltration.** The plugin makes no outbound calls
366
- beyond the providers you configure and the search endpoints you
367
- opt into.
368
- - **Fail-open hooks.** Permission hooks are a guard layer, not a
369
- sandbox: if the mixdog daemon or its hook pipe is down, hook
370
- decisions default to allow. `/mixdog:doctor` warns explicitly when
371
- the hook pipe is unreachable. See the "Fail-open Hook Model" section
372
- in [SECURITY.md](SECURITY.md).
373
-
374
- For the full local state, secret, and network model, see
375
- [SECURITY.md](SECURITY.md) and [DATA-FLOW.md](DATA-FLOW.md). To restore the
376
- pre-install `CLAUDE.md` and Claude Code settings, run
377
- `node scripts/uninstall.mjs`; for full removal, see
378
- [UNINSTALL.md](UNINSTALL.md).
379
-
380
- ## Windows support
381
-
382
- mixdog is developed on Windows and tested on Windows + Linux.
383
- All scripts use forward slashes or `path.join`, line endings are
384
- normalised to LF via `.gitattributes` (except `.cmd` / `.bat` /
385
- `.ps1`, which stay CRLF), and Node child-process calls resolve
386
- binaries through `process.platform`-aware shims.
387
-
388
- The prebuilt memory runtime ships for Windows (`win32-x64`), Linux
389
- (`linux-x64`), and macOS on both Apple Silicon (`darwin-arm64`) and Intel
390
- (`darwin-x64`); the optional voice helper publishes verified assets for the
391
- same platforms. `linux-arm64` is not yet built.
332
+ The prebuilt memory runtime ships for Windows (`win32-x64`), Linux (`linux-x64`),
333
+ and macOS on Apple Silicon (`darwin-arm64`) and Intel (`darwin-x64`); the optional
334
+ voice helper publishes verified assets for the same platforms. `linux-arm64` is
335
+ not yet built.
392
336
 
393
337
  The `bash` MCP tool is OS-native: Windows runs commands through PowerShell
394
- (`pwsh.exe` when available, otherwise Windows PowerShell), while macOS/Linux
395
- use `/bin/sh`. No extra Windows shell runtime is required or auto-installed.
338
+ (`pwsh.exe` when available, otherwise Windows PowerShell), while macOS/Linux use
339
+ `/bin/sh`. No extra Windows shell runtime is required or auto-installed.
396
340
 
397
- ## Contributing
341
+ </details>
398
342
 
399
- Architecture notes live in [ARCHITECTURE.md](ARCHITECTURE.md). Contributor
400
- setup and PR expectations live in [CONTRIBUTING.md](CONTRIBUTING.md).
343
+ ## Contributing
401
344
 
402
- Before opening a PR, run:
345
+ Architecture notes live in [ARCHITECTURE.md](ARCHITECTURE.md); contributor setup
346
+ and PR expectations in [CONTRIBUTING.md](CONTRIBUTING.md). Before opening a PR, run:
403
347
 
404
348
  ```sh
405
349
  bun run ci
@@ -21,6 +21,10 @@ function failSoft() {
21
21
  process.exit(0);
22
22
  }
23
23
 
24
+ function claudeConfigDir() {
25
+ return process.env.CLAUDE_CONFIG_DIR || path.join(os.homedir(), '.claude');
26
+ }
27
+
24
28
  async function main() {
25
29
  // CC stdin JSON (may be empty). Never block the tick on a read error.
26
30
  let stdinBuf = Buffer.alloc(0);
@@ -29,7 +33,7 @@ async function main() {
29
33
  // Resolve the ACTIVE install from the manifest — manifest-canonical, no
30
34
  // version pin. Any failure here → fail-soft.
31
35
  const manifestPath = path.join(
32
- os.homedir(), '.claude', 'plugins', 'installed_plugins.json'
36
+ claudeConfigDir(), 'plugins', 'installed_plugins.json'
33
37
  );
34
38
  let installPath = '';
35
39
  try {