@drewpayment/mink 0.1.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 (72) hide show
  1. package/README.md +347 -0
  2. package/package.json +32 -0
  3. package/src/cli.ts +176 -0
  4. package/src/commands/bug-search.ts +32 -0
  5. package/src/commands/config.ts +109 -0
  6. package/src/commands/cron.ts +295 -0
  7. package/src/commands/daemon.ts +46 -0
  8. package/src/commands/dashboard.ts +21 -0
  9. package/src/commands/designqc.ts +160 -0
  10. package/src/commands/detect-waste.ts +81 -0
  11. package/src/commands/framework-advisor.ts +52 -0
  12. package/src/commands/init.ts +159 -0
  13. package/src/commands/post-read.ts +123 -0
  14. package/src/commands/post-write.ts +157 -0
  15. package/src/commands/pre-read.ts +109 -0
  16. package/src/commands/pre-write.ts +136 -0
  17. package/src/commands/reflect.ts +39 -0
  18. package/src/commands/restore.ts +31 -0
  19. package/src/commands/scan.ts +101 -0
  20. package/src/commands/session-start.ts +21 -0
  21. package/src/commands/session-stop.ts +115 -0
  22. package/src/commands/status.ts +152 -0
  23. package/src/commands/update.ts +121 -0
  24. package/src/core/action-log.ts +341 -0
  25. package/src/core/backup.ts +122 -0
  26. package/src/core/bug-memory.ts +223 -0
  27. package/src/core/cron-parser.ts +94 -0
  28. package/src/core/daemon.ts +152 -0
  29. package/src/core/dashboard-api.ts +280 -0
  30. package/src/core/dashboard-server.ts +580 -0
  31. package/src/core/description.ts +232 -0
  32. package/src/core/design-eval/capture.ts +269 -0
  33. package/src/core/design-eval/route-detect.ts +165 -0
  34. package/src/core/design-eval/server-detect.ts +91 -0
  35. package/src/core/framework-advisor/catalog.ts +360 -0
  36. package/src/core/framework-advisor/decision-tree.ts +287 -0
  37. package/src/core/framework-advisor/generate.ts +132 -0
  38. package/src/core/framework-advisor/migration-prompts.ts +502 -0
  39. package/src/core/framework-advisor/validate.ts +137 -0
  40. package/src/core/fs-utils.ts +30 -0
  41. package/src/core/global-config.ts +74 -0
  42. package/src/core/index-store.ts +72 -0
  43. package/src/core/learning-memory.ts +120 -0
  44. package/src/core/paths.ts +86 -0
  45. package/src/core/pattern-engine.ts +108 -0
  46. package/src/core/project-id.ts +19 -0
  47. package/src/core/project-registry.ts +64 -0
  48. package/src/core/reflection.ts +256 -0
  49. package/src/core/scanner.ts +99 -0
  50. package/src/core/scheduler.ts +352 -0
  51. package/src/core/seed.ts +239 -0
  52. package/src/core/session.ts +128 -0
  53. package/src/core/stdin.ts +13 -0
  54. package/src/core/task-registry.ts +202 -0
  55. package/src/core/token-estimate.ts +36 -0
  56. package/src/core/token-ledger.ts +185 -0
  57. package/src/core/waste-detection.ts +214 -0
  58. package/src/core/write-exclusions.ts +24 -0
  59. package/src/types/action-log.ts +20 -0
  60. package/src/types/backup.ts +6 -0
  61. package/src/types/bug-memory.ts +24 -0
  62. package/src/types/config.ts +59 -0
  63. package/src/types/dashboard.ts +104 -0
  64. package/src/types/design-eval.ts +64 -0
  65. package/src/types/file-index.ts +38 -0
  66. package/src/types/framework-advisor.ts +97 -0
  67. package/src/types/hook-input.ts +27 -0
  68. package/src/types/learning-memory.ts +36 -0
  69. package/src/types/scheduler.ts +82 -0
  70. package/src/types/session.ts +50 -0
  71. package/src/types/token-ledger.ts +43 -0
  72. package/src/types/waste-detection.ts +21 -0
