@misaka-net/misakanet-setup 0.8.1 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +43 -32
- package/bin/misakanet-setup.mjs +66 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
# @misaka-net/misakanet-setup
|
|
2
2
|
|
|
3
3
|
One command to teach your **Claude Code**, **Codex**, **Hermes**, **OpenClaw**, **codewhale**,
|
|
4
|
-
**Cursor**, **Gemini CLI**, **Copilot CLI**, **OpenCode**, **Kiro
|
|
5
|
-
check MisakaNet's failure lessons before repeating a mistake — and to write
|
|
6
|
-
this session produced, at a checkpoint.
|
|
4
|
+
**Cursor**, **Gemini CLI**, **Copilot CLI**, **OpenCode**, **Kiro**, **MiniMax Code** or
|
|
5
|
+
**DeepSeek Harness** to check MisakaNet's failure lessons before repeating a mistake — and to write
|
|
6
|
+
up the reusable lessons this session produced, at a checkpoint.
|
|
7
|
+
|
|
8
|
+
For **DeepSeek Harness (dsh)** that command writes the **rules half only** (`$DSH_HOME/AGENTS.md`)
|
|
9
|
+
and prints the one command its tools need (`dsh plugin --profile web add misakanet`); everything
|
|
10
|
+
else in this README applies to all twelve exactly as written. The split, and why dsh is the one
|
|
11
|
+
target shaped that way, is in [dsh: the rules half, written](#dsh-the-rules-half-written--the-plugin-half-printed).
|
|
7
12
|
|
|
8
13
|
**What it writes:** an MCP endpoint into each agent config, rules blocks for the clients that take
|
|
9
14
|
one, and a local hook for Claude Code. **What leaves this machine:** at most one anonymous request
|
|
@@ -47,60 +52,66 @@ look installed and register nothing. Its manifest also comes with the rules bloc
|
|
|
47
52
|
(`NODE_USE_ENV_PROXY=1`) are in `docs/integrations/mcode.md`.
|
|
48
53
|
|
|
49
54
|
All of them are config files written file-to-file — no subprocess is spawned, so **no token ever appears in a command line**. For Claude Code only, the five **read-only** tools are also added to `permissions.allow` — "can call it" otherwise still means a permission prompt on the very first search, so `0.5.3` pre-allows them (`--verify` reports it, `--report` prints `permissions:`); `write_lesson` is deliberately **not** pre-allowed, because a tool that writes should ask |
|
|
50
|
-
| 2 | the agent **knows when** | rules block appended to `~/.claude/CLAUDE.md` / `~/.codex/AGENTS.md` / `~/.hermes/SOUL.md` / `~/.openclaw/workspace/AGENTS.md` / `~/.minimax/AGENTS.md` (mcode's global scope). **The five JSON-config clients are the exception: they get none**, because their rules are project-scoped (`.cursor/rules/*.mdc`, `GEMINI.md`, `.github/copilot-instructions.md`, `AGENTS.md`, `.kiro/steering/*.md`) and the installer cannot know where your projects live — the install output says so, with the project-side action for each client, instead of implying behaviour changed (issue, retry, risky-operation triggers; desensitisation rules). Wording is **imperative first** ("必须先调 misakanet_search") rather than descriptive, because a field test showed a weaker model reads a descriptive block as background and never calls the tool |
|
|
55
|
+
| 2 | the agent **knows when** | rules block appended to `~/.claude/CLAUDE.md` / `~/.codex/AGENTS.md` / `~/.hermes/SOUL.md` / `~/.openclaw/workspace/AGENTS.md` / `~/.minimax/AGENTS.md` (mcode's global scope) / `$DSH_HOME/AGENTS.md` (dsh, default `~/.dsh`). **The five JSON-config clients are the exception: they get none**, because their rules are project-scoped (`.cursor/rules/*.mdc`, `GEMINI.md`, `.github/copilot-instructions.md`, `AGENTS.md`, `.kiro/steering/*.md`) and the installer cannot know where your projects live — the install output says so, with the project-side action for each client, instead of implying behaviour changed (issue, retry, risky-operation triggers; desensitisation rules). Wording is **imperative first** ("必须先调 misakanet_search") rather than descriptive, because a field test showed a weaker model reads a descriptive block as background and never calls the tool |
|
|
51
56
|
| 4 | *(opt-in)* you **hear** it | `--voice` adds a `PostToolUse` hook that plays the cue the server asked for (`lesson-found` / `failure-warning` / `connect-success` / `pair-success`). Off by default; mute with `MISAKANET_VOICE=0`; see `docs/integrations/mcp-voice-hooks.md` |
|
|
52
57
|
| 3 | the checkpoint **fires** | a hook that counts user turns: turn 1 announces the install to the user, turn 20 (and every 10 after) injects the "write up the reusable lessons and submit them" reminder — the agent does that writing and that submitting, by hand, and the hook itself sends nothing by default; a failed tool call injects a "search before you retry" reminder built from the error text, and only with `MISAKANET_HOOK_FETCH=1` (off by default) does the hook itself send that error text as a search query. Claude Code only today — Codex's user-level hook shape is unconfirmed and OpenClaw's events are unverified, so those two work from the rules block, and `--verify` says so per target instead of implying otherwise |
|
|
53
58
|
|
|
54
59
|
Without (3) a rule saying "summarise every 20 turns" never fires — agents do not keep
|
|
55
60
|
counters. Without (1)/(2) the hook has nothing to call.
|
|
56
61
|
|
|
57
|
-
### dsh
|
|
62
|
+
### dsh: the rules half, written — the plugin half, printed
|
|
58
63
|
|
|
59
64
|
dsh takes its MCP servers from a **plugin bundle**, not from a JSON file. Its instruction files are a
|
|
60
65
|
chain: **`$DSH_HOME/AGENTS.md`** (user-global, default `~/.dsh/AGENTS.md`, applies to every session)
|
|
61
66
|
first, then the project's `AGENTS.md`/`CLAUDE.md` from the project root down to the working directory
|
|
62
67
|
(`@deepseek-ai/dsh-agent-instructions`, byte-budgeted at 65,536 by default). It has no Claude-Code-style
|
|
63
|
-
hooks
|
|
68
|
+
hooks — and no plugin extension point that could inject a rule, which is why the rules are a **file**
|
|
69
|
+
and the tools are a **plugin**, and why the two cannot be one write.
|
|
64
70
|
|
|
65
|
-
So dsh
|
|
66
|
-
|
|
71
|
+
So dsh is **one file target and one printed step**. The installer writes the half a file can hold and
|
|
72
|
+
names the other half instead of doing neither:
|
|
67
73
|
|
|
68
74
|
```bash
|
|
69
|
-
|
|
70
|
-
|
|
75
|
+
npx @misaka-net/misakanet-setup --only dsh # ① the rules block → $DSH_HOME/AGENTS.md
|
|
76
|
+
dsh plugin --profile web add misakanet # ② the tools (mcp__misakanet__*) — dsh's own command
|
|
71
77
|
```
|
|
72
78
|
|
|
79
|
+
Order does not matter; skipping ② leaves rules without tools, and the run says so with the exact
|
|
80
|
+
command (`! dsh:工具在插件包里,安装器不写这个文件 → 跑 \`dsh plugin --profile web add misakanet\``).
|
|
81
|
+
`--list-writes --only dsh` names the file and its tier (`tier2 ② 写规则块 … ~/.dsh/AGENTS.md`), and
|
|
82
|
+
`--mcp-only` skips it, like every other rules block.
|
|
83
|
+
|
|
73
84
|
Measured 2026-10-17: writing `~/.dsh/AGENTS.md` is picked up as `user-global` instructions on the next
|
|
74
|
-
message, with no restart.
|
|
85
|
+
message, with no restart. Measured 2026-10-17: installing the plugin takes ~1s into
|
|
86
|
+
`~/.dsh/profiles/web`, and neither `index.js` (the MCP client mount) nor `lib/client.js` (the web
|
|
87
|
+
panel) injects a rule.
|
|
75
88
|
|
|
76
|
-
Measured 2026-10-
|
|
77
|
-
|
|
78
|
-
|
|
89
|
+
Measured 2026-10-30, on a machine whose block had been pasted by hand: the unmarked text was adopted
|
|
90
|
+
into a marked block (`<!-- misakanet:start -->` … `<!-- misakanet:end -->`, header preserved,
|
|
91
|
+
1,474 bytes) and the next message reloaded it — so an older hand-pasted copy is upgraded in place
|
|
92
|
+
rather than duplicated.
|
|
79
93
|
|
|
80
|
-
**
|
|
81
|
-
installer
|
|
82
|
-
2026-10-
|
|
83
|
-
|
|
84
|
-
(`脱敏:已由代码自动完成…`) to `~/.claude/CLAUDE.md`. Re-paste after an upgrade, and check by comparing
|
|
85
|
-
that line; the copy in `docs/integrations/dsh.md` can lag too.
|
|
94
|
+
**A sandbox home stays a sandbox.** `DSH_HOME` is a user setting, so it is honoured **only when the
|
|
95
|
+
installer is addressing the real home**; with `--home <dir>` every write stays under `<dir>`. That is
|
|
96
|
+
not a footnote: before 2026-10-30 the package's own test run wrote the *real* `~/.dsh/AGENTS.md`
|
|
97
|
+
(truncated it to 35 bytes) because the suite inherits `DSH_HOME` from the shell.
|
|
86
98
|
|
|
87
|
-
**Uninstalling
|
|
88
|
-
removes the tools; the rules block stays in `~/.dsh/AGENTS.md` (or the project's `AGENTS.md`), and there is
|
|
89
|
-
no `misakanet:start` / `misakanet:end` marker to lift it — the installer never put one there, because it
|
|
90
|
-
never wrote that file. Remove the block by hand, then check:
|
|
99
|
+
**Uninstalling is two steps, and neither takes the other's half:**
|
|
91
100
|
|
|
92
101
|
```bash
|
|
93
|
-
|
|
102
|
+
npx @misaka-net/misakanet-setup --uninstall # ① strips the marked block
|
|
103
|
+
dsh plugin --profile web remove misakanet # ② removes the tools
|
|
94
104
|
```
|
|
95
105
|
|
|
96
|
-
|
|
97
|
-
no longer exist.
|
|
106
|
+
Doing ① alone leaves a plugin nobody's rules mention; doing ② alone leaves a session following rules
|
|
107
|
+
that call tools which no longer exist. `--uninstall` keeps `AGENTS.md.misakanet.bak` next to the file
|
|
108
|
+
it emptied, and deletes the file outright when it held nothing but the block.
|
|
98
109
|
|
|
99
|
-
**
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
110
|
+
**Upgrades now refresh the block**, which is the one thing the old hand-pasted flow could not do
|
|
111
|
+
(measured 2026-10-23, issue #3773: a machine's block was still the old `脱敏:密钥/凭据→<REDACTED>…`
|
|
112
|
+
wording while the same installer had just written the current one to `~/.claude/CLAUDE.md`). Re-running
|
|
113
|
+
the installer updates it in place; the copy in `docs/integrations/dsh.md` can still lag, and the
|
|
114
|
+
installer's output is the criterion.
|
|
104
115
|
|
|
105
116
|
Full guide: `docs/integrations/dsh.md`.
|
|
106
117
|
|
package/bin/misakanet-setup.mjs
CHANGED
|
@@ -132,7 +132,7 @@ const SILENT = has('--silent');
|
|
|
132
132
|
const REPORT_JSON = has('--report-json');
|
|
133
133
|
const HOME = resolve(valueOf('--home', homedir()));
|
|
134
134
|
const AGENTS = ['claude', 'codex', 'hermes', 'openclaw', 'codewhale',
|
|
135
|
-
'cursor', 'gemini', 'copilot', 'opencode', 'kiro', 'mcode'];
|
|
135
|
+
'cursor', 'gemini', 'copilot', 'opencode', 'kiro', 'mcode', 'dsh'];
|
|
136
136
|
|
|
137
137
|
/**
|
|
138
138
|
* The three line lists, and what every line knows about itself.
|
|
@@ -197,7 +197,7 @@ function readText(path) {
|
|
|
197
197
|
* except the two that name the version (measured 2026-10-22: the 0.6.0 release pull request
|
|
198
198
|
* failed 9 e2e legs on exactly that).
|
|
199
199
|
*/
|
|
200
|
-
const VERSION = '0.
|
|
200
|
+
const VERSION = '0.9.0' // x-release-please-version
|
|
201
201
|
|
|
202
202
|
/**
|
|
203
203
|
* The shape of a client id, in one place.
|
|
@@ -483,6 +483,8 @@ const AGENT_LABELS = {
|
|
|
483
483
|
hermes: 'Hermes',
|
|
484
484
|
openclaw: 'OpenClaw',
|
|
485
485
|
codewhale: 'Codewhale',
|
|
486
|
+
// dsh is a plugin-bundle client: the installer writes only its rules half (see installDsh).
|
|
487
|
+
dsh: 'dsh',
|
|
486
488
|
...Object.fromEntries(Object.entries(MCP_ONLY_TARGETS).map(([id, spec]) => [id, spec.label])),
|
|
487
489
|
// Not an MCP-only target: it takes a rules block too (see `installMcode`), so its label cannot be
|
|
488
490
|
// read from that table.
|
|
@@ -566,6 +568,9 @@ const AGENT_WRITE_PATHS = {
|
|
|
566
568
|
// carries the rules block (②). Listing both here is what makes the preview, `--list-writes` and
|
|
567
569
|
// the permission pre-check agree with `installMcode`.
|
|
568
570
|
mcode: (home) => [join(home, MCODE_PLUGIN_REL), join(home, MCODE_RULES_REL)],
|
|
571
|
+
// dsh reads its instructions from $DSH_HOME/AGENTS.md (default ~/.dsh). Its MCP servers
|
|
572
|
+
// come from a plugin bundle this installer cannot write, so one file is the whole manifest.
|
|
573
|
+
dsh: (home) => [join(dshHome(home), 'AGENTS.md')],
|
|
569
574
|
openclaw: () => openclawWorkspaces().map((workspace) => join(workspace, 'AGENTS.md')),
|
|
570
575
|
};
|
|
571
576
|
|
|
@@ -1704,6 +1709,9 @@ function mcpEntryPresent(agent) {
|
|
|
1704
1709
|
}
|
|
1705
1710
|
|
|
1706
1711
|
function detect(agent) {
|
|
1712
|
+
// dsh may live outside $HOME (DSH_HOME), so it is answered by its own resolver rather
|
|
1713
|
+
// than by the relative-path table below.
|
|
1714
|
+
if (agent === 'dsh') return existsSync(dshHome());
|
|
1707
1715
|
const paths = {
|
|
1708
1716
|
claude: ['.claude.json', '.claude'],
|
|
1709
1717
|
codex: ['.codex'],
|
|
@@ -2332,6 +2340,43 @@ async function installMcpOnly(agent, bearer) {
|
|
|
2332
2340
|
* `adoptExistingClientId`, so a re-run without `--client-id` keeps the header the file already
|
|
2333
2341
|
* declares (#3772).
|
|
2334
2342
|
*/
|
|
2343
|
+
/**
|
|
2344
|
+
* Where dsh keeps its home: `DSH_HOME` wins, `<home>/.dsh` otherwise (#100.4 item 4).
|
|
2345
|
+
*
|
|
2346
|
+
* `DSH_HOME` is a *user* setting, so it may only apply when the install is addressing the real
|
|
2347
|
+
* home. `--home <dir>` means "pretend this directory is the home" — the test suite and the e2e
|
|
2348
|
+
* depend on every write staying inside it. Honouring `DSH_HOME` there wrote the user's real
|
|
2349
|
+
* `~/.dsh/AGENTS.md` from inside a sandbox run (measured 2026-10-30: the suite truncated it to
|
|
2350
|
+
* 35 bytes, and the next message reloaded the broken block).
|
|
2351
|
+
*/
|
|
2352
|
+
function dshHome(home = HOME) {
|
|
2353
|
+
const real = homedir();
|
|
2354
|
+
if (process.env.DSH_HOME && resolve(home) === resolve(real)) return process.env.DSH_HOME;
|
|
2355
|
+
return join(home, '.dsh');
|
|
2356
|
+
}
|
|
2357
|
+
|
|
2358
|
+
/**
|
|
2359
|
+
* dsh is a plugin-bundle client, so only half of it is a file target.
|
|
2360
|
+
*
|
|
2361
|
+
* The tools (`mcp__misakanet__*`) come from the `misakanet` plugin bundle, which dsh installs with
|
|
2362
|
+
* its own command — there is no JSON file this installer could write. The rules, however, live in
|
|
2363
|
+
* `$DSH_HOME/AGENTS.md`, and writing them is exactly the manual step the README used to ask for.
|
|
2364
|
+
* So the installer writes the half it can and prints the half it cannot, instead of doing neither
|
|
2365
|
+
* and leaving the user with two steps that do not know about each other.
|
|
2366
|
+
*/
|
|
2367
|
+
async function installDsh() {
|
|
2368
|
+
const rules = join(dshHome(), 'AGENTS.md');
|
|
2369
|
+
const profile = process.env.DSH_PROFILE || 'web';
|
|
2370
|
+
const manual = `dsh plugin --profile ${profile} add misakanet`;
|
|
2371
|
+
if (!MCP_ONLY) {
|
|
2372
|
+
ok(`dsh:规则块 ${injectBlock(rules, PROMPT_BLOCK)} → ${rules}`);
|
|
2373
|
+
} else {
|
|
2374
|
+
skip('dsh:规则块未写(--mcp-only)');
|
|
2375
|
+
}
|
|
2376
|
+
need(`dsh:工具在插件包里,安装器不写这个文件 → 跑 \`${manual}\``
|
|
2377
|
+
+ '(不跑就只有规则、没有 mcp__misakanet__* 工具)');
|
|
2378
|
+
}
|
|
2379
|
+
|
|
2335
2380
|
async function installMcode(bearer) {
|
|
2336
2381
|
const plugin = mcodePluginPath(HOME);
|
|
2337
2382
|
const existing = readText(plugin);
|
|
@@ -2826,6 +2871,23 @@ async function verify() {
|
|
|
2826
2871
|
}
|
|
2827
2872
|
}
|
|
2828
2873
|
}
|
|
2874
|
+
// dsh: one file, and only half of the client — so the report says which half it can see. The
|
|
2875
|
+
// rules block is our footprint and is checked like every other target's; the tools live in the
|
|
2876
|
+
// plugin's profile, which this process cannot read, and a "complete" that quietly skipped that
|
|
2877
|
+
// would be the false green this whole report exists to avoid (measured 2026-10-30: with the
|
|
2878
|
+
// block deleted, `--verify` still said 安装完整性:完整).
|
|
2879
|
+
if (wantClient('dsh') && detect('dsh')) {
|
|
2880
|
+
const rules = join(dshHome(), 'AGENTS.md');
|
|
2881
|
+
if (!readText(rules).includes(`<!-- ${START} -->`)) {
|
|
2882
|
+
needWrite('dsh', rules,
|
|
2883
|
+
`dsh:规则块没装(${rules})→ 重跑安装命令`,
|
|
2884
|
+
`dsh:规则块装不了(${rules})→ ${unwritableAdvice()}`);
|
|
2885
|
+
} else {
|
|
2886
|
+
ok('dsh:规则块已装', 'dsh');
|
|
2887
|
+
skip(`dsh:工具在插件包里,--verify 看不到它 → 跑 \`dsh plugin --profile ${process.env.DSH_PROFILE || 'web'} list\` 复核`,
|
|
2888
|
+
'dsh');
|
|
2889
|
+
}
|
|
2890
|
+
}
|
|
2829
2891
|
// Version: what is installed, and whether the registry has moved on. Read-only here — the
|
|
2830
2892
|
// hook owns the periodic nudge (it cannot be a network call in this process's hot path), and
|
|
2831
2893
|
// `--verify` is an explicit user action, so one lookup is both cheap and expected.
|
|
@@ -3175,6 +3237,7 @@ function mcodePluginDirectoryOwnership() {
|
|
|
3175
3237
|
|
|
3176
3238
|
function uninstall() {
|
|
3177
3239
|
let hermesRulesRemoved = false;
|
|
3240
|
+
if (stripBlock(join(dshHome(), 'AGENTS.md'))) ok(`移除规则块 → ${join(dshHome(), 'AGENTS.md')}`);
|
|
3178
3241
|
for (const rel of ['.claude/CLAUDE.md', '.codex/AGENTS.md', '.hermes/SOUL.md', '.minimax/AGENTS.md']) {
|
|
3179
3242
|
if (stripBlock(join(HOME, rel))) {
|
|
3180
3243
|
ok(`移除规则块 → ${rel}`);
|
|
@@ -3816,6 +3879,7 @@ try {
|
|
|
3816
3879
|
else if (agent === 'openclaw') await installOpenclaw(bearer);
|
|
3817
3880
|
else if (agent === 'codewhale') await installCodewhale(bearer);
|
|
3818
3881
|
else if (agent === 'mcode') await installMcode(bearer);
|
|
3882
|
+
else if (agent === 'dsh') await installDsh();
|
|
3819
3883
|
else if (MCP_ONLY_TARGETS[agent]) await installMcpOnly(agent, bearer);
|
|
3820
3884
|
installed += 1;
|
|
3821
3885
|
} catch (err) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@misaka-net/misakanet-setup",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "MisakaNet failure lessons for your agents: writes an MCP endpoint into each agent config, rules blocks where the client takes one, and a Claude Code hook. At most one anonymous request leaves this machine at install; then only the agent's calls — unless MISAKANET_HOOK_FETCH=1 (off by default) the hook sends the failed call's error text or command.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"misakanet-setup": "bin/misakanet-setup.mjs"
|