daedalus-cli 3.25.0 → 3.25.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ ## [3.25.1](https://github.com/bgill55/daedalus/compare/v3.25.0...v3.25.1) (2026-08-09)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * **build:** copy skill playbooks to dist so they ship to npm users ([#86](https://github.com/bgill55/daedalus/issues/86)) ([56d6aa4](https://github.com/bgill55/daedalus/commit/56d6aa4cc0acd092694ca80b421d7592e8f48991)), closes [#85](https://github.com/bgill55/daedalus/issues/85)
7
+
1
8
  # [3.25.0](https://github.com/bgill55/daedalus/compare/v3.24.0...v3.25.0) (2026-08-09)
2
9
 
3
10
 
@@ -0,0 +1,65 @@
1
+ ---
2
+ name: add-slash-command
3
+ description: How to add a new slash command to Daedalus (src/commands), including the docs-sync step that breaks CI if skipped.
4
+ trigger: add a command|new /command|create a slash command|add /command|/command
5
+ safety: instructions
6
+ ---
7
+
8
+ # Adding a Slash Command to Daedalus
9
+
10
+ Commands live in `src/commands/` and are aggregated in `src/commands/index.ts`.
11
+ ESM only, named exports, `.js` extension on imports, no comments unless necessary.
12
+
13
+ ## Command shape
14
+ `src/commands/types.ts` defines `Command`:
15
+ ```ts
16
+ export interface Command {
17
+ name: string; // '/spinner'
18
+ aliases?: string[]; // ['spin']
19
+ description: string;
20
+ usage?: string;
21
+ helpText?: string;
22
+ execute: (args: string, ctx: CommandContext) => Promise<boolean | void>;
23
+ }
24
+ ```
25
+
26
+ ## Steps
27
+ 1. Create `src/commands/<name>.ts` exporting `export const <name>Commands: Command[]`.
28
+ Inside `execute`, use `ctx.config` (typed `DaedalusConfig`), `ctx.configDir`, `ctx.router`.
29
+ 2. To persist a config change, mirror `/config` (src/commands/dev.ts ~line 964):
30
+ ```ts
31
+ const { saveConfig, ConfigSchema } = await import('../config/index.js');
32
+ ctx.config.ui.spinner = arg;
33
+ const validated = ConfigSchema.parse(ctx.config);
34
+ ctx.config = validated;
35
+ saveConfig(validated);
36
+ if (ctx.router && typeof ctx.router.updateConfig === 'function') {
37
+ ctx.router.updateConfig(ctx.config.router);
38
+ }
39
+ ```
40
+ Validate input BEFORE mutating; reject unknown values with a friendly message.
41
+ 3. Register in `src/commands/index.ts`:
42
+ `import { <name>Commands } from './<name>.js';` then spread `...<name>Commands,` into `commandsList`.
43
+ 4. CRITICAL — docs will break CI if you skip this. `src/docs.test.ts` has two tests
44
+ that fail unless the command is in BOTH the docs generator and the test's own copy:
45
+ - `scripts/sync-docs.ts`: add the command to `COMMAND_GROUPS` (array) AND `COMMAND_USAGES` (map).
46
+ - `src/docs.test.ts`: add the SAME entries to its duplicate `COMMAND_GROUPS` + `COMMAND_USAGES`.
47
+ - Then run `npm run sync-docs` to regenerate README.md + docs/configuration-reference.md.
48
+ The usual failure: a missing `COMMAND_USAGES` entry → test says "commands table is out of sync".
49
+ 5. Add `src/commands/<name>.test.ts`. For config-persisting commands, `vi.mock('../config/index.js')`
50
+ with `{ ConfigSchema: { parse: (c) => c }, saveConfig: vi.fn() }` so no real disk write;
51
+ assert `saveConfig` called and `ctx.router.updateConfig` fired.
52
+
53
+ ## Verify before commit
54
+ ```
55
+ npx tsc --noEmit
56
+ npm run lint
57
+ npm test
58
+ ```
59
+ `docs.test.ts` is the easy one to break — always run `npm run sync-docs` after touching groups/usages.
60
+
61
+ ## PR + release notes
62
+ - PR title scope with a comma (`fix(tools,router):`) is rejected by the title guard; use a single scope.
63
+ - `require()`-style imports in test files trip `no-require-imports`; use ESM imports.
64
+ - The Release workflow may not auto-trigger on squash-merge; dispatch manually:
65
+ `gh workflow run release.yml`.
@@ -0,0 +1,56 @@
1
+ ---
2
+ name: fix-typescript-build
3
+ description: How to fix a failing `tsc`/`npm run build` (type-check) run in a project, batching fixes into sprints to preserve context.
4
+ trigger: fix the build|type errors|typescript errors|tsc errors|build is broken|build fails|npm run build|fix the type errors
5
+ safety: instructions
6
+ ---
7
+
8
+ # Fixing a TypeScript Build (npm run build / tsc)
9
+
10
+ The project's `build` script is usually `tsc --noEmit` (a type-check, not a bundle).
11
+ A failing build means type errors. Fix them deliberately — do NOT blast the whole
12
+ codebase in one giant turn (that burns the context window and makes review impossible).
13
+
14
+ > Prefer `npm run build` over `npx tsc`. `npx tsc` is not a declared dependency in
15
+ > most projects, so `npx` will try to download the `tsc` package from the registry —
16
+ > that download is slow and flaky (and can be killed by the terminal's process-group
17
+ > isolation on Windows). `npm run build` uses the project's local TypeScript.
18
+
19
+ ## Process
20
+ 1. Get the full error list first. Run `npm run build` (the project's `build` script).
21
+ Only fall back to `npx tsc --noEmit` if the project has no `build` script. Capture
22
+ EVERY error line. Do not guess — read the actual compiler output.
23
+ 2. Group errors by file. Most real projects concentrate errors in a few files.
24
+ Present the grouped summary to the user and STOP to confirm scope before editing
25
+ (audit/review etiquette: list findings, then ask which to fix).
26
+ 3. Once confirmed, FIX FILE-SCOPED. For each target file:
27
+ - Read the file, make the minimal change (rename an unused param to `_x`,
28
+ switch `obj.key` to `obj['key']` when the type is an index signature, etc.).
29
+ - The syntax checker will NOT false-revert a valid edit just because the file
30
+ already had other errors — it diffs pre- vs post-edit diagnostics. So fix one
31
+ file at a time confidently; a valid edit won't be blamed for pre-existing errors.
32
+ 4. Re-run `npm run build` after each file (or each small batch) to confirm the
33
+ errors for that file are gone. Iterate until the build is clean.
34
+ 5. Run the test suite (`npm test`) to confirm nothing broke. Report the final state.
35
+
36
+ ## Context-window discipline (important)
37
+ - Break the work into SPRINTS: e.g. Sprint 1 = fix `validation.ts`, Sprint 2 =
38
+ fix `server.ts`. After each sprint, the build gets greener and you checkpoint.
39
+ - Keep each turn's edits SMALL (one file, few lines). Do NOT dump a 100-line rewrite
40
+ of a file that only needed 3 lines changed — that is what burns context and trips
41
+ the patch tooling.
42
+ - Use the `todo` tool to track sprints so progress survives across turns.
43
+
44
+ ## Common error patterns
45
+ - `TS6133` unused variable/param → prefix with `_` (respects `noUnusedLocals`/`noUnusedParameters`).
46
+ - `TS4111` / `noPropertyAccessFromIndexSignature` → use bracket access `prompt['id']`
47
+ instead of dot access `prompt.id` when the type is `Record<string, unknown>`.
48
+ - `exactOptionalPropertyTypes` → don't assign `string | undefined` to an optional
49
+ `id?: string`; assign conditionally (`if (id !== undefined) result.id = id;`).
50
+ - `TS2345` type mismatch → fix the actual type, don't cast with `as any` (casts hide
51
+ real bugs and the project lints against `any`).
52
+
53
+ ## Verify
54
+ - `npm run build` exits 0.
55
+ - `npm test` passes.
56
+ - State the final error count (0) and which files you touched.
@@ -0,0 +1,235 @@
1
+ ---
2
+ name: grade-and-fix-daedalus
3
+ description: How to grade a Daedalus run (or pasted agent transcript), root-cause the failure, and ship the fix to Daedalus CORE as a stacked PR — without modifying the prompt-vault sandbox (read-only grading). Covers recurring bug archetypes (Unicode punctuation patch mismatch, syntax-vs-type mislabel, emoji box misalignment, half-edited files, loop/false-completion guards, and the v3.25.0 pre-flight dependency gate where "every patch reverts" is the prevention gate working, not a broken guardrail). Includes tsx repro and the verified ship flow.
4
+ trigger: fix this daedalus bug|why did the patch fail|grade this run|ship the fix|every patch reverts|patch keeps reverting|type error introduced by patch|pre-flight|prevention over revert|daedalus core resilience
5
+ safety: instructions
6
+ ---
7
+
8
+ # Grade a Daedalus run and ship the core fix (stacked PR)
9
+
10
+ This skill covers how to grade a Daedalus run (or read a pasted agent transcript),
11
+ root-cause the failure, fix it in `src/...`, and ship it as a stacked PR. The
12
+ prompt-vault sandbox stays READ-ONLY except for one user-explicit exception.
13
+
14
+ ## Hard rules (standing)
15
+
16
+ - **Grade, don't fix the sandbox.** `prompt-vault` (+ `social_media_manager`) are
17
+ TEST-ONLY. You READ/GRADE them. You do NOT edit them to "help" Daedalus — that
18
+ defeats the purpose. The ONE exception: a user-explicit "just this once, fix this
19
+ error in the test project" — otherwise the sandbox is passive.
20
+ - **Fixes go to Daedalus CORE** (`src/...`), never the sandbox. A graded run that
21
+ exposes a guardrail gap is a core bug; ship it as a PR.
22
+ - **Run Daedalus from SOURCE** (`npx tsx src/index.ts`) — the published bin is stale.
23
+ Banner version lagging package.json is cosmetic.
24
+ - **`search_files` FAILS on `D:\` paths** (MSYS IO error). Use `terminal` with
25
+ `grep`/`ls`/`git` for anything under D:\.
26
+ - **Verify with real tool calls, not theory.** Reproduce the bug by importing the
27
+ actual function and calling it (tsx repro), then prove the fix the same way. Do
28
+ NOT assert "the guard is wrong" without a repro.
29
+ - **Skills are auto-discovered** from this `src/skills/` dir (see `src/skills/index.ts`):
30
+ any subdir with a `SKILL.md` whose frontmatter has a `trigger` field is matched
31
+ keyword-style against the user's request and injected into the prompt. Keep the
32
+ `trigger` field populated with pipe-separated phrases.
33
+
34
+ ## Recurring bug archetypes (with exact fixes that shipped)
35
+
36
+ These are the failure modes seen grading real Daedalus runs. Each maps to a specific
37
+ root cause and a specific fix location.
38
+
39
+ ### 1. Patch fails on a Unicode punctuation mismatch (en-dash vs hyphen)
40
+ - **Symptom:** agent's `old_string` uses a regular hyphen `-` but the file has an
41
+ en-dash `–` (U+2013) in a comment; Daedalus reports "Old string not found" and the
42
+ edit never lands. Looks like "every patch fails" but it's a 1-char invisible mismatch.
43
+ - **Root cause:** `patchFile` (`src/tools/builtin/files.ts`) matches `old_string`
44
+ exactly, and the fuzzy fallback `fuzzyWhitespacePatch` only normalizes whitespace,
45
+ not Unicode punctuation. en-dash/hyphen/smart-quotes/NBSP are invisible to a human
46
+ but distinct bytes.
47
+ - **Fix (v3.20.7):** added `normalizeUnicode()` in `patch-utils.ts` mapping en/em-dash
48
+ -> hyphen, smart quotes -> straight, NBSP -> space (all 1:1 so original bytes stay
49
+ intact), folded into `normalizeWhitespace()`; the exact `indexOf` path in `files.ts`
50
+ also tries a unicode-normalized match. Mappings must be 1:1 (no length-changing
51
+ entries like ellipsis `…`->`...`, or the index-slice math breaks).
52
+
53
+ ### 2. "Syntax error introduced by patch" is actually a TYPE error
54
+ - **Symptom:** user sees "every one-line change is a syntax error" and is confused.
55
+ - **Root cause:** `syntaxCheck` returns diagnostics that include TypeScript type errors
56
+ (TS2304 "Cannot find name 'X'", TS2322, etc.) — genuine TYPE errors, not syntax — but
57
+ `files.ts` wrapped them all with a hardcoded `"Syntax error introduced by patch"`
58
+ prefix. A type error (file parses fine, a downstream reference broke) is NOT a syntax
59
+ error (structurally broken file). The mislabel is what made it look like the model
60
+ couldn't change one line.
61
+ - **Fix (v3.20.8):** `syntaxCheck` now self-labels — genuine transpile/parse breaks
62
+ (.js `--check`, the transpile stage) return `"Syntax error introduced by patch —
63
+ reverted."`; tsc type-check failures return `"Type error introduced by patch —
64
+ reverted."`. JSON/YAML keep their specific labels. `formatDiagnostic` now emits the
65
+ FULL file path + line:col (was basename only). `files.ts` no longer prepends the
66
+ misleading prefix.
67
+
68
+ ### 3. Assistant box misaligned / reply spills outside the frame
69
+ - **Symptom:** the `⚡ Daedalus` box top/bottom rules don't line up; long body lines
70
+ overflow the right edge.
71
+ - **Root cause:** (a) the `⚡` emoji is 2 terminal cells wide but was counted as 1, so
72
+ the top border's dash fill overshot by a column; (b) padding used `string.length`
73
+ instead of display (cell) width, so wide glyphs under/over-padded; (c) curved corners
74
+ (╭╮╰╯) + side rails (│) made the alignment math fragile.
75
+ - **Fix (v3.20.9, per user request for "two straight lines, no curves, no side rails"):**
76
+ dropped the curves and rails; both rules + body lines now build from a single
77
+ `displayWidth()`-aware helper (`isWide()` flags CJK/emoji/wide as 2 cells,
78
+ box-drawing stays 1) so everything measures exactly `_lastBoxW` cells. Bottom stat
79
+ line truncates with `…` and reserves 1 cell for it.
80
+
81
+ ### 4. Half-edited file causes repeated "port is undefined" / type errors
82
+ - **Symptom:** a prior failed run left the file mid-edit (e.g. signature changed but
83
+ the old `if (port) { app.listen }` block + call site still reference `port`). Any new
84
+ patch to the signature fails type-check; the guard correctly reverts, and the model
85
+ loops on a stale view.
86
+ - **Root cause:** NOT a guard bug — the guard correctly refused a build-breaking patch.
87
+ The trap is the half-edited disk state. Fixing it means either (a) re-reading the
88
+ current file and fixing all references together, or (b) the v3.20.5 removed-symbol
89
+ hint, which detects when an introduced TS2304 refers to a symbol the patch deleted
90
+ and says exactly which lines still reference it.
91
+ - **Lesson:** when "every patch fails," first `git status`/`git diff` the sandbox to
92
+ check for a half-applied state before assuming the guard is broken.
93
+
94
+ ### 5. Loop / false-completion (the v3.20.4 guards)
95
+ - Patch-failure streak breaker: global `context.patchFailureTotal` counter (not
96
+ per-path) trips at 3 -> `[PATCH CIRCUIT BREAKER]` hard stop, forces terminal
97
+ turn-close.
98
+ - On-disk completion guard (`detectFalseCompletionOnDisk` in `completion-guard.ts`): if
99
+ the agent claims "fixed X" but `git diff`/disk shows no change, block the turn with a
100
+ SYSTEM WARNING. This is the strict false-report mandate — never accept an empty diff
101
+ "done."
102
+
103
+ ### 6. "Every patch reverts" — it's the PRE-FLIGHT gate working (prevention over revert)
104
+ - **Symptom:** user reports "Daedalus can't edit a single file without an error / every
105
+ patch throws a type error and reverts." Looks like the patch tool is broken. It is NOT.
106
+ - **Root cause (the helmet incident, v3.25.0):** a patch imports a dependency whose
107
+ types don't resolve in the project — e.g. `helmet@8` installed but `@types/helmet`
108
+ MISSING. The `import helmet from 'helmet'` is therefore untyped (`any`), and under
109
+ `strict` the options object literal (`policy: 'require-corp'`, etc.) generates real TS
110
+ errors that the patch DID introduce. The post-write `syntaxCheck` correctly reverts.
111
+ The agent then re-proposes the SAME broken diff 3x, trips the circuit breaker, and
112
+ sometimes goes on an unrelated side-quest (installing swagger, running bare `tsc`
113
+ which throws its own noise).
114
+ - **The real fix is PREVENTION, not revert (standing mandate: "clean code from the
115
+ get-go, resolve issues before patching").** Shipped in v3.25.0 as
116
+ `preflightDependencyCheck()` in `src/tools/builtin/patch-utils.ts`, wired into all
117
+ three write paths in `files.ts` (writeFile, patchFile autoapply-all, patchFile
118
+ interactive) — BEFORE the disk write + post-write `syntaxCheck`. It scans the proposed
119
+ content's import specifiers and resolves each against the project's installed
120
+ `node_modules` + tsconfig (bundled `types`/`typings`, `@types/<pkg>` companion, or a
121
+ `@types/*` pkg). If a dependency has no usable type declarations, the patch is REFUSED
122
+ PRE-WRITE with an actionable fix: `npm install --save-dev @types/<pkg>`, then re-patch.
123
+ It never touches disk, never reverts, never hits the circuit breaker. Also added a
124
+ system-prompt rule "Resolve dependencies BEFORE patching" telling the agent to verify
125
+ types resolve and install missing `@types` as a PREREQUISITE patch first.
126
+ - **Grading takeaway:** when a user says "every patch fails," FIRST check whether it's
127
+ the pre-flight gate catching a missing `@types` / missing dep (gate working correctly)
128
+ vs. a genuinely broken guardrail. The pre-flight message names the exact missing
129
+ package + the install command. If the agent is looping 3x into the breaker, the bug is
130
+ in the agent's RECOVERY logic (re-proposing the same broken diff instead of resolving
131
+ the dependency), which is fixed by this gate — not by weakening the revert net.
132
+ - **Pinned test cases (in `src/tools/builtin/patch-utils.test.ts`):** resolvable import
133
+ passes; missing-types flagged pre-write with `npm install --save-dev @types/<pkg>`
134
+ hint; `@types` companion resolves; relative imports ignored.
135
+
136
+ ## Step 1 — Reproduce the bug against REAL code (don't theorize)
137
+
138
+ Write a throwaway `.mts` repro that imports the actual function and calls it. Example
139
+ for the en-dash / type-error cases:
140
+
141
+ ```ts
142
+ // repro.mts (run: npx tsx repro.mts ; then rm -f repro.mts)
143
+ import { patchFile } from './src/tools/builtin/files.js';
144
+ import fs from 'fs';
145
+ const file = 'D:/prompt-vault/src/server.ts';
146
+ const ctx: any = {
147
+ sessionId: 'r', projectRoot: 'D:/prompt-vault', projectHash: 'x', activeFiles: new Map(),
148
+ agentRole: 'test', abortSignal: new AbortController().signal, autoApplyEdits: 'all',
149
+ patchHistory: [], patchFailureStreak: new Map(), patchFailureTotal: 0,
150
+ sessionReadCache: new Map(),
151
+ };
152
+ // case: remove param but leave usages -> should report TYPE error, not syntax
153
+ const r = await patchFile({ path: file, old_string: 'export function createApp(): Application {',
154
+ new_string: 'export function createApp(): Application {' }, ctx);
155
+ console.log((r.error || '').split('\n').slice(0, 4).join('\n'));
156
+ ```
157
+
158
+ For the box: capture `console.log` into an array, render a block with a forced
159
+ `process.stdout.columns = 80`, and assert `displayWidth(line) === 80 - 6` for both
160
+ rules.
161
+
162
+ **Keep repro files SMALL** — the patch tool streams time out on large payloads. If a
163
+ `patch`/`write_file` call is large, split it into multiple smaller calls.
164
+
165
+ ## Step 2 — Fix in core, keep tests green
166
+
167
+ - Match Daedalus conventions: named exports only, `.js` ESM import extensions, no
168
+ source comments unless necessary, Zod config schemas. Tests co-located as
169
+ `*.test.ts`, vitest.
170
+ - Add/update a unit test that pins the exact behavior (e.g. en-dash patch now matches;
171
+ type error labeled "Type error"; box rules exactly `_lastBoxW`). The alignment test
172
+ must assert CELL width (`displayWidth`), not JS `.length` — emoji make `.length`
173
+ wrong.
174
+ - Verify locally BEFORE pushing:
175
+ ```bash
176
+ npx tsc --noEmit # expect 0 errors
177
+ npm run lint # 0 errors (pre-existing warnings are fine)
178
+ npm test # full suite green
179
+ ```
180
+
181
+ ## Step 3 — Ship as a stacked PR (verified flow)
182
+
183
+ Use the `daedalus-stacked-prs` skill for the mechanics. The proven sequence:
184
+
185
+ ```bash
186
+ cd D:/Daedalus
187
+ git checkout -b fix/<short-slug>
188
+ # edit src/... + tests
189
+ npx tsc --noEmit && npm run lint && npm test # gate locally first
190
+ git add <files> && git commit -q -m "fix(tools): <conventional commit, single scope>
191
+
192
+ <why + what + verification, ~3 short paras>"
193
+ git push -u origin fix/<short-slug>
194
+ gh pr create --title "fix(tools): <same as commit subject>" --body "<PR body>"
195
+ # wait for ALL THREE CI lanes, not just one:
196
+ for i in $(seq 1 15); do
197
+ pend=$(gh pr checks <N> 2>&1 | grep -c pending); [ "$pend" -eq 0 ] && break; sleep 12
198
+ done
199
+ gh pr checks <N> # confirm Test (ubuntu) + Test (windows) + Test (macos) all pass
200
+ gh pr merge <N> --squash
201
+ git fetch origin && git checkout main && git reset --hard origin/main
202
+ git branch -D fix/<short-slug>; git push origin --delete fix/<short-slug>
203
+ # wait for semantic-release, then confirm the tag + npm version:
204
+ for i in $(seq 1 20); do
205
+ st=$(gh run list --repo bgill55/daedalus --limit 1 --json status --jq '.[0].status')
206
+ [ "$st" = completed ] && break; sleep 10
207
+ done
208
+ git fetch --tags origin; npm view daedalus-cli version
209
+ ```
210
+
211
+ **CI facts:** `Test (windows-latest)` has been FLAKY in the past (terminal/API tests,
212
+ env-only, no model server) — if it's red but the other two lanes are green and the
213
+ failure is clearly env-only, re-run that single job. Don't merge on a red core test.
214
+ **Release:** `gh pr merge --squash` does NOT auto-trigger release — after merge, the
215
+ `release.yml` workflow runs `npx semantic-release` and publishes `daedalus-cli`. Confirm
216
+ the new `v3.2X.Y` tag + npm version. Stacked PRs are FREE (all repos) — one stack +
217
+ single async merge = one release.
218
+
219
+ ## Pitfalls
220
+
221
+ - Do NOT modify the prompt-vault sandbox (except the one user-approved exception). Grade
222
+ read-only; ship to core.
223
+ - The "Syntax error" label is misleading by design-history — if you see it, check whether
224
+ it's actually a TS type error (the v3.20.8 fix separates them). If a user reports
225
+ "every patch is a syntax error," first check for a half-edited file (archetype 4).
226
+ - Unicode dash/quote mismatches are invisible in a paste — verify the actual file bytes
227
+ with `sed -n 'Np' file | cat -A` or `hexdump` before blaming the patch tool.
228
+ - `patch`/`write_file` calls have a stream timeout on large payloads — split big edits
229
+ into multiple small calls.
230
+ - Box alignment must be measured in CELL width (`displayWidth`), never JS `.length` —
231
+ emoji (⚡) is 2 cells.
232
+ - PR title MUST be a valid conventional commit with a single scope or the
233
+ `PR Title (conventional-commits)` CI check fails.
234
+ - `git reset --hard` / `git push --delete` are flagged by smart approval — that's
235
+ expected; they're part of the clean-branch flow.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "daedalus-cli",
3
- "version": "3.25.0",
3
+ "version": "3.25.1",
4
4
  "description": "Local-first AI coding CLI with embedded model router, multi-agent orchestration, and codebase indexing",
5
5
  "type": "module",
6
6
  "bin": {
@@ -21,7 +21,7 @@
21
21
  "start": "tsx src/index.ts",
22
22
  "bot": "tsx src/bot/index.ts",
23
23
  "dev": "tsx watch src/index.ts",
24
- "build": "tsc",
24
+ "build": "tsc && node scripts/copy-skills.mjs",
25
25
  "lint": "eslint src --ext .ts",
26
26
  "prepublishOnly": "npm run build",
27
27
  "test": "vitest run",