package/README.md ADDED
@@ -0,0 +1,347 @@
1
+ # Mink
2
+
3
+ A hidden presence that moves alongside the developer.
4
+
5
+ Mink is a lightweight companion for AI coding assistants like [Claude Code](https://claude.ai/code). It hooks into the assistant's lifecycle events to reduce token waste, enforce learned rules, and build a portable knowledge base across all your projects.
6
+
7
+ ## Why Mink?
8
+
9
+ AI coding assistants consume tokens every time they read a file, write code, or reason about your project. Much of this is redundant: re-reading files already seen, repeating mistakes that were already corrected, and lacking context that was available in a previous session.
10
+
11
+ Mink intercepts these lifecycle events and maintains structured state so the assistant can work smarter:
12
+
13
+ - **Track what was already read** and warn before redundant re-reads
14
+ - **Remember past mistakes** and surface them before they're repeated
15
+ - **Enforce learned rules** extracted from corrections you've already given
16
+ - **Log every action** with token cost estimates so you can see where tokens go
17
+ - **Detect token waste** and surface patterns of inefficiency
18
+ - **Run background tasks** on a schedule to keep state fresh
19
+ - **Visualize everything** in a real-time web dashboard
20
+ - **Evaluate UI designs** with automated multi-viewport screenshots
21
+ - **Advise on frameworks** with a decision tree and migration guides
22
+ - **Build a cross-project wiki** that accumulates knowledge across all your projects
23
+
24
+ ## How It Works
25
+
26
+ Mink registers as a set of [Claude Code hooks](https://docs.anthropic.com/en/docs/claude-code/hooks) that fire on key lifecycle events. Each hook is a lightweight CLI call that reads and updates JSON state files stored in `~/.mink/`.
27
+
28
+ ```
29
+ Session Start Read a File Write a File Session Stop
30
+ | | | |
31
+ v v v v
32
+ Create fresh Check file index Check learning Build summary
33
+ session state Track read count memory rules Calculate savings
34
+ Log to action log Warn on repeats Surface past bugs Append to ledger
35
+ Estimate tokens Estimate tokens Emit reminders
36
+ ```
37
+
38
+ All state lives in `~/.mink/` -- nothing is stored in your project repository.
39
+
40
+ ## Features
41
+
42
+ ### Core State Management
43
+ - **Session Lifecycle** — Tracks session start/stop, token counts, and file operations
44
+ - **File Index** — Scans and indexes project files with descriptions and metadata
45
+ - **Learning Memory** — Four-section knowledge store: preferences, learnings, do-not-repeat, and decision log
46
+ - **Token Ledger** — Persistent usage history with per-session breakdowns and savings calculations
47
+
48
+ ### Intelligent Hooks
49
+ - **Read Intelligence** — Tracks file reads, warns on redundant re-reads, estimates token cost
50
+ - **Write Enforcement** — Enforces learned rules on writes, surfaces past bugs for relevant files
51
+
52
+ ### Knowledge & Analytics
53
+ - **Bug Memory** — Tracks bugs, fixes, root causes, and tags for searchable history
54
+ - **Action Log** — Human-readable chronological log of all session activity
55
+ - **Waste Detection** — Identifies patterns of token waste (repeated reads, large file scans, etc.)
56
+
57
+ ### Automation
58
+ - **Background Scheduler** — Daemon process with cron-based task scheduling, retry logic with exponential backoff, and a dead letter queue for failed tasks
59
+ - **Built-in Tasks** — File index rescan, action log consolidation, waste detection, learning memory reflection, and project suggestions — all on configurable schedules
60
+
61
+ ### Interfaces
62
+ - **CLI** — 20+ commands covering lifecycle hooks, state management, scheduling, configuration, backup/restore, and more
63
+ - **Real-time Dashboard** — Web UI with 10 panels, SSE live updates, light/dark themes, virtual scrolling, and interactive charts
64
+
65
+ ### Advanced
66
+ - **Design Evaluation** — Automated multi-viewport screenshot capture with server and route detection (uses Puppeteer)
67
+ - **Framework Advisor** — Decision tree, framework catalog, comparison matrix, and migration prompts for UI framework selection
68
+
69
+ ## Current Status
70
+
71
+ Specs 1–14 are fully implemented and tested. Remaining specs (wiki, test plan) are designed and documented in `specs/`.
72
+
73
+ | Domain | Specs | Status |
74
+ |--------|-------|--------|
75
+ | Core | Session Lifecycle, File Index, Learning Memory, Token Ledger | Implemented |
76
+ | Hooks | Read Intelligence, Write Enforcement | Implemented |
77
+ | Knowledge | Bug Memory, Action Log | Implemented |
78
+ | Analytics | Waste Detection | Implemented |
79
+ | Automation | Background Scheduler | Implemented |
80
+ | Interfaces | CLI Commands, Dashboard | Implemented |
81
+ | Advanced | Design Evaluation, Framework Advisor | Implemented |
82
+ | Wiki | Cross-Project Wiki | Designed |
83
+ | Quality | Test Plan | Designed |
84
+
85
+ ## Installation
86
+
87
+ ### Prerequisites
88
+
89
+ - [Node.js](https://nodejs.org/) 18+ or [Bun](https://bun.sh/) (recommended for faster hook execution)
90
+ - [Claude Code](https://claude.ai/code)
91
+
92
+ ### Install
93
+
94
+ ```bash
95
+ # With Bun (recommended)
96
+ bun add -g mink
97
+
98
+ # With npm
99
+ npm install -g mink
100
+ ```
101
+
102
+ ### Initialize in a project
103
+
104
+ From your project root:
105
+
106
+ ```bash
107
+ mink init
108
+ ```
109
+
110
+ This will:
111
+
112
+ 1. Detect your runtime (Bun if available, otherwise Node.js)
113
+ 2. Create your project's state directory at `~/.mink/projects/<project-slug>/`
114
+ 3. Register Mink's hooks in `.claude/settings.json`
115
+
116
+ ```
117
+ [mink] initialized
118
+ project: my-project-a3f2b1
119
+ state: /Users/you/.mink/projects/my-project-a3f2b1
120
+ runtime: bun
121
+ hooks: /Users/you/dev/my-project/.claude/settings.json
122
+ ```
123
+
124
+ That's it. Mink runs automatically in the background during your Claude Code sessions.
125
+
126
+ ### Verify it's working
127
+
128
+ Start a new Claude Code session in your project. Mink will create a `session.json` in your project's state directory:
129
+
130
+ ```bash
131
+ cat ~/.mink/projects/*/session.json
132
+ ```
133
+
134
+ You should see a fresh session state with a unique ID, timestamp, and zeroed counters.
135
+
136
+ ## Architecture
137
+
138
+ ### State Directory
139
+
140
+ ```
141
+ ~/.mink/
142
+ ├── config.json # Global user configuration
143
+ ├── projects/
144
+ │ └── my-project-a3f2b1/
145
+ │ ├── session.json # Ephemeral session state
146
+ │ ├── file-index.json # File descriptions and metadata
147
+ │ ├── learning-memory.md # Accumulated project knowledge (4 sections)
148
+ │ ├── token-ledger.json # Persistent usage history
149
+ │ ├── action-log.md # Human-readable action history
150
+ │ ├── bug-memory.json # Past bugs, fixes, and root causes
151
+ │ ├── scheduler.json # Scheduler manifest and task state
152
+ │ ├── daemon.pid # Background daemon PID
153
+ │ ├── backups/ # State backups for restore
154
+ │ └── screenshots/ # Design evaluation captures
155
+ ```
156
+
157
+ ### Project Identification
158
+
159
+ Each project gets a deterministic, human-readable identifier: the slugified directory name plus a 6-character hash of the absolute path. This means:
160
+
161
+ - `my-project` in `/Users/drew/dev/` becomes `my-project-a3f2b1`
162
+ - `my-project` in `/Users/drew/work/` gets a different hash, avoiding collisions
163
+ - Moving a project changes its ID (re-run `mink init`)
164
+
165
+ ### Crash Safety
166
+
167
+ All JSON writes use atomic temp-file-then-rename. If the process dies mid-write, only the `.tmp` file is affected -- the original state file remains intact.
168
+
169
+ ### Hook Integration
170
+
171
+ Mink hooks into Claude Code via `.claude/settings.json`:
172
+
173
+ | Claude Code Event | Mink Command | Purpose |
174
+ |-------------------|--------------|---------|
175
+ | `SessionStart` | `mink session-start` | Create fresh session state |
176
+ | `Stop` | `mink session-stop` | Finalize session, calculate savings |
177
+ | `PreToolUse` (Read) | `mink pre-read` | Check file index, warn on repeat reads |
178
+ | `PostToolUse` (Read) | `mink post-read` | Track read, estimate tokens |
179
+ | `PreToolUse` (Write/Edit) | `mink pre-write` | Enforce learned rules, surface past bugs |
180
+ | `PostToolUse` (Write/Edit) | `mink post-write` | Log write, update file index |
181
+
182
+ ## Development
183
+
184
+ ### Setup
185
+
186
+ ```bash
187
+ git clone git@github.com:drewpayment/mink.git
188
+ cd mink
189
+ bun install
190
+ ```
191
+
192
+ ### Run tests
193
+
194
+ ```bash
195
+ # Run all tests
196
+ bun test
197
+
198
+ # Watch mode
199
+ bun test --watch
200
+
201
+ # Run a specific test file
202
+ bun test tests/unit/session.test.ts
203
+ ```
204
+
205
+ ### Project structure
206
+
207
+ ```
208
+ mink/
209
+ ├── src/
210
+ │ ├── cli.ts # Entry point, command routing (20+ commands)
211
+ │ ├── commands/ # CLI command implementations
212
+ │ │ ├── init.ts # mink init — runtime detection, hook wiring
213
+ │ │ ├── session-start.ts # Hook: create fresh session state
214
+ │ │ ├── session-stop.ts # Hook: finalize session, emit reminders
215
+ │ │ ├── pre-read.ts # Hook: file read intelligence
216
+ │ │ ├── post-read.ts # Hook: post-read tracking
217
+ │ │ ├── pre-write.ts # Hook: write enforcement
218
+ │ │ ├── post-write.ts # Hook: post-write tracking
219
+ │ │ ├── status.ts # Project health display
220
+ │ │ ├── scan.ts # Force full file index rescan
221
+ │ │ ├── config.ts # Global configuration management
222
+ │ │ ├── cron.ts # Scheduled task management
223
+ │ │ ├── daemon.ts # Background daemon control
224
+ │ │ ├── dashboard.ts # Real-time web dashboard
225
+ │ │ ├── designqc.ts # Design evaluation screenshots
226
+ │ │ ├── framework-advisor.ts # Framework advisor CLI
227
+ │ │ ├── detect-waste.ts # Token waste analysis
228
+ │ │ ├── bug-search.ts # Bug log search
229
+ │ │ ├── reflect.ts # Learning memory reflection
230
+ │ │ ├── update.ts # Cross-project update
231
+ │ │ └── restore.ts # State restoration from backup
232
+ │ ├── core/ # Core library modules
233
+ │ │ ├── session.ts # Session state CRUD, summary, savings
234
+ │ │ ├── paths.ts # ~/.mink path resolution
235
+ │ │ ├── project-id.ts # Slug + hash project ID generation
236
+ │ │ ├── fs-utils.ts # Atomic JSON write, safe read
237
+ │ │ ├── index-store.ts # File index management
238
+ │ │ ├── scanner.ts # Project file scanner
239
+ │ │ ├── learning-memory.ts # Learning memory operations
240
+ │ │ ├── token-ledger.ts # Token usage tracking
241
+ │ │ ├── action-log.ts # Action log management
242
+ │ │ ├── bug-memory.ts # Bug memory operations
243
+ │ │ ├── waste-detection.ts # Waste pattern detection
244
+ │ │ ├── pattern-engine.ts # Learned pattern matching
245
+ │ │ ├── scheduler.ts # Cron-based task scheduler
246
+ │ │ ├── daemon.ts # Daemon process management
247
+ │ │ ├── cron-parser.ts # Cron expression parsing
248
+ │ │ ├── task-registry.ts # Built-in task definitions
249
+ │ │ ├── dashboard-server.ts # Dashboard HTTP server
250
+ │ │ ├── dashboard-api.ts # Dashboard REST API + SSE
251
+ │ │ ├── design-eval/ # Screenshot capture, route/server detection
252
+ │ │ ├── framework-advisor/ # Catalog, decision tree, migration prompts
253
+ │ │ └── ... # Global config, backup, reflection, etc.
254
+ │ ├── dashboard/ # Embedded dashboard UI (HTML/CSS/JS generation)
255
+ │ │ ├── get-dashboard-html.ts # Main HTML assembly
256
+ │ │ ├── panel-*.ts # 10 panel implementations
257
+ │ │ ├── css-*.ts # Base styles and themes
258
+ │ │ └── js-*.ts # Charts, SSE, virtual scroll, search
259
+ │ └── types/ # TypeScript interfaces
260
+ ├── tests/
261
+ │ ├── unit/ # 35+ unit test files
262
+ │ └── integration/ # 15+ integration test files
263
+ ├── specs/ # Feature specifications (technology-agnostic)
264
+ └── docs/ # Design docs and implementation plans
265
+ ```
266
+
267
+ ## Contributing
268
+
269
+ ### Specs-first development
270
+
271
+ Mink follows a specs-first approach. All feature specifications live in `specs/` and describe **what** to build, not how. Each spec follows a consistent format: Overview, Capabilities, Acceptance Criteria (Given/When/Then), Edge Cases, and Test Requirements.
272
+
273
+ Before implementing a new feature:
274
+
275
+ 1. Read the relevant spec in `specs/`
276
+ 2. Check if a design doc exists in `docs/superpowers/specs/`
277
+ 3. Check if an implementation plan exists in `docs/superpowers/plans/`
278
+
279
+ ### Guidelines
280
+
281
+ - **TypeScript** with strict mode enabled
282
+ - **Bun** as runtime, test runner, and package manager
283
+ - **TDD** -- write failing tests first, then implement
284
+ - **Atomic commits** -- one logical change per commit
285
+ - **No state in project repos** -- all Mink state goes in `~/.mink/`
286
+ - **Crash-safe I/O** -- use `atomicWriteJson` from `src/core/fs-utils.ts` for all JSON writes
287
+ - **Graceful degradation** -- missing or corrupt state files should log warnings, not crash
288
+
289
+ ### Running the full lifecycle locally
290
+
291
+ ```bash
292
+ # Initialize mink for this repo
293
+ bun src/cli.ts init
294
+
295
+ # Simulate a session
296
+ bun src/cli.ts session-start
297
+ cat ~/.mink/projects/mink-*/session.json
298
+
299
+ bun src/cli.ts session-stop
300
+ cat ~/.mink/projects/mink-*/session.json
301
+
302
+ # Start the dashboard
303
+ bun src/cli.ts dashboard --port 3333
304
+
305
+ # Start the background daemon
306
+ bun src/cli.ts daemon start
307
+
308
+ # Check project status
309
+ bun src/cli.ts status
310
+
311
+ # Run a waste detection scan
312
+ bun src/cli.ts detect-waste
313
+ ```
314
+
315
+ ### Adding a new spec implementation
316
+
317
+ Each spec follows this workflow:
318
+
319
+ 1. **Design** -- Brainstorm approaches, document decisions in `docs/superpowers/specs/`
320
+ 2. **Plan** -- Break down into bite-sized tasks in `docs/superpowers/plans/`
321
+ 3. **Implement** -- Follow the plan task by task using TDD
322
+ 4. **Review** -- Verify spec compliance and code quality
323
+
324
+ ## Specifications
325
+
326
+ | # | Spec | Domain | Status |
327
+ |---|------|--------|--------|
328
+ | 01 | [Session Lifecycle](./specs/01-session-lifecycle.md) | Core | Implemented |
329
+ | 02 | [File Index](./specs/02-file-index.md) | Core | Implemented |
330
+ | 03 | [Learning Memory](./specs/03-learning-memory.md) | Core | Implemented |
331
+ | 04 | [Token Ledger](./specs/04-token-ledger.md) | Core | Implemented |
332
+ | 05 | [Read Intelligence](./specs/05-read-intelligence.md) | Hooks | Implemented |
333
+ | 06 | [Write Enforcement](./specs/06-write-enforcement.md) | Hooks | Implemented |
334
+ | 07 | [Bug Memory](./specs/07-bug-memory.md) | Knowledge | Implemented |
335
+ | 08 | [Action Log](./specs/08-action-log.md) | Knowledge | Implemented |
336
+ | 09 | [Waste Detection](./specs/09-waste-detection.md) | Analytics | Implemented |
337
+ | 10 | [Background Scheduler](./specs/10-background-scheduler.md) | Automation | Implemented |
338
+ | 11 | [CLI Interface](./specs/11-cli-interface.md) | Interface | Implemented |
339
+ | 12 | [Dashboard](./specs/12-dashboard.md) | Interface | Implemented |
340
+ | 13 | [Design Evaluation](./specs/13-design-evaluation.md) | Advanced | Implemented |
341
+ | 14 | [Framework Advisor](./specs/14-framework-advisor.md) | Advanced | Implemented |
342
+ | 15 | [Cross-Project Wiki](./specs/15-cross-project-wiki.md) | Wiki | Designed |
343
+ | 16 | [Test Plan](./specs/16-test-plan.md) | Quality | Designed |
344
+
345
+ ## License
346
+
347
+ MIT
package/package.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "@drewpayment/mink",
3
+ "version": "0.1.0",
4
+ "description": "A hidden presence that moves alongside the developer — token efficiency and cross-project wiki for AI coding assistants",
5
+ "type": "module",
6
+ "bin": {
7
+ "mink": "./src/cli.ts"
8
+ },
9
+ "scripts": {
10
+ "typecheck": "bunx tsc --noEmit",
11
+ "test": "bun test",
12
+ "test:watch": "bun test --watch",
13
+ "dashboard:dev": "cd dashboard && bun run dev",
14
+ "dashboard:build": "cd dashboard && bun run build"
15
+ },
16
+ "files": [
17
+ "src/**/*.ts"
18
+ ],
19
+ "publishConfig": {
20
+ "access": "public"
21
+ },
22
+ "license": "MIT",
23
+ "dependencies": {
24
+ "puppeteer-core": "^24.0.0"
25
+ },
26
+ "optionalDependencies": {
27
+ "@puppeteer/browsers": "^2.0.0"
28
+ },
29
+ "devDependencies": {
30
+ "bun-types": "^1.3.12"
31
+ }
32
+ }
package/src/cli.ts ADDED
@@ -0,0 +1,176 @@
1
+ #!/usr/bin/env bun
2
+ import { sessionStart } from "./commands/session-start";
3
+ import { sessionStop } from "./commands/session-stop";
4
+ import { sessionPath } from "./core/paths";
5
+
6
+ const command = process.argv[2];
7
+ const cwd = process.cwd();
8
+
9
+ switch (command) {
10
+ case "session-start":
11
+ sessionStart(cwd);
12
+ break;
13
+
14
+ case "session-stop":
15
+ sessionStop(sessionPath(cwd));
16
+ break;
17
+
18
+ case "init": {
19
+ const { init } = await import("./commands/init");
20
+ await init(cwd);
21
+ break;
22
+ }
23
+
24
+ case "status": {
25
+ const { status } = await import("./commands/status");
26
+ status(cwd);
27
+ break;
28
+ }
29
+
30
+ case "scan": {
31
+ const { scan } = await import("./commands/scan");
32
+ const check = process.argv.includes("--check");
33
+ scan(cwd, { check });
34
+ break;
35
+ }
36
+
37
+ case "reflect": {
38
+ const { reflect } = await import("./commands/reflect");
39
+ const { learningMemoryPath, configPath } = await import("./core/paths");
40
+ reflect(cwd, learningMemoryPath(cwd), configPath(cwd));
41
+ break;
42
+ }
43
+
44
+ case "pre-read": {
45
+ const { preRead } = await import("./commands/pre-read");
46
+ await preRead(cwd);
47
+ break;
48
+ }
49
+
50
+ case "post-read": {
51
+ const { postRead } = await import("./commands/post-read");
52
+ await postRead(cwd);
53
+ break;
54
+ }
55
+
56
+ case "pre-write": {
57
+ const { preWrite } = await import("./commands/pre-write");
58
+ await preWrite(cwd);
59
+ break;
60
+ }
61
+
62
+ case "post-write": {
63
+ const { postWrite } = await import("./commands/post-write");
64
+ await postWrite(cwd);
65
+ break;
66
+ }
67
+
68
+ case "detect-waste": {
69
+ const { detectWaste } = await import("./commands/detect-waste");
70
+ detectWaste(cwd);
71
+ break;
72
+ }
73
+
74
+ case "cron": {
75
+ const { cron } = await import("./commands/cron");
76
+ await cron(cwd, process.argv.slice(3));
77
+ break;
78
+ }
79
+
80
+ case "dashboard": {
81
+ const { dashboard } = await import("./commands/dashboard");
82
+ await dashboard(cwd, process.argv.slice(3));
83
+ break;
84
+ }
85
+
86
+ case "daemon": {
87
+ const { daemon } = await import("./commands/daemon");
88
+ await daemon(cwd, process.argv.slice(3));
89
+ break;
90
+ }
91
+
92
+ case "config": {
93
+ const { config } = await import("./commands/config");
94
+ await config(process.argv.slice(3));
95
+ break;
96
+ }
97
+
98
+ case "update": {
99
+ const { update } = await import("./commands/update");
100
+ await update(cwd, process.argv.slice(3));
101
+ break;
102
+ }
103
+
104
+ case "restore": {
105
+ const { restore } = await import("./commands/restore");
106
+ restore(cwd, process.argv.slice(3));
107
+ break;
108
+ }
109
+
110
+ case "designqc": {
111
+ const { designqc } = await import("./commands/designqc");
112
+ designqc(cwd, process.argv.slice(3));
113
+ break;
114
+ }
115
+
116
+ case "framework-advisor": {
117
+ const { frameworkAdvisor } = await import("./commands/framework-advisor");
118
+ await frameworkAdvisor(cwd, process.argv.slice(3));
119
+ break;
120
+ }
121
+
122
+ case "bug-search": {
123
+ const { bugSearch } = await import("./commands/bug-search");
124
+ bugSearch(cwd, process.argv.slice(3).join(" "));
125
+ break;
126
+ }
127
+
128
+ case "bug": {
129
+ if (process.argv[3] === "search") {
130
+ const { bugSearch } = await import("./commands/bug-search");
131
+ bugSearch(cwd, process.argv.slice(4).join(" "));
132
+ } else {
133
+ console.error(
134
+ `[mink] unknown bug subcommand: ${process.argv[3] ?? "(none)"}`
135
+ );
136
+ console.error("Usage: mink bug search <term>");
137
+ process.exit(1);
138
+ }
139
+ break;
140
+ }
141
+
142
+ case "help":
143
+ case "--help":
144
+ case "-h":
145
+ console.log("mink — a hidden presence that moves alongside the developer");
146
+ console.log();
147
+ console.log("Usage: mink <command> [options]");
148
+ console.log();
149
+ console.log("Commands:");
150
+ console.log(" init Initialize Mink in the current project");
151
+ console.log(" status Display project health at a glance");
152
+ console.log(" scan [--check] Force a full file index rescan");
153
+ console.log(" config [key] [value] Manage global user settings");
154
+ console.log(" dashboard [--port=N] Open the real-time web dashboard");
155
+ console.log(" daemon <cmd> Manage the background daemon (start|stop|restart|logs)");
156
+ console.log(" cron <cmd> [id] Manage scheduled tasks (list|run|retry)");
157
+ console.log(" update [options] Update Mink across registered projects");
158
+ console.log(" restore [backup] Restore state from a backup");
159
+ console.log(" bug search <term> Search the bug log");
160
+ console.log(" detect-waste Detect and flag wasteful patterns");
161
+ console.log(" reflect Generate learning memory reflections");
162
+ console.log(" designqc [target] Capture design screenshots (spec 13)");
163
+ console.log(" framework-advisor Generate framework advisor knowledge file (spec 14)");
164
+ console.log();
165
+ console.log("Lifecycle hooks (internal):");
166
+ console.log(" session-start Start session tracking");
167
+ console.log(" session-stop Finalize session and log data");
168
+ console.log(" pre-read / post-read File read hooks");
169
+ console.log(" pre-write / post-write File write hooks");
170
+ break;
171
+
172
+ default:
173
+ console.error(`[mink] unknown command: ${command ?? "(none)"}`);
174
+ console.error("Run 'mink help' for usage information.");
175
+ process.exit(1);
176
+ }
@@ -0,0 +1,32 @@
1
+ import { loadBugMemory, searchBugs } from "../core/bug-memory";
2
+ import { bugMemoryPath } from "../core/paths";
3
+
4
+ export function bugSearch(cwd: string, query: string): void {
5
+ if (!query) {
6
+ console.error("Usage: mink bug search <query>");
7
+ process.exit(1);
8
+ }
9
+
10
+ const memory = loadBugMemory(bugMemoryPath(cwd));
11
+ const results = searchBugs(memory, query);
12
+
13
+ if (results.length === 0) {
14
+ console.log("No matching bugs found.");
15
+ return;
16
+ }
17
+
18
+ for (const match of results) {
19
+ const e = match.entry;
20
+ console.log(
21
+ `${e.id} (score: ${match.score.toFixed(2)}) — ${e.errorMessage}`
22
+ );
23
+ console.log(
24
+ ` File: ${e.filePath}${e.lineNumber ? `:${e.lineNumber}` : ""}`
25
+ );
26
+ console.log(` Root cause: ${e.rootCause}`);
27
+ console.log(` Fix: ${e.fixDescription}`);
28
+ if (e.tags.length > 0) console.log(` Tags: ${e.tags.join(", ")}`);
29
+ if (e.occurrenceCount > 1) console.log(` Seen ${e.occurrenceCount} times`);
30
+ console.log();
31
+ }
32
+ }
@@ -0,0 +1,109 @@
1
+ import {
2
+ CONFIG_KEYS,
3
+ isValidConfigKey,
4
+ } from "../types/config";
5
+ import {
6
+ resolveConfigValue,
7
+ resolveAllConfig,
8
+ setConfigValue,
9
+ resetConfigKey,
10
+ resetAllConfig,
11
+ } from "../core/global-config";
12
+
13
+ function printValidKeys(): void {
14
+ console.error("Valid keys:");
15
+ for (const meta of CONFIG_KEYS) {
16
+ console.error(` ${meta.key} — ${meta.description}`);
17
+ }
18
+ }
19
+
20
+ function readLineFromStdin(): Promise<string> {
21
+ return new Promise((resolve) => {
22
+ const chunks: Buffer[] = [];
23
+ process.stdin.resume();
24
+ process.stdin.setEncoding("utf-8");
25
+ process.stdin.once("data", (data) => {
26
+ process.stdin.pause();
27
+ resolve(String(data).trim());
28
+ });
29
+ });
30
+ }
31
+
32
+ export async function config(args: string[]): Promise<void> {
33
+ // mink config --reset-all
34
+ if (args.includes("--reset-all")) {
35
+ process.stdout.write(
36
+ "[mink] reset all settings to defaults? (yes/no): "
37
+ );
38
+ const answer = await readLineFromStdin();
39
+ if (answer === "yes" || answer === "y") {
40
+ resetAllConfig();
41
+ console.log("[mink] all settings reset to defaults");
42
+ } else {
43
+ console.log("[mink] cancelled");
44
+ }
45
+ return;
46
+ }
47
+
48
+ // mink config --reset <key>
49
+ const resetIdx = args.indexOf("--reset");
50
+ if (resetIdx !== -1) {
51
+ const key = args[resetIdx + 1];
52
+ if (!key) {
53
+ console.error("Usage: mink config --reset <key>");
54
+ printValidKeys();
55
+ process.exit(1);
56
+ }
57
+ if (!isValidConfigKey(key)) {
58
+ console.error(`[mink] unknown config key: ${key}`);
59
+ printValidKeys();
60
+ process.exit(1);
61
+ }
62
+ resetConfigKey(key);
63
+ console.log(`[mink] ${key} reset to default`);
64
+ return;
65
+ }
66
+
67
+ // mink config (no args) — show all
68
+ if (args.length === 0) {
69
+ const all = resolveAllConfig();
70
+ console.log("[mink] configuration:");
71
+ for (const entry of all) {
72
+ let line = ` ${entry.key} = ${entry.value} (source: ${entry.source})`;
73
+ if (
74
+ entry.source === "environment variable" &&
75
+ entry.configFileValue !== undefined
76
+ ) {
77
+ line += ` [config file value: ${entry.configFileValue} — overridden]`;
78
+ }
79
+ console.log(line);
80
+ }
81
+ return;
82
+ }
83
+
84
+ const key = args[0];
85
+ if (!isValidConfigKey(key)) {
86
+ console.error(`[mink] unknown config key: ${key}`);
87
+ printValidKeys();
88
+ process.exit(1);
89
+ }
90
+
91
+ // mink config <key> <value> — set
92
+ if (args.length >= 2) {
93
+ const value = args.slice(1).join(" ");
94
+ setConfigValue(key, value);
95
+ console.log(`[mink] ${key} = ${value}`);
96
+ return;
97
+ }
98
+
99
+ // mink config <key> — show one
100
+ const resolved = resolveConfigValue(key);
101
+ let line = `${key} = ${resolved.value} (source: ${resolved.source})`;
102
+ if (
103
+ resolved.source === "environment variable" &&
104
+ resolved.configFileValue !== undefined
105
+ ) {
106
+ line += `\n note: config file value (${resolved.configFileValue}) is overridden`;
107
+ }
108
+ console.log(line);
109
+ }