fixmind 1.0.2 → 1.0.4

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.
@@ -16,42 +16,42 @@ export function initializeDataDirectory() {
16
16
  export function createLessonStore(filePath = databasePath()) {
17
17
  fs.mkdirSync(path.dirname(filePath), { recursive: true });
18
18
  const db = new DatabaseSync(filePath);
19
- db.exec(`
20
- CREATE TABLE IF NOT EXISTS lessons (
21
- id TEXT PRIMARY KEY,
22
- created_at TEXT NOT NULL,
23
- updated_at TEXT NOT NULL,
24
- tool TEXT NOT NULL,
25
- project_path TEXT NOT NULL,
26
- title TEXT NOT NULL,
27
- original_prompt TEXT NOT NULL,
28
- problem TEXT NOT NULL,
29
- mistake TEXT NOT NULL,
30
- root_cause TEXT NOT NULL,
31
- fix_summary TEXT NOT NULL,
32
- takeaway TEXT,
33
- mistake_pattern TEXT,
34
- when_not_applicable TEXT,
35
- concepts TEXT NOT NULL,
36
- files_changed TEXT NOT NULL,
37
- code_example TEXT,
38
- bad_code_example TEXT,
39
- good_code_example TEXT,
40
- code_explanation TEXT,
41
- practice_task TEXT,
42
- review_questions TEXT NOT NULL,
43
- understanding TEXT NOT NULL,
44
- next_review_at TEXT NOT NULL,
45
- review_count INTEGER NOT NULL DEFAULT 0,
46
- source_diff TEXT,
47
- tags TEXT NOT NULL,
48
- status TEXT NOT NULL DEFAULT 'active',
49
- superseded_by TEXT,
50
- supersedes TEXT,
51
- supersede_reason TEXT
52
- );
53
- CREATE INDEX IF NOT EXISTS idx_lessons_created_at ON lessons(created_at DESC);
54
- CREATE INDEX IF NOT EXISTS idx_lessons_next_review_at ON lessons(next_review_at);
19
+ db.exec(`
20
+ CREATE TABLE IF NOT EXISTS lessons (
21
+ id TEXT PRIMARY KEY,
22
+ created_at TEXT NOT NULL,
23
+ updated_at TEXT NOT NULL,
24
+ tool TEXT NOT NULL,
25
+ project_path TEXT NOT NULL,
26
+ title TEXT NOT NULL,
27
+ original_prompt TEXT NOT NULL,
28
+ problem TEXT NOT NULL,
29
+ mistake TEXT NOT NULL,
30
+ root_cause TEXT NOT NULL,
31
+ fix_summary TEXT NOT NULL,
32
+ takeaway TEXT,
33
+ mistake_pattern TEXT,
34
+ when_not_applicable TEXT,
35
+ concepts TEXT NOT NULL,
36
+ files_changed TEXT NOT NULL,
37
+ code_example TEXT,
38
+ bad_code_example TEXT,
39
+ good_code_example TEXT,
40
+ code_explanation TEXT,
41
+ practice_task TEXT,
42
+ review_questions TEXT NOT NULL,
43
+ understanding TEXT NOT NULL,
44
+ next_review_at TEXT NOT NULL,
45
+ review_count INTEGER NOT NULL DEFAULT 0,
46
+ source_diff TEXT,
47
+ tags TEXT NOT NULL,
48
+ status TEXT NOT NULL DEFAULT 'active',
49
+ superseded_by TEXT,
50
+ supersedes TEXT,
51
+ supersede_reason TEXT
52
+ );
53
+ CREATE INDEX IF NOT EXISTS idx_lessons_created_at ON lessons(created_at DESC);
54
+ CREATE INDEX IF NOT EXISTS idx_lessons_next_review_at ON lessons(next_review_at);
55
55
  `);
56
56
  return {
57
57
  save(input) {
@@ -90,17 +90,17 @@ export function createLessonStore(filePath = databasePath()) {
90
90
  tags: input.tags ?? [],
91
91
  status: "active",
92
92
  };
93
- db.prepare(`
94
- INSERT INTO lessons (
95
- id, created_at, updated_at, tool, project_path, title, original_prompt,
96
- problem, mistake, root_cause, fix_summary, takeaway, mistake_pattern,
97
- when_not_applicable, concepts, files_changed, code_example, bad_code_example,
98
- good_code_example, code_explanation, practice_task, review_questions,
99
- understanding, next_review_at, review_count, source_diff, tags,
100
- status, superseded_by, supersedes, supersede_reason
101
- ) VALUES (
102
- ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, NULL, NULL
103
- )
93
+ db.prepare(`
94
+ INSERT INTO lessons (
95
+ id, created_at, updated_at, tool, project_path, title, original_prompt,
96
+ problem, mistake, root_cause, fix_summary, takeaway, mistake_pattern,
97
+ when_not_applicable, concepts, files_changed, code_example, bad_code_example,
98
+ good_code_example, code_explanation, practice_task, review_questions,
99
+ understanding, next_review_at, review_count, source_diff, tags,
100
+ status, superseded_by, supersedes, supersede_reason
101
+ ) VALUES (
102
+ ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, NULL, NULL
103
+ )
104
104
  `).run(lesson.id, lesson.createdAt, lesson.updatedAt, lesson.tool, lesson.projectPath, lesson.title, lesson.originalPrompt, lesson.problem, lesson.mistake, lesson.rootCause, lesson.fixSummary, lesson.takeaway ?? null, lesson.mistakePattern ?? null, lesson.whenNotApplicable ?? null, JSON.stringify(lesson.concepts), JSON.stringify(lesson.filesChanged), lesson.codeExample ?? null, lesson.badCodeExample ?? null, lesson.goodCodeExample ?? null, lesson.codeExplanation ?? null, lesson.practiceTask ?? null, JSON.stringify(lesson.reviewQuestions), lesson.understanding, lesson.nextReviewAt, lesson.reviewCount, lesson.sourceDiff ?? null, JSON.stringify(lesson.tags), lesson.status);
105
105
  if (input.supersedesLessonId && this.get(input.supersedesLessonId)) {
106
106
  this.supersede(input.supersedesLessonId, lesson.id, input.supersedeReason);
@@ -120,31 +120,31 @@ export function createLessonStore(filePath = databasePath()) {
120
120
  return db.prepare("SELECT * FROM lessons WHERE updated_at > ? ORDER BY updated_at ASC").all(timestamp).map(fromDb);
121
121
  },
122
122
  upsertFromRemote(lesson) {
123
- db.prepare(`
124
- INSERT INTO lessons (
125
- id, created_at, updated_at, tool, project_path, title, original_prompt,
126
- problem, mistake, root_cause, fix_summary, takeaway, mistake_pattern,
127
- when_not_applicable, concepts, files_changed, code_example, bad_code_example,
128
- good_code_example, code_explanation, practice_task, review_questions,
129
- understanding, next_review_at, review_count, source_diff, tags,
130
- status, superseded_by, supersedes, supersede_reason
131
- ) VALUES (
132
- ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
133
- )
134
- ON CONFLICT(id) DO UPDATE SET
135
- created_at=excluded.created_at, updated_at=excluded.updated_at, tool=excluded.tool,
136
- project_path=excluded.project_path, title=excluded.title, original_prompt=excluded.original_prompt,
137
- problem=excluded.problem, mistake=excluded.mistake, root_cause=excluded.root_cause,
138
- fix_summary=excluded.fix_summary, takeaway=excluded.takeaway, mistake_pattern=excluded.mistake_pattern,
139
- when_not_applicable=excluded.when_not_applicable, concepts=excluded.concepts,
140
- files_changed=excluded.files_changed, code_example=excluded.code_example,
141
- bad_code_example=excluded.bad_code_example, good_code_example=excluded.good_code_example,
142
- code_explanation=excluded.code_explanation, practice_task=excluded.practice_task,
143
- review_questions=excluded.review_questions, understanding=excluded.understanding,
144
- next_review_at=excluded.next_review_at, review_count=excluded.review_count,
145
- source_diff=excluded.source_diff, tags=excluded.tags, status=excluded.status,
146
- superseded_by=excluded.superseded_by, supersedes=excluded.supersedes,
147
- supersede_reason=excluded.supersede_reason
123
+ db.prepare(`
124
+ INSERT INTO lessons (
125
+ id, created_at, updated_at, tool, project_path, title, original_prompt,
126
+ problem, mistake, root_cause, fix_summary, takeaway, mistake_pattern,
127
+ when_not_applicable, concepts, files_changed, code_example, bad_code_example,
128
+ good_code_example, code_explanation, practice_task, review_questions,
129
+ understanding, next_review_at, review_count, source_diff, tags,
130
+ status, superseded_by, supersedes, supersede_reason
131
+ ) VALUES (
132
+ ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
133
+ )
134
+ ON CONFLICT(id) DO UPDATE SET
135
+ created_at=excluded.created_at, updated_at=excluded.updated_at, tool=excluded.tool,
136
+ project_path=excluded.project_path, title=excluded.title, original_prompt=excluded.original_prompt,
137
+ problem=excluded.problem, mistake=excluded.mistake, root_cause=excluded.root_cause,
138
+ fix_summary=excluded.fix_summary, takeaway=excluded.takeaway, mistake_pattern=excluded.mistake_pattern,
139
+ when_not_applicable=excluded.when_not_applicable, concepts=excluded.concepts,
140
+ files_changed=excluded.files_changed, code_example=excluded.code_example,
141
+ bad_code_example=excluded.bad_code_example, good_code_example=excluded.good_code_example,
142
+ code_explanation=excluded.code_explanation, practice_task=excluded.practice_task,
143
+ review_questions=excluded.review_questions, understanding=excluded.understanding,
144
+ next_review_at=excluded.next_review_at, review_count=excluded.review_count,
145
+ source_diff=excluded.source_diff, tags=excluded.tags, status=excluded.status,
146
+ superseded_by=excluded.superseded_by, supersedes=excluded.supersedes,
147
+ supersede_reason=excluded.supersede_reason
148
148
  `).run(lesson.id, lesson.createdAt, lesson.updatedAt, lesson.tool, lesson.projectPath, lesson.title, lesson.originalPrompt, lesson.problem, lesson.mistake, lesson.rootCause, lesson.fixSummary, lesson.takeaway ?? null, lesson.mistakePattern ?? null, lesson.whenNotApplicable ?? null, JSON.stringify(lesson.concepts), JSON.stringify(lesson.filesChanged), lesson.codeExample ?? null, lesson.badCodeExample ?? null, lesson.goodCodeExample ?? null, lesson.codeExplanation ?? null, lesson.practiceTask ?? null, JSON.stringify(lesson.reviewQuestions), lesson.understanding, lesson.nextReviewAt, lesson.reviewCount, lesson.sourceDiff ?? null, JSON.stringify(lesson.tags), lesson.status, lesson.supersededBy ?? null, lesson.supersedes ?? null, lesson.supersedeReason ?? null);
149
149
  },
150
150
  search(query, options = {}) {
package/dist/src/sync.js CHANGED
@@ -46,67 +46,67 @@ function escapeHtml(value) {
46
46
  }
47
47
  function oauthCallbackPage(options) {
48
48
  const tint = options.ok ? "124,92,255" : "255,92,114";
49
- return `<!doctype html>
50
- <html lang="en">
51
- <head>
52
- <meta charset="utf-8">
53
- <title>Fixmind</title>
54
- <style>
55
- :root { color-scheme: dark; }
56
- body {
57
- margin: 0; min-height: 100vh; display: flex; align-items: center; justify-content: center;
58
- position: relative; overflow: hidden;
59
- background-color: #08090d; color: #e9ecf4;
60
- font-family: "Inter", -apple-system, BlinkMacSystemFont, sans-serif;
61
- }
62
- body::before {
63
- content: ""; position: absolute; inset: 0; pointer-events: none;
64
- background-image:
65
- linear-gradient(to right, rgba(35,40,56,0.6) 1px, transparent 1px),
66
- linear-gradient(to bottom, rgba(35,40,56,0.6) 1px, transparent 1px);
67
- background-size: 48px 48px;
68
- mask-image: radial-gradient(circle at 50% 35%, black, transparent 75%);
69
- }
70
- body::after {
71
- content: ""; position: absolute; left: 50%; top: 0; width: 760px; height: 420px;
72
- transform: translateX(-50%); pointer-events: none; border-radius: 9999px;
73
- background: rgba(${tint},0.15); filter: blur(130px);
74
- }
75
- .card {
76
- position: relative; z-index: 1; text-align: center; padding: 2.5rem 3rem; border-radius: 16px;
77
- border: 1px solid #232838; background: rgba(17,20,27,0.92);
78
- }
79
- .icon {
80
- width: 48px; height: 48px; margin: 0 auto 1.25rem; border-radius: 50%;
81
- display: flex; align-items: center; justify-content: center; font-size: 22px;
82
- background: rgba(${tint},0.15);
83
- color: ${options.ok ? "#7c5cff" : "#ff5c72"};
84
- }
85
- h1 {
86
- font-family: "Space Grotesk", "Inter", sans-serif; font-size: 1.25rem; font-weight: 600;
87
- margin: 0 0 0.5rem;
88
- }
89
- p { margin: 0; color: #828a9c; font-size: 0.95rem; line-height: 1.5; }
90
- .redirect {
91
- display: inline-block; margin-top: 1.5rem; padding: 0.6rem 1.5rem; border-radius: 8px;
92
- background: #7c5cff; color: #08090d; font-weight: 600; font-size: 0.9rem;
93
- text-decoration: none;
94
- }
95
- .brand {
96
- margin-top: 2rem; font-size: 0.75rem; letter-spacing: 0.1em; text-transform: uppercase;
97
- color: #4b3aae;
98
- }
99
- </style>
100
- </head>
101
- <body>
102
- <div class="card">
103
- <div class="icon">${options.ok ? "&#10003;" : "&#33;"}</div>
104
- <h1>${options.ok ? "You're signed in" : "Sign in failed"}</h1>
105
- <p>${escapeHtml(options.message)}</p>
106
- ${options.redirectUrl ? `<a class="redirect" href="${escapeHtml(options.redirectUrl)}">Try again</a>` : ""}
107
- <div class="brand">Fixmind</div>
108
- </div>
109
- </body>
49
+ return `<!doctype html>
50
+ <html lang="en">
51
+ <head>
52
+ <meta charset="utf-8">
53
+ <title>Fixmind</title>
54
+ <style>
55
+ :root { color-scheme: dark; }
56
+ body {
57
+ margin: 0; min-height: 100vh; display: flex; align-items: center; justify-content: center;
58
+ position: relative; overflow: hidden;
59
+ background-color: #08090d; color: #e9ecf4;
60
+ font-family: "Inter", -apple-system, BlinkMacSystemFont, sans-serif;
61
+ }
62
+ body::before {
63
+ content: ""; position: absolute; inset: 0; pointer-events: none;
64
+ background-image:
65
+ linear-gradient(to right, rgba(35,40,56,0.6) 1px, transparent 1px),
66
+ linear-gradient(to bottom, rgba(35,40,56,0.6) 1px, transparent 1px);
67
+ background-size: 48px 48px;
68
+ mask-image: radial-gradient(circle at 50% 35%, black, transparent 75%);
69
+ }
70
+ body::after {
71
+ content: ""; position: absolute; left: 50%; top: 0; width: 760px; height: 420px;
72
+ transform: translateX(-50%); pointer-events: none; border-radius: 9999px;
73
+ background: rgba(${tint},0.15); filter: blur(130px);
74
+ }
75
+ .card {
76
+ position: relative; z-index: 1; text-align: center; padding: 2.5rem 3rem; border-radius: 16px;
77
+ border: 1px solid #232838; background: rgba(17,20,27,0.92);
78
+ }
79
+ .icon {
80
+ width: 48px; height: 48px; margin: 0 auto 1.25rem; border-radius: 50%;
81
+ display: flex; align-items: center; justify-content: center; font-size: 22px;
82
+ background: rgba(${tint},0.15);
83
+ color: ${options.ok ? "#7c5cff" : "#ff5c72"};
84
+ }
85
+ h1 {
86
+ font-family: "Space Grotesk", "Inter", sans-serif; font-size: 1.25rem; font-weight: 600;
87
+ margin: 0 0 0.5rem;
88
+ }
89
+ p { margin: 0; color: #828a9c; font-size: 0.95rem; line-height: 1.5; }
90
+ .redirect {
91
+ display: inline-block; margin-top: 1.5rem; padding: 0.6rem 1.5rem; border-radius: 8px;
92
+ background: #7c5cff; color: #08090d; font-weight: 600; font-size: 0.9rem;
93
+ text-decoration: none;
94
+ }
95
+ .brand {
96
+ margin-top: 2rem; font-size: 0.75rem; letter-spacing: 0.1em; text-transform: uppercase;
97
+ color: #4b3aae;
98
+ }
99
+ </style>
100
+ </head>
101
+ <body>
102
+ <div class="card">
103
+ <div class="icon">${options.ok ? "&#10003;" : "&#33;"}</div>
104
+ <h1>${options.ok ? "You're signed in" : "Sign in failed"}</h1>
105
+ <p>${escapeHtml(options.message)}</p>
106
+ ${options.redirectUrl ? `<a class="redirect" href="${escapeHtml(options.redirectUrl)}">Try again</a>` : ""}
107
+ <div class="brand">Fixmind</div>
108
+ </div>
109
+ </body>
110
110
  </html>`;
111
111
  }
112
112
  function waitForOAuthCode(port, authUrl) {
@@ -1,104 +1,112 @@
1
- # MCP Integration
2
-
3
- Fixmind exposes a local stdio MCP server. Any MCP-compatible AI coding client can start it and call one tool:
4
-
5
- `save_lesson`
6
-
7
- The tool stores a lesson locally. It does not call an AI API, upload code, or expose lesson history to the agent.
8
-
9
- ## Guided setup
10
-
11
- After installing the package globally, run:
12
-
13
- ```powershell
14
- fixmind setup
15
- ```
16
-
17
- The setup command detects Codex, Claude Code, and Cursor, asks which clients to configure, initializes local storage, and registers this stdio command:
18
-
19
- ```powershell
20
- npx -y fixmind mcp
21
- ```
22
-
23
- On Windows, clients receive the compatible equivalent using `cmd /c`.
24
-
25
- Non-interactive examples:
26
-
27
- ```powershell
28
- fixmind setup --client codex,claude,cursor
29
- fixmind setup --client cursor --dry-run
30
- ```
31
-
32
- Setup is idempotent. Existing MCP entries are preserved. Before changing Cursor's JSON configuration, the previous file is copied to `mcp.json.backup`.
33
-
34
- For Claude Code, setup additionally pre-approves the `mcp__fixmind__save_lesson` tool by adding it to `permissions.allow` in `~/.claude/settings.json`, so the agent isn't blocked by a runtime permission prompt when saving a lesson. Existing settings and other permission entries are preserved, and a `.backup` copy of `settings.json` is made before the first change.
35
-
36
- ## Other MCP clients
37
-
38
- Run `fixmind setup` on a machine where no supported client is detected to print a generic MCP configuration. The equivalent configuration is:
39
-
40
- ```json
41
- {
42
- "mcpServers": {
43
- "fixmind": {
44
- "command": "npx",
45
- "args": ["-y", "fixmind", "mcp"]
46
- }
47
- }
48
- }
49
- ```
50
-
51
- ## Agent behavior
52
-
53
- The MCP server sends instructions asking the agent to create a lesson after a meaningful coding fix and skip formatting-only, rename-only, generated-file, and mechanical changes.
54
-
55
- Automatic use is best-effort because each MCP client decides when to call available tools. The human can explicitly say "save a learning lesson after the fix" if a client does not consistently follow server instructions.
56
-
57
- ## Token and context overhead
58
-
59
- Connecting the fixmind MCP server adds a small, mostly one-time cost to an agent's context:
60
-
61
- - The server's instructions and the `save_lesson` tool schema are sent once when the client connects. Clients that support prompt caching reuse this across subsequent turns in the same session.
62
- - `save_lesson` is called only when the agent determines a meaningful fix occurred, per the checklist in its instructions — not on every turn. Sessions with no qualifying fixes add nothing beyond the initial connection cost.
63
- - When a lesson is saved, the generated payload (problem, root cause, fix summary, takeaway, code examples, review questions) is comparable in size to a short commit message or code review comment.
64
-
65
- In practice, this overhead is negligible relative to the tokens used by the coding work itself.
66
-
67
- ## Tool input
68
-
69
- The MCP tool accepts:
70
-
71
- ```json
72
- {
73
- "projectPath": "/path/to/project",
74
- "title": "Short learning-oriented title",
75
- "originalPrompt": "The user's original request",
76
- "problem": "What behavior was broken",
77
- "mistake": "The specific mistake",
78
- "rootCause": "Why the mistake caused the behavior",
79
- "fixSummary": "What changed and why it works",
80
- "takeaway": "One plain sentence the developer should remember",
81
- "mistakePattern": "A short reusable category",
82
- "concepts": ["Reusable concept"],
83
- "filesChanged": ["src/example.ts"],
84
- "codeExample": "A small focused example",
85
- "badCodeExample": "A minimal example showing the mistake",
86
- "goodCodeExample": "A minimal corrected example",
87
- "codeExplanation": "The important difference between the two examples",
88
- "practiceTask": "A small exercise to apply the concept",
89
- "reviewQuestions": [
90
- {
91
- "question": "A recall question",
92
- "expectedAnswer": "A concise expected answer"
93
- }
94
- ],
95
- "understanding": "unknown",
96
- "tags": [
97
- { "name": "MDN: fetch()", "url": "https://developer.mozilla.org/en-US/docs/Web/API/Window/fetch" }
98
- ]
99
- }
100
- ```
101
-
102
- `tool` is optional and normally omitted: fixmind reads it from the connected MCP client's `clientInfo.name` during the initialize handshake. Each `tags` entry is `{ name, url? }`; only set `url` when it points to real, official documentation (MDN, the framework's docs, etc.) — otherwise omit it and the tag is shown as a plain label.
103
-
104
- If Git is available at `projectPath`, omitted changed files and source diff are collected from the current working tree.
1
+ # MCP Integration
2
+
3
+ ## Supported clients
4
+
5
+ ![Claude Code](/logos/claude.svg) ![Cursor](/logos/cursor.svg) ![Codex](/logos/codex.svg)
6
+
7
+ `fixmind setup` detects and configures all three. Any other MCP-compatible client works too see [Other MCP clients](#other-mcp-clients).
8
+
9
+ Fixmind exposes a local stdio MCP server. Any MCP-compatible AI coding client can start it and call one tool:
10
+
11
+ `save_lesson`
12
+
13
+ The tool stores a lesson locally. It does not call an AI API, upload code, or expose lesson history to the agent. For what gets stored and how it's reviewed afterward, see [Lesson Schema](../../../docs/lesson-schema.md). For the `fixmind setup` flags used below, see [Commands](../../../docs/cli-reference.md#fixmind-setup).
14
+
15
+ ## Guided setup
16
+
17
+ After installing the package globally, run:
18
+
19
+ ```powershell
20
+ fixmind setup
21
+ ```
22
+
23
+ The setup command detects Codex, Claude Code, and Cursor, asks which clients to configure, initializes local storage, and registers this stdio command:
24
+
25
+ ```powershell
26
+ npx -y fixmind mcp
27
+ ```
28
+
29
+ On Windows, clients receive the compatible equivalent using `cmd /c`.
30
+
31
+ Non-interactive examples:
32
+
33
+ ```powershell
34
+ fixmind setup --client codex,claude,cursor
35
+ fixmind setup --client cursor --dry-run
36
+ ```
37
+
38
+ Setup is idempotent. Existing MCP entries are preserved. Before changing Cursor's JSON configuration, the previous file is copied to `mcp.json.backup`.
39
+
40
+ For Claude Code, setup additionally pre-approves the `mcp__fixmind__save_lesson` tool by adding it to `permissions.allow` in `~/.claude/settings.json`, so the agent isn't blocked by a runtime permission prompt when saving a lesson. Existing settings and other permission entries are preserved, and a `.backup` copy of `settings.json` is made before the first change.
41
+
42
+ ## Other MCP clients
43
+
44
+ Run `fixmind setup` on a machine where no supported client is detected to print a generic MCP configuration. The equivalent configuration is:
45
+
46
+ ```json
47
+ {
48
+ "mcpServers": {
49
+ "fixmind": {
50
+ "command": "npx",
51
+ "args": ["-y", "fixmind", "mcp"]
52
+ }
53
+ }
54
+ }
55
+ ```
56
+
57
+ ## Agent behavior
58
+
59
+ The MCP server sends instructions asking the agent to create a lesson after a meaningful coding fix and skip formatting-only, rename-only, generated-file, and mechanical changes.
60
+
61
+ Automatic use is best-effort because each MCP client decides when to call available tools. The human can explicitly say "save a learning lesson after the fix" if a client does not consistently follow server instructions.
62
+
63
+ ## Token and context overhead
64
+
65
+ Connecting the fixmind MCP server adds a small, mostly one-time cost to an agent's context:
66
+
67
+ - The server's instructions and the `save_lesson` tool schema are sent once when the client connects. Clients that support prompt caching reuse this across subsequent turns in the same session.
68
+ - `save_lesson` is called only when the agent determines a meaningful fix occurred, per the checklist in its instructions — not on every turn. Sessions with no qualifying fixes add nothing beyond the initial connection cost.
69
+ - When a lesson is saved, the generated payload (problem, root cause, fix summary, takeaway, code examples, review questions) is comparable in size to a short commit message or code review comment.
70
+
71
+ In practice, this overhead is negligible relative to the tokens used by the coding work itself.
72
+
73
+ If a client isn't consistently calling `save_lesson`, or you want to know why a save was rejected, see [FAQ & Troubleshooting](../../../docs/faq.md).
74
+
75
+ ## Tool input
76
+
77
+ The MCP tool accepts:
78
+
79
+ ```json
80
+ {
81
+ "projectPath": "/path/to/project",
82
+ "title": "Short learning-oriented title",
83
+ "originalPrompt": "The user's original request",
84
+ "problem": "What behavior was broken",
85
+ "mistake": "The specific mistake",
86
+ "rootCause": "Why the mistake caused the behavior",
87
+ "fixSummary": "What changed and why it works",
88
+ "takeaway": "One plain sentence the developer should remember",
89
+ "mistakePattern": "A short reusable category",
90
+ "concepts": ["Reusable concept"],
91
+ "filesChanged": ["src/example.ts"],
92
+ "codeExample": "A small focused example",
93
+ "badCodeExample": "A minimal example showing the mistake",
94
+ "goodCodeExample": "A minimal corrected example",
95
+ "codeExplanation": "The important difference between the two examples",
96
+ "practiceTask": "A small exercise to apply the concept",
97
+ "reviewQuestions": [
98
+ {
99
+ "question": "A recall question",
100
+ "expectedAnswer": "A concise expected answer"
101
+ }
102
+ ],
103
+ "understanding": "unknown",
104
+ "tags": [
105
+ { "name": "MDN: fetch()", "url": "https://developer.mozilla.org/en-US/docs/Web/API/Window/fetch" }
106
+ ]
107
+ }
108
+ ```
109
+
110
+ `tool` is optional and normally omitted: fixmind reads it from the connected MCP client's `clientInfo.name` during the initialize handshake. Each `tags` entry is `{ name, url? }`; only set `url` when it points to real, official documentation (MDN, the framework's docs, etc.) — otherwise omit it and the tag is shown as a plain label.
111
+
112
+ If Git is available at `projectPath`, omitted changed files and source diff are collected from the current working tree.
package/package.json CHANGED
@@ -1,45 +1,45 @@
1
- {
2
- "name": "fixmind",
3
- "version": "1.0.2",
4
- "description": "Local-first learning lessons for developers working with AI coding agents.",
5
- "type": "module",
6
- "repository": {
7
- "type": "git",
8
- "url": "git+https://github.com/F-47/fixmind.git",
9
- "directory": "packages/core"
10
- },
11
- "homepage": "https://github.com/F-47/fixmind#readme",
12
- "bin": {
13
- "fixmind": "dist/src/cli.js"
14
- },
15
- "files": [
16
- "dist/src",
17
- "dist/dashboard",
18
- "README.md",
19
- "docs"
20
- ],
21
- "scripts": {
22
- "clean": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\"",
23
- "build": "npm run clean && npm run build:server && npm run copy:dashboard && npm run chmod:bin",
24
- "build:server": "tsc -p tsconfig.json",
25
- "chmod:bin": "node -e \"require('fs').chmodSync('dist/src/cli.js', 0o755)\"",
26
- "copy:dashboard": "node -e \"require('fs').cpSync('../dashboard/dist','dist/dashboard',{recursive:true})\"",
27
- "test": "npm run build && node --no-warnings --test dist/test/*.test.js",
28
- "prepack": "npm run build",
29
- "fixmind": "NODE_OPTIONS=--disable-warning=ExperimentalWarning node dist/src/cli.js"
30
- },
31
- "dependencies": {
32
- "@clack/prompts": "^1.5.1",
33
- "@modelcontextprotocol/sdk": "^1.29.0",
34
- "@supabase/supabase-js": "^2.45.4",
35
- "zod": "^4.4.3"
36
- },
37
- "engines": {
38
- "node": ">=22.5.0"
39
- },
40
- "devDependencies": {
41
- "@types/node": "^22.15.0",
42
- "typescript": "^5.8.3"
43
- },
44
- "license": "MIT"
45
- }
1
+ {
2
+ "name": "fixmind",
3
+ "version": "1.0.4",
4
+ "description": "Local-first learning lessons for developers working with AI coding agents.",
5
+ "type": "module",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/F-47/fixmind.git",
9
+ "directory": "packages/core"
10
+ },
11
+ "homepage": "https://github.com/F-47/fixmind#readme",
12
+ "bin": {
13
+ "fixmind": "dist/src/launcher.js"
14
+ },
15
+ "files": [
16
+ "dist/src",
17
+ "dist/dashboard",
18
+ "README.md",
19
+ "docs"
20
+ ],
21
+ "scripts": {
22
+ "clean": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\"",
23
+ "build": "npm run clean && npm run build:server && npm run copy:dashboard && npm run chmod:bin",
24
+ "build:server": "tsc -p tsconfig.json",
25
+ "chmod:bin": "node -e \"require('fs').chmodSync('dist/src/cli.js', 0o755); require('fs').chmodSync('dist/src/launcher.js', 0o755)\"",
26
+ "copy:dashboard": "node -e \"require('fs').cpSync('../dashboard/dist','dist/dashboard',{recursive:true})\"",
27
+ "test": "npm run build && node --no-warnings --test dist/test/*.test.js",
28
+ "prepack": "npm run build",
29
+ "fixmind": "node dist/src/launcher.js"
30
+ },
31
+ "dependencies": {
32
+ "@clack/prompts": "^1.5.1",
33
+ "@modelcontextprotocol/sdk": "^1.29.0",
34
+ "@supabase/supabase-js": "^2.45.4",
35
+ "zod": "^4.4.3"
36
+ },
37
+ "engines": {
38
+ "node": ">=22.5.0"
39
+ },
40
+ "devDependencies": {
41
+ "@types/node": "^22.15.0",
42
+ "typescript": "^5.8.3"
43
+ },
44
+ "license": "MIT"
45
+ }