neuro-cli 4.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 (175) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +510 -0
  3. package/dist/advisor/advisor.d.ts +50 -0
  4. package/dist/advisor/advisor.js +178 -0
  5. package/dist/agents/base.d.ts +62 -0
  6. package/dist/agents/base.js +215 -0
  7. package/dist/agents/orchestrator.d.ts +46 -0
  8. package/dist/agents/orchestrator.js +192 -0
  9. package/dist/agents/team.d.ts +51 -0
  10. package/dist/agents/team.js +210 -0
  11. package/dist/api/models.d.ts +23 -0
  12. package/dist/api/models.js +514 -0
  13. package/dist/api/ollama.d.ts +153 -0
  14. package/dist/api/ollama.js +751 -0
  15. package/dist/api/openrouter.d.ts +55 -0
  16. package/dist/api/openrouter.js +223 -0
  17. package/dist/commands/commands.d.ts +43 -0
  18. package/dist/commands/commands.js +308 -0
  19. package/dist/config/config.d.ts +8 -0
  20. package/dist/config/config.js +311 -0
  21. package/dist/context/compaction.d.ts +54 -0
  22. package/dist/context/compaction.js +251 -0
  23. package/dist/context/custom-agents.d.ts +107 -0
  24. package/dist/context/custom-agents.js +397 -0
  25. package/dist/context/custom-tools.d.ts +120 -0
  26. package/dist/context/custom-tools.js +564 -0
  27. package/dist/context/git-checkpoint.d.ts +52 -0
  28. package/dist/context/git-checkpoint.js +240 -0
  29. package/dist/context/neuro-md.d.ts +48 -0
  30. package/dist/context/neuro-md.js +202 -0
  31. package/dist/context/neuroignore.d.ts +102 -0
  32. package/dist/context/neuroignore.js +441 -0
  33. package/dist/context/repo-map.d.ts +38 -0
  34. package/dist/context/repo-map.js +220 -0
  35. package/dist/context/skill-standard.d.ts +262 -0
  36. package/dist/context/skill-standard.js +1156 -0
  37. package/dist/context/skill-system.d.ts +75 -0
  38. package/dist/context/skill-system.js +578 -0
  39. package/dist/context/tree-sitter.d.ts +99 -0
  40. package/dist/context/tree-sitter.js +1956 -0
  41. package/dist/core/acp.d.ts +325 -0
  42. package/dist/core/acp.js +1498 -0
  43. package/dist/core/api-server.d.ts +143 -0
  44. package/dist/core/api-server.js +550 -0
  45. package/dist/core/approval.d.ts +81 -0
  46. package/dist/core/approval.js +432 -0
  47. package/dist/core/auto-compact.d.ts +127 -0
  48. package/dist/core/auto-compact.js +436 -0
  49. package/dist/core/auto-mode.d.ts +232 -0
  50. package/dist/core/auto-mode.js +831 -0
  51. package/dist/core/background-session.d.ts +166 -0
  52. package/dist/core/background-session.js +696 -0
  53. package/dist/core/cicd.d.ts +257 -0
  54. package/dist/core/cicd.js +1443 -0
  55. package/dist/core/cloud-sync.d.ts +156 -0
  56. package/dist/core/cloud-sync.js +582 -0
  57. package/dist/core/code-review.d.ts +132 -0
  58. package/dist/core/code-review.js +1191 -0
  59. package/dist/core/completion.d.ts +49 -0
  60. package/dist/core/completion.js +384 -0
  61. package/dist/core/context.d.ts +38 -0
  62. package/dist/core/context.js +144 -0
  63. package/dist/core/diff-preview.d.ts +35 -0
  64. package/dist/core/diff-preview.js +173 -0
  65. package/dist/core/doom-loop.d.ts +51 -0
  66. package/dist/core/doom-loop.js +179 -0
  67. package/dist/core/engine.d.ts +183 -0
  68. package/dist/core/engine.js +942 -0
  69. package/dist/core/extended-thinking.d.ts +103 -0
  70. package/dist/core/extended-thinking.js +269 -0
  71. package/dist/core/fallback.d.ts +54 -0
  72. package/dist/core/fallback.js +104 -0
  73. package/dist/core/git-worktree.d.ts +139 -0
  74. package/dist/core/git-worktree.js +614 -0
  75. package/dist/core/headless.d.ts +30 -0
  76. package/dist/core/headless.js +101 -0
  77. package/dist/core/i18n.d.ts +83 -0
  78. package/dist/core/i18n.js +739 -0
  79. package/dist/core/linting.d.ts +129 -0
  80. package/dist/core/linting.js +699 -0
  81. package/dist/core/model-router.d.ts +109 -0
  82. package/dist/core/model-router.js +581 -0
  83. package/dist/core/multi-model.d.ts +243 -0
  84. package/dist/core/multi-model.js +1099 -0
  85. package/dist/core/multi-session.d.ts +144 -0
  86. package/dist/core/multi-session.js +442 -0
  87. package/dist/core/multimodal.d.ts +125 -0
  88. package/dist/core/multimodal.js +286 -0
  89. package/dist/core/observability.d.ts +93 -0
  90. package/dist/core/observability.js +737 -0
  91. package/dist/core/os-sandbox.d.ts +122 -0
  92. package/dist/core/os-sandbox.js +1193 -0
  93. package/dist/core/outcome-grading.d.ts +228 -0
  94. package/dist/core/outcome-grading.js +1123 -0
  95. package/dist/core/output-styles.d.ts +57 -0
  96. package/dist/core/output-styles.js +382 -0
  97. package/dist/core/parallel-agents.d.ts +183 -0
  98. package/dist/core/parallel-agents.js +563 -0
  99. package/dist/core/plugin-bundle.d.ts +236 -0
  100. package/dist/core/plugin-bundle.js +887 -0
  101. package/dist/core/plugin-sdk.d.ts +139 -0
  102. package/dist/core/plugin-sdk.js +273 -0
  103. package/dist/core/prompt-cache.d.ts +163 -0
  104. package/dist/core/prompt-cache.js +599 -0
  105. package/dist/core/sandbox.d.ts +127 -0
  106. package/dist/core/sandbox.js +369 -0
  107. package/dist/core/scheduled-tasks.d.ts +151 -0
  108. package/dist/core/scheduled-tasks.js +502 -0
  109. package/dist/core/security-scanner.d.ts +160 -0
  110. package/dist/core/security-scanner.js +1494 -0
  111. package/dist/core/session.d.ts +83 -0
  112. package/dist/core/session.js +269 -0
  113. package/dist/core/shell-completion.d.ts +51 -0
  114. package/dist/core/shell-completion.js +674 -0
  115. package/dist/core/smart-monitor.d.ts +146 -0
  116. package/dist/core/smart-monitor.js +1199 -0
  117. package/dist/core/spec-driven.d.ts +233 -0
  118. package/dist/core/spec-driven.js +1485 -0
  119. package/dist/core/spending-warnings.d.ts +123 -0
  120. package/dist/core/spending-warnings.js +456 -0
  121. package/dist/core/sub-agent.d.ts +298 -0
  122. package/dist/core/sub-agent.js +1023 -0
  123. package/dist/core/telemetry.d.ts +157 -0
  124. package/dist/core/telemetry.js +412 -0
  125. package/dist/core/terminal-ux.d.ts +134 -0
  126. package/dist/core/terminal-ux.js +649 -0
  127. package/dist/core/testing.d.ts +146 -0
  128. package/dist/core/testing.js +1200 -0
  129. package/dist/core/types.d.ts +439 -0
  130. package/dist/core/types.js +6 -0
  131. package/dist/core/undo-redo.d.ts +112 -0
  132. package/dist/core/undo-redo.js +290 -0
  133. package/dist/core/updater.d.ts +159 -0
  134. package/dist/core/updater.js +608 -0
  135. package/dist/core/vim-mode.d.ts +151 -0
  136. package/dist/core/vim-mode.js +771 -0
  137. package/dist/core/voice.d.ts +137 -0
  138. package/dist/core/voice.js +538 -0
  139. package/dist/core/web-dashboard.d.ts +109 -0
  140. package/dist/core/web-dashboard.js +484 -0
  141. package/dist/hooks/hooks.d.ts +74 -0
  142. package/dist/hooks/hooks.js +160 -0
  143. package/dist/hooks/llm-evaluator.d.ts +165 -0
  144. package/dist/hooks/llm-evaluator.js +560 -0
  145. package/dist/index.d.ts +3 -0
  146. package/dist/index.js +1186 -0
  147. package/dist/lsp/lsp-manager.d.ts +63 -0
  148. package/dist/lsp/lsp-manager.js +351 -0
  149. package/dist/mcp/client.d.ts +133 -0
  150. package/dist/mcp/client.js +684 -0
  151. package/dist/mcp/mcp-apps.d.ts +70 -0
  152. package/dist/mcp/mcp-apps.js +1007 -0
  153. package/dist/tools/bash.d.ts +5 -0
  154. package/dist/tools/bash.js +195 -0
  155. package/dist/tools/browser.d.ts +92 -0
  156. package/dist/tools/browser.js +1570 -0
  157. package/dist/tools/extended.d.ts +6 -0
  158. package/dist/tools/extended.js +191 -0
  159. package/dist/tools/file.d.ts +10 -0
  160. package/dist/tools/file.js +382 -0
  161. package/dist/tools/github.d.ts +389 -0
  162. package/dist/tools/github.js +759 -0
  163. package/dist/tools/index.d.ts +9 -0
  164. package/dist/tools/index.js +40 -0
  165. package/dist/tools/memory.d.ts +6 -0
  166. package/dist/tools/memory.js +197 -0
  167. package/dist/tools/registry.d.ts +29 -0
  168. package/dist/tools/registry.js +64 -0
  169. package/dist/tools/web.d.ts +6 -0
  170. package/dist/tools/web.js +150 -0
  171. package/dist/ui/renderer.d.ts +97 -0
  172. package/dist/ui/renderer.js +279 -0
  173. package/dist/ui/theme.d.ts +27 -0
  174. package/dist/ui/theme.js +106 -0
  175. package/package.json +83 -0
