athar-mcp 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 (71) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +242 -0
  3. package/dist/cli/commands/list.d.ts +10 -0
  4. package/dist/cli/commands/list.d.ts.map +1 -0
  5. package/dist/cli/commands/list.js +73 -0
  6. package/dist/cli/commands/list.js.map +1 -0
  7. package/dist/cli/commands/review.d.ts +2 -0
  8. package/dist/cli/commands/review.d.ts.map +1 -0
  9. package/dist/cli/commands/review.js +112 -0
  10. package/dist/cli/commands/review.js.map +1 -0
  11. package/dist/cli/commands/setup.d.ts +2 -0
  12. package/dist/cli/commands/setup.d.ts.map +1 -0
  13. package/dist/cli/commands/setup.js +55 -0
  14. package/dist/cli/commands/setup.js.map +1 -0
  15. package/dist/cli/commands/status.d.ts +2 -0
  16. package/dist/cli/commands/status.d.ts.map +1 -0
  17. package/dist/cli/commands/status.js +39 -0
  18. package/dist/cli/commands/status.js.map +1 -0
  19. package/dist/cli/index.d.ts +12 -0
  20. package/dist/cli/index.d.ts.map +1 -0
  21. package/dist/cli/index.js +43 -0
  22. package/dist/cli/index.js.map +1 -0
  23. package/dist/db/connection.d.ts +11 -0
  24. package/dist/db/connection.d.ts.map +1 -0
  25. package/dist/db/connection.js +49 -0
  26. package/dist/db/connection.js.map +1 -0
  27. package/dist/db/schema.d.ts +12 -0
  28. package/dist/db/schema.d.ts.map +1 -0
  29. package/dist/db/schema.js +95 -0
  30. package/dist/db/schema.js.map +1 -0
  31. package/dist/index.d.ts +19 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +48 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/server.d.ts +7 -0
  36. package/dist/server.d.ts.map +1 -0
  37. package/dist/server.js +139 -0
  38. package/dist/server.js.map +1 -0
  39. package/dist/smoke-test.d.ts +7 -0
  40. package/dist/smoke-test.d.ts.map +1 -0
  41. package/dist/smoke-test.js +99 -0
  42. package/dist/smoke-test.js.map +1 -0
  43. package/dist/spaced-repetition/scheduler.d.ts +46 -0
  44. package/dist/spaced-repetition/scheduler.d.ts.map +1 -0
  45. package/dist/spaced-repetition/scheduler.js +98 -0
  46. package/dist/spaced-repetition/scheduler.js.map +1 -0
  47. package/dist/spaced-repetition/sm2.d.ts +36 -0
  48. package/dist/spaced-repetition/sm2.d.ts.map +1 -0
  49. package/dist/spaced-repetition/sm2.js +90 -0
  50. package/dist/spaced-repetition/sm2.js.map +1 -0
  51. package/dist/tools/memory.d.ts +25 -0
  52. package/dist/tools/memory.d.ts.map +1 -0
  53. package/dist/tools/memory.js +112 -0
  54. package/dist/tools/memory.js.map +1 -0
  55. package/dist/tools/save-lesson.d.ts +11 -0
  56. package/dist/tools/save-lesson.d.ts.map +1 -0
  57. package/dist/tools/save-lesson.js +137 -0
  58. package/dist/tools/save-lesson.js.map +1 -0
  59. package/dist/tools/validators.d.ts +82 -0
  60. package/dist/tools/validators.d.ts.map +1 -0
  61. package/dist/tools/validators.js +86 -0
  62. package/dist/tools/validators.js.map +1 -0
  63. package/dist/utils/logger.d.ts +23 -0
  64. package/dist/utils/logger.d.ts.map +1 -0
  65. package/dist/utils/logger.js +55 -0
  66. package/dist/utils/logger.js.map +1 -0
  67. package/dist/utils/paths.d.ts +17 -0
  68. package/dist/utils/paths.d.ts.map +1 -0
  69. package/dist/utils/paths.js +43 -0
  70. package/dist/utils/paths.js.map +1 -0
  71. package/package.json +60 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Ameen
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,242 @@
1
+ # Ų£Ų«Ų± — Athar
2
+
3
+ > **Every mistake leaves a trace, every lesson leaves an impact.**
4
+
5
+ An open-source, local-first MCP server that captures programming lessons from AI-assisted coding sessions, stores them in a local SQLite database, and uses spaced repetition to ensure you never repeat the same mistake twice.
6
+
7
+ <div align="center">
8
+
9
+ ![Node.js](https://img.shields.io/badge/Node.js-≄20-339933?logo=node.js&logoColor=white)
10
+ ![MCP](https://img.shields.io/badge/MCP-Protocol-blueviolet)
11
+ ![License](https://img.shields.io/badge/License-MIT-green)
12
+ ![SQLite](https://img.shields.io/badge/SQLite-Local--First-003B57?logo=sqlite&logoColor=white)
13
+
14
+ </div>
15
+
16
+ ---
17
+
18
+ ## 🧠 What is Athar?
19
+
20
+ **Athar** (Ų£Ų«Ų±) is a memory system for developers. It works as an [MCP (Model Context Protocol)](https://modelcontextprotocol.io/) server that integrates with AI-powered IDEs like [Antigravity IDE](https://antigravity.google).
21
+
22
+ When you're coding with an AI assistant and it helps you fix a real bug, Athar automatically captures the lesson — the problem, root cause, fix, and review questions — and stores it locally. Later, it uses **spaced repetition** (SM-2 algorithm) to quiz you on past mistakes so they stick in your memory permanently.
23
+
24
+ ### How it works
25
+
26
+ ```
27
+ ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā” stdio ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
28
+ │ Antigravity IDE │ ◄────────────► │ Athar MCP │
29
+ │ (AI Assistant) │ JSON-RPC │ Server │
30
+ ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜ ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜
31
+ │
32
+ ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā–¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
33
+ │ SQLite DB │
34
+ │ (local-first) │
35
+ │ ~/.local/share/ │
36
+ │ athar/lessons.db│
37
+ ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜
38
+ │
39
+ ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā–¼ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
40
+ │ CLI & Dashboard │
41
+ │ athar review │
42
+ │ athar status │
43
+ ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜
44
+ ```
45
+
46
+ ---
47
+
48
+ ## ✨ Features
49
+
50
+ - **šŸ”Œ MCP Integration** — Works seamlessly with Antigravity IDE via stdio transport
51
+ - **šŸ“ Smart Lesson Capture** — AI assistant saves lessons with structured data: problem, root cause, bad/good code, review questions
52
+ - **šŸ›”ļø Quality Validation** — Rejects trivial changes (formatting, typos) and detects duplicates
53
+ - **šŸ” Full-Text Search** — FTS5-powered search to recall past lessons instantly
54
+ - **🧠 Spaced Repetition** — SM-2 algorithm schedules reviews at optimal intervals
55
+ - **šŸ’¾ Local-First** — All data stored locally in SQLite. No cloud, no API keys, no costs
56
+ - **🌐 Bilingual** — Supports lessons in both Arabic and English
57
+ - **⚔ Zero Native Dependencies** — Uses Node.js built-in `node:sqlite` module
58
+
59
+ ---
60
+
61
+ ## šŸš€ Quick Start
62
+
63
+ ### Prerequisites
64
+
65
+ - **Node.js** ≄ 20 (tested on v24)
66
+ - **Antigravity IDE** (or any MCP-compatible IDE)
67
+
68
+ ### Installation
69
+
70
+ ```bash
71
+ # Clone the repository
72
+ git clone https://github.com/ameenmv/athar.git
73
+ cd athar
74
+
75
+ # Install dependencies
76
+ npm install
77
+
78
+ # Build
79
+ npm run build
80
+ ```
81
+
82
+ ### Setup with Antigravity IDE
83
+
84
+ Run the setup command (coming in Phase 2), or manually add to your MCP config:
85
+
86
+ **`~/.gemini/config/mcp_config.json`**
87
+
88
+ ```json
89
+ {
90
+ "mcpServers": {
91
+ "athar": {
92
+ "command": "node",
93
+ "args": ["/absolute/path/to/athar/dist/index.js"]
94
+ }
95
+ }
96
+ }
97
+ ```
98
+
99
+ Then restart/refresh MCP servers in Antigravity IDE.
100
+
101
+ ---
102
+
103
+ ## šŸ› ļø MCP Tools
104
+
105
+ Athar exposes two tools to the AI assistant:
106
+
107
+ ### `save_lesson`
108
+
109
+ Captures a programming lesson from a real mistake.
110
+
111
+ | Field | Type | Required | Description |
112
+ |-------|------|----------|-------------|
113
+ | `title` | string | āœ… | Concise title describing the mistake pattern |
114
+ | `problem` | string | āœ… | What went wrong — the symptom observed |
115
+ | `root_cause` | string | āœ… | WHY it happened — the actual root cause |
116
+ | `lesson` | string | āœ… | Key takeaway — what to remember |
117
+ | `tags` | string[] | āœ… | Categorization tags |
118
+ | `review_questions` | {q,a}[] | āœ… | 1-3 review questions for spaced repetition |
119
+ | `error_message` | string | āŒ | Exact error message or stack trace |
120
+ | `bad_code` | string | āŒ | The incorrect code snippet |
121
+ | `good_code` | string | āŒ | The corrected code snippet |
122
+ | `language` | string | āŒ | Programming language |
123
+ | `file_path` | string | āŒ | File where the error occurred |
124
+ | `git_diff` | string | āŒ | Git diff context |
125
+
126
+ **Validation rules:**
127
+ - Rejects trivial formatting/style changes
128
+ - Rejects if problem and root_cause are identical
129
+ - Requires both bad_code and good_code if either is provided
130
+ - Detects and rejects duplicates via FTS5 similarity
131
+
132
+ ### `memory`
133
+
134
+ Searches past lessons for relevant mistakes and solutions.
135
+
136
+ | Field | Type | Required | Description |
137
+ |-------|------|----------|-------------|
138
+ | `query` | string | āœ… | Search query — keyword, error pattern, or tag |
139
+ | `limit` | number | āŒ | Max results (1-10, default: 3) |
140
+ | `language` | string | āŒ | Filter by programming language |
141
+ | `tags` | string[] | āŒ | Filter by tags |
142
+
143
+ ---
144
+
145
+ ## šŸ“ Project Structure
146
+
147
+ ```
148
+ athar/
149
+ ā”œā”€ā”€ src/
150
+ │ ā”œā”€ā”€ index.ts # MCP server entry point
151
+ │ ā”œā”€ā”€ server.ts # McpServer setup & tool registration
152
+ │ ā”œā”€ā”€ db/
153
+ │ │ ā”œā”€ā”€ schema.ts # SQLite schema + FTS5 + triggers
154
+ │ │ └── connection.ts # Database singleton
155
+ │ ā”œā”€ā”€ tools/
156
+ │ │ ā”œā”€ā”€ save-lesson.ts # save_lesson handler + validation
157
+ │ │ ā”œā”€ā”€ memory.ts # memory search handler
158
+ │ │ └── validators.ts # Zod schemas
159
+ │ ā”œā”€ā”€ spaced-repetition/ # SM-2 algorithm (Phase 3)
160
+ │ ā”œā”€ā”€ cli/ # CLI commands (Phase 3)
161
+ │ └── utils/
162
+ │ ā”œā”€ā”€ paths.ts # XDG-compliant paths
163
+ │ └── logger.ts # stderr-only logger
164
+ ā”œā”€ā”€ dashboard/ # Nuxt 4 web UI (Phase 4)
165
+ ā”œā”€ā”€ package.json
166
+ └── tsconfig.json
167
+ ```
168
+
169
+ ---
170
+
171
+ ## šŸ—ŗļø Roadmap
172
+
173
+ - [x] **Phase 1** — Core MCP Server & Database
174
+ - [x] SQLite schema with FTS5 full-text search
175
+ - [x] `save_lesson` tool with quality validation
176
+ - [x] `memory` search tool with FTS5 + LIKE fallback
177
+ - [x] Duplicate detection
178
+ - [x] stderr-only logging (MCP-safe)
179
+
180
+ - [ ] **Phase 2** — IDE Integration
181
+ - [ ] `athar setup` command for Antigravity IDE
182
+ - [ ] Auto-detect and configure MCP settings
183
+
184
+ - [ ] **Phase 3** — Spaced Repetition & CLI
185
+ - [ ] SM-2 algorithm implementation
186
+ - [ ] `athar review` — interactive terminal review sessions
187
+ - [ ] `athar status` — pending reviews dashboard
188
+ - [ ] `athar list` — browse and filter lessons
189
+
190
+ - [ ] **Phase 4** — Nuxt 4 Dashboard
191
+ - [ ] Web UI for browsing lessons
192
+ - [ ] Syntax-highlighted code diff viewer
193
+ - [ ] Review progress visualization
194
+
195
+ ---
196
+
197
+ ## 🧪 Development
198
+
199
+ ```bash
200
+ # Type check
201
+ npm run typecheck
202
+
203
+ # Build
204
+ npm run build
205
+
206
+ # Run MCP server directly (for testing)
207
+ npm run dev
208
+
209
+ # Run smoke tests
210
+ npx tsx src/smoke-test.ts
211
+ ```
212
+
213
+ ### Debug logging
214
+
215
+ Set `ATHAR_DEBUG=1` to enable verbose logging to stderr:
216
+
217
+ ```bash
218
+ ATHAR_DEBUG=1 npm run dev
219
+ ```
220
+
221
+ ---
222
+
223
+ ## šŸ’” How the AI Decides to Save a Lesson
224
+
225
+ The MCP server includes detailed instructions for the AI assistant. It will save a lesson when:
226
+
227
+ - āœ… Helping fix a **non-trivial bug** with a clear root cause
228
+ - āœ… Correcting a **misconception** about an API or framework
229
+ - āœ… A **debugging session** reveals unexpected behavior
230
+ - āœ… An **architectural mistake** is identified
231
+ - āœ… A **security vulnerability** or performance issue is discovered
232
+
233
+ It will **NOT** save for:
234
+ - āŒ Simple typos or formatting fixes
235
+ - āŒ Routine code generation
236
+ - āŒ Style preferences
237
+
238
+ ---
239
+
240
+ ## šŸ“„ License
241
+
242
+ [MIT](LICENSE) — Built with ā¤ļø by [Ameen](https://github.com/ameenmv)
@@ -0,0 +1,10 @@
1
+ interface ListOptions {
2
+ tag?: string;
3
+ language?: string;
4
+ status?: string;
5
+ search?: string;
6
+ limit: string;
7
+ }
8
+ export declare function listCommand(options: ListOptions): Promise<void>;
9
+ export {};
10
+ //# sourceMappingURL=list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/list.ts"],"names":[],"mappings":"AAIA,UAAU,WAAW;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,wBAAsB,WAAW,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CA2FrE"}
@@ -0,0 +1,73 @@
1
+ import chalk from 'chalk';
2
+ import { getDatabase } from '../../db/connection.js';
3
+ import { closeDatabase } from '../../db/connection.js';
4
+ export async function listCommand(options) {
5
+ try {
6
+ const db = getDatabase();
7
+ const limit = parseInt(options.limit, 10) || 20;
8
+ let sql = `
9
+ SELECT id, title, tags, language, status, review_count,
10
+ interval_days, next_review_at, created_at
11
+ FROM lessons
12
+ `;
13
+ const conditions = [];
14
+ const params = [];
15
+ if (options.tag) {
16
+ conditions.push('tags LIKE ?');
17
+ params.push(`%"${options.tag}"%`);
18
+ }
19
+ if (options.language) {
20
+ conditions.push('language = ?');
21
+ params.push(options.language);
22
+ }
23
+ if (options.status) {
24
+ conditions.push('status = ?');
25
+ params.push(options.status);
26
+ }
27
+ if (options.search) {
28
+ conditions.push('(title LIKE ? OR problem LIKE ? OR root_cause LIKE ? OR lesson LIKE ?)');
29
+ const q = `%${options.search}%`;
30
+ params.push(q, q, q, q);
31
+ }
32
+ if (conditions.length > 0) {
33
+ sql += ' WHERE ' + conditions.join(' AND ');
34
+ }
35
+ sql += ' ORDER BY created_at DESC LIMIT ?';
36
+ params.push(limit);
37
+ const lessons = db.prepare(sql).all(...params);
38
+ if (lessons.length === 0) {
39
+ console.log(chalk.gray('\n No lessons found matching your criteria.\n'));
40
+ return;
41
+ }
42
+ console.log(chalk.bold(`\nšŸ“š Lessons (${lessons.length} results)\n`));
43
+ const statusIcons = {
44
+ new: 'šŸ†•',
45
+ learning: 'šŸ“–',
46
+ learned: 'āœ…',
47
+ mastered: 'šŸ†',
48
+ };
49
+ for (const lesson of lessons) {
50
+ const tags = JSON.parse(lesson.tags || '[]');
51
+ const icon = statusIcons[lesson.status] || 'ā“';
52
+ const date = lesson.created_at.split('T')[0];
53
+ console.log(` ${icon} ${chalk.bold.white(`#${lesson.id}`)} ${chalk.white(lesson.title)}`);
54
+ console.log(` ${chalk.gray(date)} Ā· ${chalk.blue(tags.join(', '))} Ā· ${chalk.gray(lesson.language || 'N/A')} Ā· Reviews: ${chalk.white(lesson.review_count)}`);
55
+ if (lesson.next_review_at) {
56
+ const nextReview = new Date(lesson.next_review_at);
57
+ const now = new Date();
58
+ const daysUntil = Math.ceil((nextReview.getTime() - now.getTime()) / (1000 * 60 * 60 * 24));
59
+ if (daysUntil <= 0) {
60
+ console.log(` ${chalk.yellow('āš ļø Due for review!')}`);
61
+ }
62
+ else {
63
+ console.log(` ${chalk.gray(`Next review in ${daysUntil} day(s)`)}`);
64
+ }
65
+ }
66
+ console.log();
67
+ }
68
+ }
69
+ finally {
70
+ closeDatabase();
71
+ }
72
+ }
73
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../../src/cli/commands/list.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function reviewCommand(): Promise<void>;
2
+ //# sourceMappingURL=review.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/review.ts"],"names":[],"mappings":"AAYA,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAqHnD"}
@@ -0,0 +1,112 @@
1
+ import chalk from 'chalk';
2
+ import { getDueReviews, recordReview } from '../../spaced-repetition/scheduler.js';
3
+ import { qualityLabel } from '../../spaced-repetition/sm2.js';
4
+ import { closeDatabase } from '../../db/connection.js';
5
+ import { createInterface } from 'node:readline';
6
+ function askQuestion(rl, prompt) {
7
+ return new Promise((resolve) => {
8
+ rl.question(prompt, (answer) => resolve(answer.trim()));
9
+ });
10
+ }
11
+ export async function reviewCommand() {
12
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
13
+ try {
14
+ const dueReviews = getDueReviews();
15
+ if (dueReviews.length === 0) {
16
+ console.log(chalk.green('\n ✨ No lessons due for review. Great job!'));
17
+ console.log(chalk.gray(' Check back later or run `athar status` for stats.\n'));
18
+ rl.close();
19
+ return;
20
+ }
21
+ console.log(chalk.bold(`\nā•”${'═'.repeat(50)}ā•—`));
22
+ console.log(chalk.bold(`ā•‘ Ų£Ų«Ų± Review Session — ${chalk.yellow(dueReviews.length)} lesson(s) due${' '.repeat(Math.max(0, 50 - 30 - String(dueReviews.length).length))}ā•‘`));
23
+ console.log(chalk.bold(`ā•š${'═'.repeat(50)}ā•\n`));
24
+ let reviewed = 0;
25
+ let skipped = 0;
26
+ for (let i = 0; i < dueReviews.length; i++) {
27
+ const lesson = dueReviews[i];
28
+ const tags = JSON.parse(lesson.tags || '[]');
29
+ const questions = JSON.parse(lesson.review_questions || '[]');
30
+ console.log(chalk.bold(`\nšŸ“– Lesson ${i + 1}/${dueReviews.length}: "${lesson.title}"`));
31
+ console.log(chalk.gray('━'.repeat(55)));
32
+ console.log(`${chalk.gray('Tags:')} ${tags.map(t => chalk.blue(t)).join(', ')}`);
33
+ console.log(`${chalk.gray('Language:')} ${lesson.language || 'N/A'} ${chalk.gray('Status:')} ${lesson.status}`);
34
+ // Show problem
35
+ console.log(chalk.bold('\nā— Problem:'));
36
+ console.log(chalk.white(` ${lesson.problem}`));
37
+ // Show review questions one by one
38
+ for (const question of questions) {
39
+ console.log(chalk.bold.yellow(`\nā“ ${question.q}`));
40
+ await askQuestion(rl, chalk.gray('\n Press Enter to reveal answer...'));
41
+ console.log(chalk.bold.green(`\nāœ… ${question.a}`));
42
+ }
43
+ // Show root cause and lesson
44
+ console.log(chalk.bold('\nšŸ” Root Cause:'));
45
+ console.log(chalk.white(` ${lesson.root_cause}`));
46
+ console.log(chalk.bold('\nšŸ’” Key Lesson:'));
47
+ console.log(chalk.white(` ${lesson.lesson}`));
48
+ // Show code comparison if available
49
+ if (lesson.bad_code && lesson.good_code) {
50
+ console.log(chalk.bold.red('\nāœ— Bad Code:'));
51
+ console.log(chalk.gray(' ā”Œā”€'));
52
+ for (const line of lesson.bad_code.split('\n')) {
53
+ console.log(chalk.red(` │ ${line}`));
54
+ }
55
+ console.log(chalk.gray(' └─'));
56
+ console.log(chalk.bold.green('\nāœ“ Good Code:'));
57
+ console.log(chalk.gray(' ā”Œā”€'));
58
+ for (const line of lesson.good_code.split('\n')) {
59
+ console.log(chalk.green(` │ ${line}`));
60
+ }
61
+ console.log(chalk.gray(' └─'));
62
+ }
63
+ // Ask for quality rating
64
+ console.log(chalk.bold('\nšŸ“Š How well did you recall this?'));
65
+ console.log(chalk.gray(' 0 = Complete blackout'));
66
+ console.log(chalk.gray(' 1 = Incorrect, vague memory'));
67
+ console.log(chalk.gray(' 2 = Incorrect, but recognized answer'));
68
+ console.log(chalk.gray(' 3 = Correct with difficulty'));
69
+ console.log(chalk.gray(' 4 = Correct after hesitation'));
70
+ console.log(chalk.gray(' 5 = Perfect recall'));
71
+ console.log(chalk.gray(' s = Skip this lesson'));
72
+ let quality = null;
73
+ while (quality === null) {
74
+ const answer = await askQuestion(rl, chalk.bold('\n Your rating (0-5 or s): '));
75
+ if (answer.toLowerCase() === 's') {
76
+ skipped++;
77
+ console.log(chalk.gray(' Skipped.'));
78
+ break;
79
+ }
80
+ const parsed = parseInt(answer, 10);
81
+ if (!isNaN(parsed) && parsed >= 0 && parsed <= 5) {
82
+ quality = parsed;
83
+ }
84
+ else {
85
+ console.log(chalk.red(' Please enter a number 0-5 or "s" to skip.'));
86
+ }
87
+ }
88
+ if (quality !== null) {
89
+ const result = recordReview(lesson.id, quality);
90
+ reviewed++;
91
+ console.log(`\n ${qualityLabel(quality)}`);
92
+ console.log(` → Next review in ${chalk.bold(result.intervalDays + ' day(s)')} ${chalk.green('āœ“')}`);
93
+ console.log(` → Status: ${chalk.bold(result.newStatus)}`);
94
+ }
95
+ }
96
+ // Summary
97
+ console.log(chalk.bold(`\n${'━'.repeat(55)}`));
98
+ console.log(chalk.bold('šŸ“‹ Review Session Summary'));
99
+ console.log(` Reviewed: ${chalk.green(reviewed)}`);
100
+ console.log(` Skipped: ${chalk.yellow(skipped)}`);
101
+ console.log(` Total: ${dueReviews.length}`);
102
+ console.log(chalk.bold(`${'━'.repeat(55)}\n`));
103
+ if (reviewed > 0) {
104
+ console.log(chalk.green(' šŸŽ‰ Great work! Keep learning from your mistakes.\n'));
105
+ }
106
+ }
107
+ finally {
108
+ rl.close();
109
+ closeDatabase();
110
+ }
111
+ }
112
+ //# sourceMappingURL=review.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review.js","sourceRoot":"","sources":["../../../src/cli/commands/review.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function setupCommand(): Promise<void>;
2
+ //# sourceMappingURL=setup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/setup.ts"],"names":[],"mappings":"AAKA,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAsDlD"}
@@ -0,0 +1,55 @@
1
+ import chalk from 'chalk';
2
+ import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
3
+ import { join, resolve } from 'node:path';
4
+ import { getMcpConfigPath } from '../../utils/paths.js';
5
+ export async function setupCommand() {
6
+ console.log(chalk.bold('\nšŸ”® Athar Setup — Antigravity IDE Integration\n'));
7
+ const configPath = getMcpConfigPath();
8
+ const serverPath = resolve(join(import.meta.dirname, '..', '..', '..', 'dist', 'index.js'));
9
+ // Check if dist/index.js exists
10
+ if (!existsSync(serverPath)) {
11
+ console.log(chalk.red('āŒ Built server not found at:'), serverPath);
12
+ console.log(chalk.yellow(' Run `npm run build` first.\n'));
13
+ process.exit(1);
14
+ }
15
+ console.log(chalk.gray(` Config path: ${configPath}`));
16
+ console.log(chalk.gray(` Server path: ${serverPath}\n`));
17
+ // Read or create config
18
+ let config;
19
+ if (existsSync(configPath)) {
20
+ try {
21
+ config = JSON.parse(readFileSync(configPath, 'utf-8'));
22
+ if (!config.mcpServers)
23
+ config.mcpServers = {};
24
+ }
25
+ catch {
26
+ console.log(chalk.yellow('āš ļø Existing config is invalid, creating new one...'));
27
+ config = { mcpServers: {} };
28
+ }
29
+ }
30
+ else {
31
+ // Create directory if needed
32
+ const dir = join(configPath, '..');
33
+ mkdirSync(dir, { recursive: true });
34
+ config = { mcpServers: {} };
35
+ }
36
+ // Check if already configured
37
+ if (config.mcpServers.athar) {
38
+ console.log(chalk.yellow('āš ļø Athar is already configured in your MCP settings.'));
39
+ console.log(chalk.gray(' Updating to latest path...\n'));
40
+ }
41
+ // Add/update athar entry
42
+ config.mcpServers.athar = {
43
+ command: 'node',
44
+ args: ['--experimental-sqlite', serverPath],
45
+ };
46
+ // Write config
47
+ writeFileSync(configPath, JSON.stringify(config, null, 2));
48
+ console.log(chalk.green('āœ… Athar MCP server configured successfully!\n'));
49
+ console.log(chalk.bold('Next steps:'));
50
+ console.log(chalk.white(' 1. Refresh MCP servers in Antigravity IDE'));
51
+ console.log(chalk.white(' (Click "..." → "Manage MCP Servers" → Refresh)'));
52
+ console.log(chalk.white(' 2. Start coding — the AI will save lessons automatically'));
53
+ console.log(chalk.white(' 3. Run `athar status` to check your progress\n'));
54
+ }
55
+ //# sourceMappingURL=setup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup.js","sourceRoot":"","sources":["../../../src/cli/commands/setup.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function statusCommand(): Promise<void>;
2
+ //# sourceMappingURL=status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/status.ts"],"names":[],"mappings":"AAIA,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAoCnD"}
@@ -0,0 +1,39 @@
1
+ import chalk from 'chalk';
2
+ import { getStats } from '../../spaced-repetition/scheduler.js';
3
+ import { closeDatabase } from '../../db/connection.js';
4
+ export async function statusCommand() {
5
+ try {
6
+ const stats = getStats();
7
+ console.log(chalk.bold('\nšŸ“Š Athar Memory Status'));
8
+ console.log(chalk.gray('━'.repeat(40)));
9
+ console.log(`\n Total Lessons: ${chalk.bold.white(stats.total)}`);
10
+ console.log(` Due Today: ${stats.dueToday > 0 ? chalk.bold.yellow(stats.dueToday + ' āš ļø') : chalk.green('0 āœ“')}`);
11
+ console.log(` Due This Week: ${chalk.white(stats.dueThisWeek)}`);
12
+ console.log(chalk.bold('\n By Status:'));
13
+ console.log(` šŸ†• New: ${chalk.white(stats.byStatus['new'] || 0)}`);
14
+ console.log(` šŸ“– Learning: ${chalk.cyan(stats.byStatus['learning'] || 0)}`);
15
+ console.log(` āœ… Learned: ${chalk.green(stats.byStatus['learned'] || 0)}`);
16
+ console.log(` šŸ† Mastered: ${chalk.magenta(stats.byStatus['mastered'] || 0)}`);
17
+ if (stats.topTags.length > 0) {
18
+ console.log(chalk.bold('\n Top Tags:'));
19
+ for (const { tag, count } of stats.topTags) {
20
+ const bar = chalk.blue('ā–ˆ'.repeat(Math.min(count * 2, 20)));
21
+ console.log(` ${chalk.white(tag.padEnd(18))} ${bar} ${chalk.gray(count)}`);
22
+ }
23
+ }
24
+ if (stats.dueToday > 0) {
25
+ console.log(chalk.yellow(`\n šŸ’” You have ${stats.dueToday} lesson(s) due for review!`));
26
+ console.log(chalk.white(' Run `athar review` to start.\n'));
27
+ }
28
+ else if (stats.total === 0) {
29
+ console.log(chalk.gray('\n No lessons yet. Start coding with Athar MCP in your IDE!\n'));
30
+ }
31
+ else {
32
+ console.log(chalk.green('\n ✨ All caught up! No reviews due today.\n'));
33
+ }
34
+ }
35
+ finally {
36
+ closeDatabase();
37
+ }
38
+ }
39
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../../src/cli/commands/status.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Athar CLI (Ų£Ų«Ų±)
4
+ *
5
+ * Commands:
6
+ * athar setup — Configure Antigravity IDE integration
7
+ * athar review — Interactive spaced repetition review
8
+ * athar status — Show pending reviews and stats
9
+ * athar list — Browse all lessons
10
+ */
11
+ export {};
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AAEA;;;;;;;;GAQG"}