@@ -0,0 +1,240 @@
1
+ // ============================================================
2
+ // NeuroCLI - Git Auto-Commit & Checkpointing
3
+ // (Like Aider's auto-commit + Gemini CLI's shadow repo)
4
+ // ============================================================
5
+ import { execSync } from 'child_process';
6
+ import { existsSync, mkdirSync, writeFileSync } from 'fs';
7
+ import { join } from 'path';
8
+ import { homedir } from 'os';
9
+ export class GitCheckpointSystem {
10
+ workingDirectory;
11
+ shadowRepo;
12
+ autoCommit;
13
+ checkpoints = [];
14
+ constructor(workingDirectory, autoCommit = true) {
15
+ this.workingDirectory = workingDirectory;
16
+ this.autoCommit = autoCommit;
17
+ // Shadow repo for checkpointing (doesn't interfere with user's git)
18
+ const projectHash = this.hashString(workingDirectory);
19
+ this.shadowRepo = join(homedir(), '.neuro', 'checkpoints', projectHash);
20
+ }
21
+ /**
22
+ * Initialize the checkpoint system
23
+ */
24
+ initialize() {
25
+ if (!this.isGitRepo())
26
+ return false;
27
+ this.ensureShadowRepo();
28
+ return true;
29
+ }
30
+ /**
31
+ * Create a checkpoint before risky operations
32
+ */
33
+ createCheckpoint(message) {
34
+ const changedFiles = this.getChangedFiles();
35
+ if (changedFiles.length === 0) {
36
+ return null;
37
+ }
38
+ const checkpoint = {
39
+ id: `cp_${Date.now()}`,
40
+ timestamp: Date.now(),
41
+ message,
42
+ files: changedFiles,
43
+ };
44
+ // Option 1: Git stash-based checkpoint (quick)
45
+ if (this.autoCommit) {
46
+ try {
47
+ // Stage all changes
48
+ execSync('git add -A', { cwd: this.workingDirectory, encoding: 'utf-8' });
49
+ // Commit with checkpoint marker
50
+ const commitMsg = `neuro:checkpoint ${message}`;
51
+ execSync(`git commit -m "${commitMsg}" --no-gpg-sign`, {
52
+ cwd: this.workingDirectory,
53
+ encoding: 'utf-8',
54
+ });
55
+ const hash = execSync('git rev-parse HEAD', {
56
+ cwd: this.workingDirectory,
57
+ encoding: 'utf-8',
58
+ }).trim();
59
+ checkpoint.hash = hash;
60
+ }
61
+ catch {
62
+ // Nothing to commit or commit failed
63
+ }
64
+ }
65
+ // Option 2: Shadow repo snapshot
66
+ this.saveShadowSnapshot(checkpoint);
67
+ this.checkpoints.push(checkpoint);
68
+ return checkpoint;
69
+ }
70
+ /**
71
+ * Restore to a checkpoint
72
+ */
73
+ restore(checkpointId) {
74
+ const checkpoint = this.checkpoints.find(c => c.id === checkpointId);
75
+ if (!checkpoint)
76
+ return false;
77
+ // Try git restore first
78
+ if (checkpoint.hash) {
79
+ try {
80
+ execSync(`git reset --hard ${checkpoint.hash}`, {
81
+ cwd: this.workingDirectory,
82
+ encoding: 'utf-8',
83
+ });
84
+ return true;
85
+ }
86
+ catch { }
87
+ }
88
+ // Fallback: restore from shadow repo
89
+ return this.restoreShadowSnapshot(checkpoint);
90
+ }
91
+ /**
92
+ * Undo the last checkpoint
93
+ */
94
+ undo() {
95
+ if (this.checkpoints.length === 0)
96
+ return false;
97
+ const lastCheckpoint = this.checkpoints[this.checkpoints.length - 1];
98
+ return this.restore(lastCheckpoint.id);
99
+ }
100
+ /**
101
+ * List all checkpoints
102
+ */
103
+ listCheckpoints() {
104
+ return [...this.checkpoints];
105
+ }
106
+ /**
107
+ * Get changed files since last commit
108
+ */
109
+ getChangedFiles() {
110
+ try {
111
+ const status = execSync('git status --porcelain', {
112
+ cwd: this.workingDirectory,
113
+ encoding: 'utf-8',
114
+ });
115
+ return status.trim().split('\n')
116
+ .filter(l => l.trim())
117
+ .map(l => l.slice(3).trim());
118
+ }
119
+ catch {
120
+ return [];
121
+ }
122
+ }
123
+ /**
124
+ * Get diff of changes
125
+ */
126
+ getDiff() {
127
+ try {
128
+ return execSync('git diff', {
129
+ cwd: this.workingDirectory,
130
+ encoding: 'utf-8',
131
+ });
132
+ }
133
+ catch {
134
+ return '';
135
+ }
136
+ }
137
+ /**
138
+ * Auto-commit changes with a message
139
+ */
140
+ autoCommitChanges(message) {
141
+ if (!this.autoCommit)
142
+ return null;
143
+ if (!this.isGitRepo())
144
+ return null;
145
+ const changed = this.getChangedFiles();
146
+ if (changed.length === 0)
147
+ return null;
148
+ try {
149
+ execSync('git add -A', { cwd: this.workingDirectory, encoding: 'utf-8' });
150
+ execSync(`git commit -m "neuro: ${message}" --no-gpg-sign`, {
151
+ cwd: this.workingDirectory,
152
+ encoding: 'utf-8',
153
+ });
154
+ const hash = execSync('git rev-parse --short HEAD', {
155
+ cwd: this.workingDirectory,
156
+ encoding: 'utf-8',
157
+ }).trim();
158
+ return hash;
159
+ }
160
+ catch {
161
+ return null;
162
+ }
163
+ }
164
+ // ---- Private ----
165
+ isGitRepo() {
166
+ try {
167
+ execSync('git rev-parse --is-inside-work-tree', {
168
+ cwd: this.workingDirectory,
169
+ encoding: 'utf-8',
170
+ stdio: 'pipe',
171
+ });
172
+ return true;
173
+ }
174
+ catch {
175
+ return false;
176
+ }
177
+ }
178
+ ensureShadowRepo() {
179
+ if (!existsSync(this.shadowRepo)) {
180
+ mkdirSync(this.shadowRepo, { recursive: true });
181
+ }
182
+ // Initialize shadow repo if needed
183
+ const gitDir = join(this.shadowRepo, '.git');
184
+ if (!existsSync(gitDir)) {
185
+ try {
186
+ execSync('git init', { cwd: this.shadowRepo, encoding: 'utf-8' });
187
+ }
188
+ catch { }
189
+ }
190
+ }
191
+ saveShadowSnapshot(checkpoint) {
192
+ const snapshotDir = join(this.shadowRepo, checkpoint.id);
193
+ if (!existsSync(snapshotDir)) {
194
+ mkdirSync(snapshotDir, { recursive: true });
195
+ }
196
+ // Save checkpoint metadata
197
+ writeFileSync(join(snapshotDir, 'meta.json'), JSON.stringify(checkpoint, null, 2), 'utf-8');
198
+ // Copy changed files to snapshot
199
+ for (const file of checkpoint.files) {
200
+ const src = join(this.workingDirectory, file);
201
+ const dst = join(snapshotDir, 'files', file);
202
+ if (existsSync(src)) {
203
+ try {
204
+ mkdirSync(join(dst, '..'), { recursive: true });
205
+ const { copyFileSync } = require('fs');
206
+ copyFileSync(src, dst);
207
+ }
208
+ catch { }
209
+ }
210
+ }
211
+ }
212
+ restoreShadowSnapshot(checkpoint) {
213
+ const snapshotDir = join(this.shadowRepo, checkpoint.id, 'files');
214
+ if (!existsSync(snapshotDir))
215
+ return false;
216
+ for (const file of checkpoint.files) {
217
+ const src = join(snapshotDir, file);
218
+ const dst = join(this.workingDirectory, file);
219
+ if (existsSync(src)) {
220
+ try {
221
+ const { copyFileSync } = require('fs');
222
+ mkdirSync(join(dst, '..'), { recursive: true });
223
+ copyFileSync(src, dst);
224
+ }
225
+ catch { }
226
+ }
227
+ }
228
+ return true;
229
+ }
230
+ hashString(str) {
231
+ let hash = 0;
232
+ for (let i = 0; i < str.length; i++) {
233
+ const char = str.charCodeAt(i);
234
+ hash = ((hash << 5) - hash) + char;
235
+ hash |= 0;
236
+ }
237
+ return Math.abs(hash).toString(36);
238
+ }
239
+ }
240
+ //# sourceMappingURL=git-checkpoint.js.map
@@ -0,0 +1,48 @@
1
+ export interface NeuroMdLayer {
2
+ scope: 'global' | 'user' | 'project' | 'local' | 'directory';
3
+ path: string;
4
+ content: string;
5
+ size: number;
6
+ }
7
+ export declare class NeuroMdSystem {
8
+ private workingDirectory;
9
+ private layers;
10
+ private watchers;
11
+ private onChange?;
12
+ constructor(workingDirectory: string, onChange?: () => void);
13
+ /**
14
+ * Load all NEURO.md layers in priority order
15
+ * Global → User → Project → Local → Directory
16
+ */
17
+ load(): NeuroMdLayer[];
18
+ /**
19
+ * Get the combined context from all NEURO.md layers
20
+ */
21
+ getCombinedContext(): string;
22
+ /**
23
+ * Get total size of all layers
24
+ */
25
+ getTotalSize(): number;
26
+ /**
27
+ * Initialize a new NEURO.md in the project
28
+ */
29
+ initProject(): string;
30
+ /**
31
+ * Watch NEURO.md files for changes
32
+ */
33
+ startWatching(): void;
34
+ /**
35
+ * Stop watching NEURO.md files
36
+ */
37
+ stopWatching(): void;
38
+ private tryLoadLayer;
39
+ private loadRulesDirectory;
40
+ /**
41
+ * Process @import references in NEURO.md
42
+ * e.g. @path/to/file.md → injects file contents
43
+ */
44
+ private processImports;
45
+ private detectTechStack;
46
+ private generateStarterMd;
47
+ }
48
+ //# sourceMappingURL=neuro-md.d.ts.map
@@ -0,0 +1,202 @@
1
+ // ============================================================
2
+ // NeuroCLI - NEURO.md Persistent Context System
3
+ // Hierarchical project instructions (like CLAUDE.md / GEMINI.md)
4
+ // ============================================================
5
+ import { readFileSync, existsSync, watchFile, unwatchFile } from 'fs';
6
+ import { join } from 'path';
7
+ import { homedir } from 'os';
8
+ export class NeuroMdSystem {
9
+ workingDirectory;
10
+ layers = [];
11
+ watchers = [];
12
+ onChange;
13
+ constructor(workingDirectory, onChange) {
14
+ this.workingDirectory = workingDirectory;
15
+ this.onChange = onChange;
16
+ }
17
+ /**
18
+ * Load all NEURO.md layers in priority order
19
+ * Global → User → Project → Local → Directory
20
+ */
21
+ load() {
22
+ this.layers = [];
23
+ // 1. Global: ~/.neuro/NEURO.md
24
+ this.tryLoadLayer('global', join(homedir(), '.neuro', 'NEURO.md'));
25
+ // 2. User: ~/.neuro/NEURO.md (same as global for now)
26
+ // Already loaded above
27
+ // 3. Project: NEURO.md in project root
28
+ this.tryLoadLayer('project', join(this.workingDirectory, 'NEURO.md'));
29
+ // 4. Project (alt): .neuro/NEURO.md
30
+ this.tryLoadLayer('project', join(this.workingDirectory, '.neuro', 'NEURO.md'));
31
+ // 5. Local: NEURO.local.md (gitignored)
32
+ this.tryLoadLayer('local', join(this.workingDirectory, 'NEURO.local.md'));
33
+ // 6. Rules: .neuro/rules/*.md
34
+ this.loadRulesDirectory();
35
+ return this.layers;
36
+ }
37
+ /**
38
+ * Get the combined context from all NEURO.md layers
39
+ */
40
+ getCombinedContext() {
41
+ if (this.layers.length === 0)
42
+ return '';
43
+ const parts = [];
44
+ parts.push('## Project Context (NEURO.md)\n');
45
+ for (const layer of this.layers) {
46
+ parts.push(`### [${layer.scope}] ${layer.path}\n${layer.content}\n`);
47
+ }
48
+ return parts.join('\n');
49
+ }
50
+ /**
51
+ * Get total size of all layers
52
+ */
53
+ getTotalSize() {
54
+ return this.layers.reduce((sum, l) => sum + l.size, 0);
55
+ }
56
+ /**
57
+ * Initialize a new NEURO.md in the project
58
+ */
59
+ initProject() {
60
+ const { writeFileSync } = require('fs');
61
+ const projectMd = join(this.workingDirectory, 'NEURO.md');
62
+ if (existsSync(projectMd)) {
63
+ return `NEURO.md already exists at ${projectMd}`;
64
+ }
65
+ // Auto-detect tech stack
66
+ const techStack = this.detectTechStack();
67
+ const content = this.generateStarterMd(techStack);
68
+ writeFileSync(projectMd, content, 'utf-8');
69
+ return `Created NEURO.md at ${projectMd}`;
70
+ }
71
+ /**
72
+ * Watch NEURO.md files for changes
73
+ */
74
+ startWatching() {
75
+ this.stopWatching();
76
+ const paths = [
77
+ join(homedir(), '.neuro', 'NEURO.md'),
78
+ join(this.workingDirectory, 'NEURO.md'),
79
+ join(this.workingDirectory, '.neuro', 'NEURO.md'),
80
+ join(this.workingDirectory, 'NEURO.local.md'),
81
+ ];
82
+ for (const path of paths) {
83
+ if (existsSync(path)) {
84
+ try {
85
+ watchFile(path, { interval: 5000 }, () => {
86
+ this.load(); // Reload on change
87
+ this.onChange?.();
88
+ });
89
+ this.watchers.push({ path, close: () => unwatchFile(path) });
90
+ }
91
+ catch { }
92
+ }
93
+ }
94
+ }
95
+ /**
96
+ * Stop watching NEURO.md files
97
+ */
98
+ stopWatching() {
99
+ for (const w of this.watchers) {
100
+ w.close();
101
+ }
102
+ this.watchers = [];
103
+ }
104
+ // ---- Private Methods ----
105
+ tryLoadLayer(scope, path) {
106
+ if (!existsSync(path))
107
+ return;
108
+ try {
109
+ const content = readFileSync(path, 'utf-8');
110
+ // Process @import references
111
+ const processed = this.processImports(content, path);
112
+ this.layers.push({ scope, path, content: processed, size: content.length });
113
+ }
114
+ catch { }
115
+ }
116
+ loadRulesDirectory() {
117
+ const rulesDir = join(this.workingDirectory, '.neuro', 'rules');
118
+ if (!existsSync(rulesDir))
119
+ return;
120
+ try {
121
+ const { readdirSync } = require('fs');
122
+ const files = readdirSync(rulesDir).filter((f) => f.endsWith('.md'));
123
+ for (const file of files) {
124
+ this.tryLoadLayer('directory', join(rulesDir, file));
125
+ }
126
+ }
127
+ catch { }
128
+ }
129
+ /**
130
+ * Process @import references in NEURO.md
131
+ * e.g. @path/to/file.md → injects file contents
132
+ */
133
+ processImports(content, basePath) {
134
+ const importRegex = /@([^\s\n]+\.(?:md|txt|json5?|yaml|yml))/g;
135
+ return content.replace(importRegex, (match, refPath) => {
136
+ const fullPath = refPath.startsWith('/')
137
+ ? refPath
138
+ : join(basePath, '..', refPath);
139
+ if (existsSync(fullPath)) {
140
+ try {
141
+ return readFileSync(fullPath, 'utf-8');
142
+ }
143
+ catch {
144
+ return match;
145
+ }
146
+ }
147
+ return match;
148
+ });
149
+ }
150
+ detectTechStack() {
151
+ const stack = [];
152
+ const checks = [
153
+ { file: 'package.json', tech: 'Node.js/JavaScript' },
154
+ { file: 'tsconfig.json', tech: 'TypeScript' },
155
+ { file: 'pyproject.toml', tech: 'Python' },
156
+ { file: 'Cargo.toml', tech: 'Rust' },
157
+ { file: 'go.mod', tech: 'Go' },
158
+ { file: 'pom.xml', tech: 'Java/Maven' },
159
+ { file: 'build.gradle', tech: 'Java/Gradle' },
160
+ { file: 'Dockerfile', tech: 'Docker' },
161
+ { file: 'docker-compose.yml', tech: 'Docker Compose' },
162
+ { file: '.github/workflows', tech: 'GitHub Actions' },
163
+ { file: 'Gemfile', tech: 'Ruby' },
164
+ { file: 'mix.exs', tech: 'Elixir' },
165
+ { file: 'composer.json', tech: 'PHP' },
166
+ ];
167
+ for (const { file, tech } of checks) {
168
+ if (existsSync(join(this.workingDirectory, file))) {
169
+ stack.push(tech);
170
+ }
171
+ }
172
+ return stack;
173
+ }
174
+ generateStarterMd(techStack) {
175
+ return `# NeuroCLI Project Context
176
+
177
+ ## Tech Stack
178
+ ${techStack.map(t => `- ${t}`).join('\n') || '- Auto-detected on first run'}
179
+
180
+ ## Project Structure
181
+ <!-- Describe your project structure here -->
182
+
183
+ ## Conventions
184
+ <!-- Add your coding conventions and preferences -->
185
+ - Follow existing code style
186
+ - Write tests for new features
187
+ - Use meaningful variable names
188
+
189
+ ## Common Commands
190
+ <!-- Add frequently used commands -->
191
+ \`\`\`bash
192
+ # Build
193
+ # Test
194
+ # Deploy
195
+ \`\`\`
196
+
197
+ ## Important Notes
198
+ <!-- Any important context for the AI assistant -->
199
+ `;
200
+ }
201
+ }
202
+ //# sourceMappingURL=neuro-md.js.map
@@ -0,0 +1,102 @@
1
+ export interface IgnoreRule {
2
+ pattern: string;
3
+ negated: boolean;
4
+ regex: RegExp;
5
+ source: string;
6
+ }
7
+ export declare class NeuroIgnore {
8
+ private rules;
9
+ private cache;
10
+ private projectRoot;
11
+ private loaded;
12
+ constructor(projectRoot: string);
13
+ /**
14
+ * Load ignore rules from all sources:
15
+ * 1. Default patterns
16
+ * 2. ~/.neuro/ignore (global user rules)
17
+ * 3. .neuroignore (project-root rules)
18
+ */
19
+ load(): void;
20
+ /**
21
+ * Check whether a given file path should be ignored.
22
+ * The path may be absolute or relative to projectRoot.
23
+ *
24
+ * Evaluation order matters: later rules override earlier ones.
25
+ * Negated patterns (prefixed with !) un-ignore previously matched paths.
26
+ */
27
+ isIgnored(filePath: string): boolean;
28
+ /**
29
+ * Filter an array of paths, removing those that are ignored.
30
+ */
31
+ filterPaths(paths: string[]): string[];
32
+ /**
33
+ * Dynamically add a rule at runtime.
34
+ */
35
+ addRule(pattern: string, source?: string): void;
36
+ /**
37
+ * Remove a rule by its original pattern string.
38
+ * Returns true if a rule was found and removed.
39
+ */
40
+ removeRule(pattern: string): boolean;
41
+ /**
42
+ * Return a shallow copy of the current rules list.
43
+ */
44
+ getRules(): IgnoreRule[];
45
+ /**
46
+ * Clear the result cache.
47
+ */
48
+ clearCache(): void;
49
+ /**
50
+ * Print all active rules to stdout (useful for debugging).
51
+ */
52
+ printRules(): void;
53
+ static readonly DEFAULT_IGNORED: string[];
54
+ /**
55
+ * Load rules from a single file. Lines starting with # are comments.
56
+ * Blank lines are skipped. Trailing whitespace is trimmed.
57
+ */
58
+ private loadFromFile;
59
+ /**
60
+ * Populate the default ignore rules.
61
+ */
62
+ private loadDefaultRules;
63
+ /**
64
+ * Convert a gitignore-style glob pattern into a RegExp.
65
+ *
66
+ * Supported features:
67
+ * * matches anything except /
68
+ * ** matches anything including /
69
+ * ? matches any single character except /
70
+ * [abc] character class
71
+ * [a-z] character range
72
+ * {a,b} brace expansion (alternation)
73
+ * !prefix negation (handled separately before this method)
74
+ *
75
+ * A trailing / means the pattern only matches directories; we keep
76
+ * the regex flexible enough to match both for simplicity, but strip
77
+ * the trailing slash indicator.
78
+ */
79
+ private patternToRegex;
80
+ /**
81
+ * Escape a string for use inside a RegExp.
82
+ */
83
+ private escapeRegex;
84
+ /**
85
+ * Ensure rules have been loaded before answering queries.
86
+ */
87
+ private ensureLoaded;
88
+ /**
89
+ * Convert a file path to a relative posix-style path from projectRoot.
90
+ * - Absolute paths are made relative to projectRoot.
91
+ * - Backslashes (Windows) are converted to forward slashes.
92
+ * - Leading ./ is stripped.
93
+ */
94
+ private toRelativePosix;
95
+ /**
96
+ * Auto-detect common directories in the project root that should
97
+ * typically be ignored (e.g. a large "vendor" or "dist" directory
98
+ * that was not already covered by default patterns).
99
+ */
100
+ private autoDetectIgnorableDirs;
101
+ }
102
+ //# sourceMappingURL=neuroignore.d.ts.map