@neurcode-ai/cli 0.7.2 → 0.7.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.
@@ -0,0 +1,300 @@
1
+ "use strict";
2
+ /**
3
+ * Init Command - Magic Init
4
+ *
5
+ * Zero-friction project initialization with auto-discovery and context menu.
6
+ *
7
+ * Flow:
8
+ * 1. Auto-detect directory name
9
+ * 2. Check .neurcode/config.json
10
+ * 3. If missing: Check API for existing project, create if not found
11
+ * 4. If present: Show context menu (Start Session, View History)
12
+ */
13
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ var desc = Object.getOwnPropertyDescriptor(m, k);
16
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
17
+ desc = { enumerable: true, get: function() { return m[k]; } };
18
+ }
19
+ Object.defineProperty(o, k2, desc);
20
+ }) : (function(o, m, k, k2) {
21
+ if (k2 === undefined) k2 = k;
22
+ o[k2] = m[k];
23
+ }));
24
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
25
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
26
+ }) : function(o, v) {
27
+ o["default"] = v;
28
+ });
29
+ var __importStar = (this && this.__importStar) || (function () {
30
+ var ownKeys = function(o) {
31
+ ownKeys = Object.getOwnPropertyNames || function (o) {
32
+ var ar = [];
33
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
34
+ return ar;
35
+ };
36
+ return ownKeys(o);
37
+ };
38
+ return function (mod) {
39
+ if (mod && mod.__esModule) return mod;
40
+ var result = {};
41
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
42
+ __setModuleDefault(result, mod);
43
+ return result;
44
+ };
45
+ })();
46
+ Object.defineProperty(exports, "__esModule", { value: true });
47
+ exports.initCommand = initCommand;
48
+ const path_1 = require("path");
49
+ const config_1 = require("../config");
50
+ const api_client_1 = require("../api-client");
51
+ const state_1 = require("../utils/state");
52
+ const readline = __importStar(require("readline"));
53
+ // Import chalk with fallback
54
+ let chalk;
55
+ try {
56
+ chalk = require('chalk');
57
+ }
58
+ catch {
59
+ chalk = {
60
+ green: (str) => str,
61
+ yellow: (str) => str,
62
+ red: (str) => str,
63
+ bold: (str) => str,
64
+ dim: (str) => str,
65
+ cyan: (str) => str,
66
+ white: (str) => str,
67
+ blue: (str) => str,
68
+ };
69
+ }
70
+ /**
71
+ * Get user input from terminal
72
+ */
73
+ function promptUser(question) {
74
+ const rl = readline.createInterface({
75
+ input: process.stdin,
76
+ output: process.stdout,
77
+ });
78
+ return new Promise((resolve) => {
79
+ rl.question(question, (answer) => {
80
+ rl.close();
81
+ resolve(answer.trim());
82
+ });
83
+ });
84
+ }
85
+ /**
86
+ * Display context menu and get user choice
87
+ */
88
+ async function showContextMenu(project, sessions) {
89
+ console.log(chalk.bold.cyan(`\nšŸ“ Project: ${project.name}`));
90
+ console.log(chalk.dim(` ID: ${project.id}\n`));
91
+ console.log(chalk.bold.white('What would you like to do?\n'));
92
+ const options = [
93
+ { key: '1', label: 'šŸš€ Start New Session (Plan)', value: 'new-session' },
94
+ { key: '2', label: 'šŸ“œ View Session History', value: 'history' },
95
+ { key: '3', label: 'āŒ Exit', value: 'exit' },
96
+ ];
97
+ options.forEach(opt => {
98
+ console.log(chalk.cyan(` ${opt.key}.`), chalk.white(opt.label));
99
+ });
100
+ console.log('');
101
+ const answer = await promptUser(chalk.bold('Select option (1-3): '));
102
+ switch (answer) {
103
+ case '1':
104
+ return 'new-session';
105
+ case '2':
106
+ return 'history';
107
+ case '3':
108
+ default:
109
+ return 'exit';
110
+ }
111
+ }
112
+ /**
113
+ * Display session history menu
114
+ */
115
+ async function showHistoryMenu(sessions) {
116
+ if (sessions.length === 0) {
117
+ console.log(chalk.yellow('\nšŸ“œ No sessions found for this project.\n'));
118
+ return null;
119
+ }
120
+ console.log(chalk.bold.white('\nšŸ“œ Session History (Last 5)\n'));
121
+ const options = sessions.map((session, index) => {
122
+ const emoji = session.status === 'active' ? '⚔' : session.status === 'completed' ? 'āœ…' : 'šŸ“';
123
+ const title = session.title || session.intentDescription || 'Untitled Session';
124
+ const status = session.status === 'active' ? chalk.green('Active') :
125
+ session.status === 'completed' ? chalk.dim('Completed') :
126
+ chalk.yellow(session.status);
127
+ return {
128
+ key: (index + 1).toString(),
129
+ session,
130
+ label: `${emoji} ${title} (${status})`,
131
+ };
132
+ });
133
+ options.forEach(opt => {
134
+ console.log(chalk.cyan(` ${opt.key}.`), chalk.white(opt.label));
135
+ });
136
+ console.log(chalk.cyan(` ${options.length + 1}.`), chalk.white('āž• Create New Session'));
137
+ console.log(chalk.cyan(` ${options.length + 2}.`), chalk.white('šŸ”™ Back'));
138
+ console.log('');
139
+ const answer = await promptUser(chalk.bold(`Select session (1-${options.length + 2}): `));
140
+ const choice = parseInt(answer, 10);
141
+ if (choice >= 1 && choice <= options.length) {
142
+ return options[choice - 1].session.sessionId;
143
+ }
144
+ else if (choice === options.length + 1) {
145
+ return 'new-session';
146
+ }
147
+ else {
148
+ return null; // Back
149
+ }
150
+ }
151
+ async function initCommand() {
152
+ try {
153
+ const config = (0, config_1.loadConfig)();
154
+ const apiKey = (0, config_1.requireApiKey)();
155
+ const apiUrl = config.apiUrl || config_1.DEFAULT_API_URL;
156
+ console.log(chalk.cyan('\nšŸš€ Initializing Neurcode...\n'));
157
+ // Step 1: Auto-detect directory name
158
+ const cwd = process.cwd();
159
+ const dirName = (0, path_1.basename)(cwd);
160
+ console.log(chalk.dim(`Detected directory: ${dirName}\n`));
161
+ // Step 2: Check local state
162
+ const state = (0, state_1.loadState)();
163
+ const existingProjectId = (0, state_1.getProjectId)() || state.projectId;
164
+ // Initialize API client
165
+ const client = new api_client_1.ApiClient({ ...config, apiKey });
166
+ let project = null;
167
+ if (existingProjectId) {
168
+ // Project already linked
169
+ console.log(chalk.green('āœ… Project already initialized\n'));
170
+ // Fetch project details
171
+ try {
172
+ const projects = await client.getProjects();
173
+ project = projects.find(p => p.id === existingProjectId) || null;
174
+ if (!project) {
175
+ console.log(chalk.yellow(`āš ļø Project ID ${existingProjectId} not found. Resetting...\n`));
176
+ // Clear invalid project ID
177
+ (0, state_1.saveState)({ projectId: undefined });
178
+ }
179
+ }
180
+ catch (error) {
181
+ console.log(chalk.yellow(`āš ļø Could not verify project. Continuing...\n`));
182
+ }
183
+ }
184
+ // Step 3: Auto-discovery if no project linked
185
+ if (!project && !existingProjectId) {
186
+ console.log(chalk.dim(`Checking for existing project "${dirName}"...\n`));
187
+ // Check if project exists by name
188
+ try {
189
+ const existingProject = await client.getProjectByName(dirName);
190
+ if (existingProject) {
191
+ // Project exists - ask to link
192
+ console.log(chalk.cyan(`Found existing project: ${existingProject.name}\n`));
193
+ const answer = await promptUser(chalk.bold(`Link this directory to "${existingProject.name}"? (y/n): `));
194
+ if (answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes') {
195
+ project = existingProject;
196
+ (0, state_1.setProjectId)(project.id);
197
+ console.log(chalk.green(`\nāœ… Linked to project: ${project.name}\n`));
198
+ }
199
+ else {
200
+ console.log(chalk.yellow('\nSkipped. Run "neurcode init" again when ready.\n'));
201
+ process.exit(0);
202
+ }
203
+ }
204
+ else {
205
+ // Project doesn't exist - create it
206
+ console.log(chalk.dim(`No existing project found for "${dirName}"\n`));
207
+ const answer = await promptUser(chalk.bold(`Create new project "${dirName}"? (y/n): `));
208
+ if (answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes') {
209
+ // Create project (using connect endpoint with empty gitUrl)
210
+ try {
211
+ const newProject = await client.ensureProject('', dirName);
212
+ project = {
213
+ id: newProject.id,
214
+ name: newProject.name,
215
+ slug: dirName.toLowerCase().replace(/[^a-z0-9]+/g, '-'),
216
+ git_url: null,
217
+ };
218
+ (0, state_1.setProjectId)(project.id);
219
+ console.log(chalk.green(`\nāœ… Created and linked project: ${project.name}\n`));
220
+ }
221
+ catch (error) {
222
+ console.error(chalk.red(`\nāŒ Failed to create project: ${error instanceof Error ? error.message : 'Unknown error'}\n`));
223
+ process.exit(1);
224
+ }
225
+ }
226
+ else {
227
+ console.log(chalk.yellow('\nSkipped. Run "neurcode init" again when ready.\n'));
228
+ process.exit(0);
229
+ }
230
+ }
231
+ }
232
+ catch (error) {
233
+ console.error(chalk.red(`\nāŒ Error during auto-discovery: ${error instanceof Error ? error.message : 'Unknown error'}\n`));
234
+ process.exit(1);
235
+ }
236
+ }
237
+ if (!project) {
238
+ console.error(chalk.red('\nāŒ No project available.\n'));
239
+ process.exit(1);
240
+ }
241
+ // Step 4: Context Menu
242
+ let done = false;
243
+ while (!done) {
244
+ // Fetch recent sessions
245
+ let sessions = [];
246
+ try {
247
+ sessions = await client.getSessions(project.id, 5);
248
+ }
249
+ catch (error) {
250
+ // If fetching sessions fails, continue without history
251
+ if (process.env.DEBUG) {
252
+ console.log(chalk.dim(`Warning: Could not fetch sessions: ${error instanceof Error ? error.message : 'Unknown error'}`));
253
+ }
254
+ }
255
+ const choice = await showContextMenu(project, sessions);
256
+ switch (choice) {
257
+ case 'new-session': {
258
+ console.log(chalk.cyan('\nšŸš€ Starting new session...\n'));
259
+ console.log(chalk.dim('Run: neurcode plan "<your intent>"\n'));
260
+ done = true;
261
+ break;
262
+ }
263
+ case 'history': {
264
+ const sessionChoice = await showHistoryMenu(sessions);
265
+ if (sessionChoice === 'new-session') {
266
+ console.log(chalk.cyan('\nšŸš€ Starting new session...\n'));
267
+ console.log(chalk.dim('Run: neurcode plan "<your intent>"\n'));
268
+ done = true;
269
+ }
270
+ else if (sessionChoice) {
271
+ console.log(chalk.cyan(`\nšŸ“‹ Session: ${sessionChoice}\n`));
272
+ console.log(chalk.dim('Use this session ID with neurcode commands\n'));
273
+ // Could implement session detail view here
274
+ done = true;
275
+ }
276
+ // If sessionChoice is null (back), continue loop
277
+ break;
278
+ }
279
+ case 'exit':
280
+ console.log(chalk.dim('\nšŸ‘‹ Goodbye!\n'));
281
+ done = true;
282
+ break;
283
+ }
284
+ }
285
+ }
286
+ catch (error) {
287
+ console.error(chalk.red('\nāŒ Error during initialization:'));
288
+ if (error instanceof Error) {
289
+ console.error(chalk.red(error.message));
290
+ if (error.message.includes('Authentication') || error.message.includes('401') || error.message.includes('403')) {
291
+ console.log(chalk.dim('\nšŸ’” Run "neurcode login" to authenticate.\n'));
292
+ }
293
+ }
294
+ else {
295
+ console.error(error);
296
+ }
297
+ process.exit(1);
298
+ }
299
+ }
300
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuIH,kCA8JC;AAnSD,+BAAgC;AAChC,sCAAuE;AACvE,8CAA0C;AAC1C,0CAAkF;AAClF,mDAAqC;AAErC,6BAA6B;AAC7B,IAAI,KAAU,CAAC;AACf,IAAI,CAAC;IACH,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;AAC3B,CAAC;AAAC,MAAM,CAAC;IACP,KAAK,GAAG;QACN,KAAK,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,GAAG;QAC3B,MAAM,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,GAAG;QAC5B,GAAG,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,GAAG;QACzB,IAAI,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,GAAG;QAC1B,GAAG,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,GAAG;QACzB,IAAI,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,GAAG;QAC1B,KAAK,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,GAAG;QAC3B,IAAI,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,GAAG;KAC3B,CAAC;AACJ,CAAC;AAkBD;;GAEG;AACH,SAAS,UAAU,CAAC,QAAgB;IAClC,MAAM,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC;QAClC,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,MAAM,EAAE,OAAO,CAAC,MAAM;KACvB,CAAC,CAAC;IAEH,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,EAAE;YAC/B,EAAE,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;QACzB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,eAAe,CAAC,OAAgB,EAAE,QAAmB;IAClE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,iBAAiB,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IAC9D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,OAAO,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;IAEjD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,8BAA8B,CAAC,CAAC,CAAC;IAE9D,MAAM,OAAO,GAAG;QACd,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,6BAA6B,EAAE,KAAK,EAAE,aAAa,EAAE;QACxE,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,yBAAyB,EAAE,KAAK,EAAE,SAAS,EAAE;QAChE,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE;KAC7C,CAAC;IAEF,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE;QACpB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,GAAG,GAAG,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;IACnE,CAAC,CAAC,CAAC;IACH,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAEhB,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC,CAAC;IAErE,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,GAAG;YACN,OAAO,aAAa,CAAC;QACvB,KAAK,GAAG;YACN,OAAO,SAAS,CAAC;QACnB,KAAK,GAAG,CAAC;QACT;YACE,OAAO,MAAM,CAAC;IAClB,CAAC;AACH,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,eAAe,CAAC,QAAmB;IAChD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,4CAA4C,CAAC,CAAC,CAAC;QACxE,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,iCAAiC,CAAC,CAAC,CAAC;IAEjE,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE;QAC9C,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;QAC9F,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,iBAAiB,IAAI,kBAAkB,CAAC;QAC/E,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC;YACrD,OAAO,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC;gBACzD,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC5C,OAAO;YACL,GAAG,EAAE,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE;YAC3B,OAAO;YACP,KAAK,EAAE,GAAG,KAAK,IAAI,KAAK,KAAK,MAAM,GAAG;SACvC,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE;QACpB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,GAAG,GAAG,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;IACnE,CAAC,CAAC,CAAC;IAEH,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,OAAO,CAAC,MAAM,GAAG,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC,CAAC;IACzF,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,OAAO,CAAC,MAAM,GAAG,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC;IAC5E,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAEhB,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,qBAAqB,OAAO,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;IAC1F,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAEpC,IAAI,MAAM,IAAI,CAAC,IAAI,MAAM,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QAC5C,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC;IAC/C,CAAC;SAAM,IAAI,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzC,OAAO,aAAa,CAAC;IACvB,CAAC;SAAM,CAAC;QACN,OAAO,IAAI,CAAC,CAAC,OAAO;IACtB,CAAC;AACH,CAAC;AAEM,KAAK,UAAU,WAAW;IAC/B,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAA,mBAAU,GAAE,CAAC;QAC5B,MAAM,MAAM,GAAG,IAAA,sBAAa,GAAE,CAAC;QAC/B,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,wBAAe,CAAC;QAEhD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC,CAAC;QAE3D,qCAAqC;QACrC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;QAC1B,MAAM,OAAO,GAAG,IAAA,eAAQ,EAAC,GAAG,CAAC,CAAC;QAC9B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,uBAAuB,OAAO,IAAI,CAAC,CAAC,CAAC;QAE3D,4BAA4B;QAC5B,MAAM,KAAK,GAAG,IAAA,iBAAS,GAAE,CAAC;QAC1B,MAAM,iBAAiB,GAAG,IAAA,oBAAY,GAAE,IAAI,KAAK,CAAC,SAAS,CAAC;QAE5D,wBAAwB;QACxB,MAAM,MAAM,GAAG,IAAI,sBAAS,CAAC,EAAE,GAAG,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;QAEpD,IAAI,OAAO,GAAmB,IAAI,CAAC;QAEnC,IAAI,iBAAiB,EAAE,CAAC;YACtB,yBAAyB;YACzB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,iCAAiC,CAAC,CAAC,CAAC;YAE5D,wBAAwB;YACxB,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,WAAW,EAAE,CAAC;gBAC5C,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,iBAAiB,CAAC,IAAI,IAAI,CAAC;gBAEjE,IAAI,CAAC,OAAO,EAAE,CAAC;oBACb,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,kBAAkB,iBAAiB,4BAA4B,CAAC,CAAC,CAAC;oBAC3F,2BAA2B;oBAC3B,IAAA,iBAAS,EAAC,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC,CAAC;gBACtC,CAAC;YACH,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,+CAA+C,CAAC,CAAC,CAAC;YAC7E,CAAC;QACH,CAAC;QAED,8CAA8C;QAC9C,IAAI,CAAC,OAAO,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACnC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,kCAAkC,OAAO,QAAQ,CAAC,CAAC,CAAC;YAE1E,kCAAkC;YAClC,IAAI,CAAC;gBACH,MAAM,eAAe,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;gBAE/D,IAAI,eAAe,EAAE,CAAC;oBACpB,+BAA+B;oBAC/B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,2BAA2B,eAAe,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC;oBAC7E,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,2BAA2B,eAAe,CAAC,IAAI,YAAY,CAAC,CAAC,CAAC;oBAEzG,IAAI,MAAM,CAAC,WAAW,EAAE,KAAK,GAAG,IAAI,MAAM,CAAC,WAAW,EAAE,KAAK,KAAK,EAAE,CAAC;wBACnE,OAAO,GAAG,eAAe,CAAC;wBAC1B,IAAA,oBAAY,EAAC,OAAO,CAAC,EAAE,CAAC,CAAC;wBACzB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,0BAA0B,OAAO,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC;oBACvE,CAAC;yBAAM,CAAC;wBACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,oDAAoD,CAAC,CAAC,CAAC;wBAChF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;oBAClB,CAAC;gBACH,CAAC;qBAAM,CAAC;oBACN,oCAAoC;oBACpC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,kCAAkC,OAAO,KAAK,CAAC,CAAC,CAAC;oBACvE,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,uBAAuB,OAAO,YAAY,CAAC,CAAC,CAAC;oBAExF,IAAI,MAAM,CAAC,WAAW,EAAE,KAAK,GAAG,IAAI,MAAM,CAAC,WAAW,EAAE,KAAK,KAAK,EAAE,CAAC;wBACnE,4DAA4D;wBAC5D,IAAI,CAAC;4BACH,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;4BAE3D,OAAO,GAAG;gCACR,EAAE,EAAE,UAAU,CAAC,EAAE;gCACjB,IAAI,EAAE,UAAU,CAAC,IAAI;gCACrB,IAAI,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC;gCACvD,OAAO,EAAE,IAAI;6BACd,CAAC;4BAEF,IAAA,oBAAY,EAAC,OAAO,CAAC,EAAE,CAAC,CAAC;4BACzB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,mCAAmC,OAAO,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC;wBAChF,CAAC;wBAAC,OAAO,KAAK,EAAE,CAAC;4BACf,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,iCAAiC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,IAAI,CAAC,CAAC,CAAC;4BACxH,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;wBAClB,CAAC;oBACH,CAAC;yBAAM,CAAC;wBACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,oDAAoD,CAAC,CAAC,CAAC;wBAChF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;oBAClB,CAAC;gBACH,CAAC;YACH,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,oCAAoC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,IAAI,CAAC,CAAC,CAAC;gBAC3H,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;QACH,CAAC;QAED,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAC,CAAC;YACxD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,uBAAuB;QACvB,IAAI,IAAI,GAAG,KAAK,CAAC;QACjB,OAAO,CAAC,IAAI,EAAE,CAAC;YACb,wBAAwB;YACxB,IAAI,QAAQ,GAAc,EAAE,CAAC;YAC7B,IAAI,CAAC;gBACH,QAAQ,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;YACrD,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,uDAAuD;gBACvD,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC;oBACtB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,sCAAsC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC;gBAC3H,CAAC;YACH,CAAC;YAED,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;YAExD,QAAQ,MAAM,EAAE,CAAC;gBACf,KAAK,aAAa,CAAC,CAAC,CAAC;oBACnB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC,CAAC;oBAC1D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,sCAAsC,CAAC,CAAC,CAAC;oBAC/D,IAAI,GAAG,IAAI,CAAC;oBACZ,MAAM;gBACR,CAAC;gBACD,KAAK,SAAS,CAAC,CAAC,CAAC;oBACf,MAAM,aAAa,GAAG,MAAM,eAAe,CAAC,QAAQ,CAAC,CAAC;oBACtD,IAAI,aAAa,KAAK,aAAa,EAAE,CAAC;wBACpC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC,CAAC;wBAC1D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,sCAAsC,CAAC,CAAC,CAAC;wBAC/D,IAAI,GAAG,IAAI,CAAC;oBACd,CAAC;yBAAM,IAAI,aAAa,EAAE,CAAC;wBACzB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,iBAAiB,aAAa,IAAI,CAAC,CAAC,CAAC;wBAC5D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,8CAA8C,CAAC,CAAC,CAAC;wBACvE,2CAA2C;wBAC3C,IAAI,GAAG,IAAI,CAAC;oBACd,CAAC;oBACD,iDAAiD;oBACjD,MAAM;gBACR,CAAC;gBACD,KAAK,MAAM;oBACT,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC;oBAC1C,IAAI,GAAG,IAAI,CAAC;oBACZ,MAAM;YACV,CAAC;QACH,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC,CAAC;QAC7D,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;YAC3B,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;YAExC,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC/G,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,8CAA8C,CAAC,CAAC,CAAC;YACzE,CAAC;QACH,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACvB,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Login Command
3
+ *
4
+ * Implements device flow authentication for CLI.
5
+ * User runs `neurcode login` → Opens browser → Approves → CLI saves API key globally
6
+ */
7
+ export declare function loginCommand(): Promise<void>;
8
+ //# sourceMappingURL=login.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAuBH,wBAAsB,YAAY,kBAkJjC"}
@@ -0,0 +1,194 @@
1
+ "use strict";
2
+ /**
3
+ * Login Command
4
+ *
5
+ * Implements device flow authentication for CLI.
6
+ * User runs `neurcode login` → Opens browser → Approves → CLI saves API key globally
7
+ */
8
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
9
+ if (k2 === undefined) k2 = k;
10
+ var desc = Object.getOwnPropertyDescriptor(m, k);
11
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
12
+ desc = { enumerable: true, get: function() { return m[k]; } };
13
+ }
14
+ Object.defineProperty(o, k2, desc);
15
+ }) : (function(o, m, k, k2) {
16
+ if (k2 === undefined) k2 = k;
17
+ o[k2] = m[k];
18
+ }));
19
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
20
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
21
+ }) : function(o, v) {
22
+ o["default"] = v;
23
+ });
24
+ var __importStar = (this && this.__importStar) || (function () {
25
+ var ownKeys = function(o) {
26
+ ownKeys = Object.getOwnPropertyNames || function (o) {
27
+ var ar = [];
28
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
29
+ return ar;
30
+ };
31
+ return ownKeys(o);
32
+ };
33
+ return function (mod) {
34
+ if (mod && mod.__esModule) return mod;
35
+ var result = {};
36
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
37
+ __setModuleDefault(result, mod);
38
+ return result;
39
+ };
40
+ })();
41
+ Object.defineProperty(exports, "__esModule", { value: true });
42
+ exports.loginCommand = loginCommand;
43
+ const config_1 = require("../config");
44
+ // Import chalk with fallback
45
+ let chalk;
46
+ try {
47
+ chalk = require('chalk');
48
+ }
49
+ catch {
50
+ chalk = {
51
+ green: (str) => str,
52
+ yellow: (str) => str,
53
+ red: (str) => str,
54
+ bold: (str) => str,
55
+ dim: (str) => str,
56
+ cyan: (str) => str,
57
+ white: (str) => str,
58
+ };
59
+ }
60
+ const POLL_INTERVAL = 3000; // 3 seconds
61
+ const MAX_POLL_ATTEMPTS = 100; // 5 minutes total (100 * 3s)
62
+ async function loginCommand() {
63
+ try {
64
+ const config = (0, config_1.loadConfig)();
65
+ const apiUrl = config.apiUrl || config_1.DEFAULT_API_URL;
66
+ console.log(chalk.cyan('\nšŸ” Authenticating Neurcode CLI...\n'));
67
+ // Step 1: Initialize device flow
68
+ const initUrl = `${apiUrl}/cli/auth/init`;
69
+ let initResponse;
70
+ try {
71
+ initResponse = await fetch(initUrl, {
72
+ method: 'POST',
73
+ headers: {
74
+ 'Content-Type': 'application/json',
75
+ },
76
+ body: JSON.stringify({}), // Fastify requires a body when Content-Type is application/json
77
+ });
78
+ }
79
+ catch (error) {
80
+ console.error(`\nšŸ” [DEBUG] Fetch failed for URL: ${initUrl}`);
81
+ console.error(`šŸ” [DEBUG] API Base URL: ${apiUrl}`);
82
+ console.error(`šŸ” [DEBUG] Error: ${error instanceof Error ? error.message : String(error)}`);
83
+ throw error;
84
+ }
85
+ if (!initResponse.ok) {
86
+ const errorText = await initResponse.text();
87
+ throw new Error(`Failed to initialize authentication: ${errorText}`);
88
+ }
89
+ const initData = await initResponse.json();
90
+ const { deviceCode, userCode, verificationUrl, expiresIn } = initData;
91
+ // Step 2: Display user code and open browser
92
+ console.log(chalk.bold.white('1. Open this URL in your browser:'));
93
+ console.log(chalk.cyan(` ${verificationUrl}\n`));
94
+ console.log(chalk.bold.white('2. Enter this code:'));
95
+ console.log(chalk.bold.green(` ${userCode}\n`));
96
+ console.log(chalk.dim('Waiting for approval...'));
97
+ // Open browser (cross-platform)
98
+ const { exec } = await Promise.resolve().then(() => __importStar(require('child_process')));
99
+ const platform = process.platform;
100
+ let command;
101
+ if (platform === 'darwin') {
102
+ command = `open "${verificationUrl}"`;
103
+ }
104
+ else if (platform === 'win32') {
105
+ command = `start "" "${verificationUrl}"`;
106
+ }
107
+ else {
108
+ command = `xdg-open "${verificationUrl}"`;
109
+ }
110
+ try {
111
+ exec(command, (error) => {
112
+ if (error) {
113
+ console.log(chalk.yellow(' (Could not open browser automatically. Please open the URL manually.)\n'));
114
+ }
115
+ });
116
+ }
117
+ catch (error) {
118
+ // Browser opening failed, but continue with polling
119
+ console.log(chalk.yellow(' (Could not open browser automatically. Please open the URL manually.)\n'));
120
+ }
121
+ // Step 3: Poll for approval
122
+ let pollAttempts = 0;
123
+ let approved = false;
124
+ while (pollAttempts < MAX_POLL_ATTEMPTS && !approved) {
125
+ await new Promise(resolve => setTimeout(resolve, POLL_INTERVAL));
126
+ const pollUrl = `${apiUrl}/cli/auth/poll`;
127
+ let pollResponse;
128
+ try {
129
+ pollResponse = await fetch(pollUrl, {
130
+ method: 'POST',
131
+ headers: {
132
+ 'Content-Type': 'application/json',
133
+ },
134
+ body: JSON.stringify({ deviceCode }),
135
+ });
136
+ }
137
+ catch (error) {
138
+ console.error(`\nšŸ” [DEBUG] Fetch failed for URL: ${pollUrl}`);
139
+ console.error(`šŸ” [DEBUG] API Base URL: ${apiUrl}`);
140
+ console.error(`šŸ” [DEBUG] Error: ${error instanceof Error ? error.message : String(error)}`);
141
+ throw error;
142
+ }
143
+ if (!pollResponse.ok) {
144
+ throw new Error(`Polling failed: ${pollResponse.statusText}`);
145
+ }
146
+ const pollData = await pollResponse.json();
147
+ if (pollData.status === 'approved') {
148
+ if (pollData.apiKey) {
149
+ // Save API key to global config
150
+ (0, config_1.saveGlobalAuth)(pollData.apiKey, apiUrl);
151
+ console.log(chalk.green('\nāœ… Authentication successful!\n'));
152
+ console.log(chalk.dim('API key saved to: ~/.neurcoderc'));
153
+ console.log(chalk.dim('You can now use neurcode commands.\n'));
154
+ approved = true;
155
+ }
156
+ else {
157
+ // Already approved but key was retrieved
158
+ console.log(chalk.yellow('\nāš ļø Authentication was already approved, but API key was not available.'));
159
+ console.log(chalk.dim('Please check your API keys or try logging in again.\n'));
160
+ approved = true;
161
+ }
162
+ }
163
+ else if (pollData.status === 'denied') {
164
+ console.log(chalk.red('\nāŒ Authentication denied.\n'));
165
+ process.exit(1);
166
+ }
167
+ else if (pollData.status === 'expired') {
168
+ console.log(chalk.red('\nāŒ Authentication request expired. Please try again.\n'));
169
+ process.exit(1);
170
+ }
171
+ else {
172
+ // pending - continue polling
173
+ process.stdout.write('.');
174
+ pollAttempts++;
175
+ }
176
+ }
177
+ if (!approved) {
178
+ console.log(chalk.red('\n\nāŒ Authentication timed out. Please try again.\n'));
179
+ process.exit(1);
180
+ }
181
+ }
182
+ catch (error) {
183
+ console.error(chalk.red('\nāŒ Error during authentication:'));
184
+ if (error instanceof Error) {
185
+ console.error(chalk.red(error.message));
186
+ }
187
+ else {
188
+ console.error(error);
189
+ }
190
+ console.log(chalk.dim('\nšŸ’” Make sure you have an active internet connection and try again.\n'));
191
+ process.exit(1);
192
+ }
193
+ }
194
+ //# sourceMappingURL=login.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"plan.d.ts","sourceRoot":"","sources":["../../src/commands/plan.ts"],"names":[],"mappings":"AAyBA,UAAU,WAAW;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAkND,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,iBA6OrE"}
1
+ {"version":3,"file":"plan.d.ts","sourceRoot":"","sources":["../../src/commands/plan.ts"],"names":[],"mappings":"AA0BA,UAAU,WAAW;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAkND,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,iBA8MrE"}
@@ -40,6 +40,7 @@ const config_1 = require("../config");
40
40
  const api_client_1 = require("../api-client");
41
41
  const project_detector_1 = require("../utils/project-detector");
42
42
  const map_1 = require("./map");
43
+ const state_1 = require("../utils/state");
43
44
  // Import chalk with fallback for plain strings if not available
44
45
  let chalk;
45
46
  try {
@@ -263,8 +264,15 @@ async function planCommand(intent, options) {
263
264
  }
264
265
  // Initialize API client
265
266
  const client = new api_client_1.ApiClient(config);
266
- // Implicit Project Discovery: Auto-detect and connect project
267
- let projectId = config.projectId;
267
+ // CRITICAL: Check state file FIRST for headless workflow support
268
+ // Priority: state file (.neurcode/config.json) > config > auto-detection
269
+ const { getProjectId } = await Promise.resolve().then(() => __importStar(require('../utils/state')));
270
+ let projectId = getProjectId(); // Priority 1: State file (headless-friendly)
271
+ // Fallback to config if state file doesn't have projectId
272
+ if (!projectId) {
273
+ projectId = config.projectId || null;
274
+ }
275
+ // Only auto-detect if we still don't have a projectId (interactive mode)
268
276
  if (!projectId) {
269
277
  try {
270
278
  const projectInfo = (0, project_detector_1.detectProject)();
@@ -273,23 +281,11 @@ async function planCommand(intent, options) {
273
281
  console.log(chalk.dim(`šŸ”— Connecting project: ${projectInfo.name || 'detecting...'}`));
274
282
  const project = await client.ensureProject(projectInfo.gitUrl, projectInfo.name || undefined);
275
283
  projectId = project.id;
276
- // Save projectId to config file
277
- const { writeFileSync, existsSync, readFileSync } = await Promise.resolve().then(() => __importStar(require('fs')));
278
- const configPath = (0, path_1.join)(process.cwd(), 'neurcode.config.json');
279
- let configData = {};
280
- if (existsSync(configPath)) {
281
- try {
282
- configData = JSON.parse(readFileSync(configPath, 'utf-8'));
283
- }
284
- catch {
285
- // Ignore parse errors
286
- }
287
- }
288
- configData.apiKey = config.apiKey;
289
- configData.projectId = projectId;
290
- writeFileSync(configPath, JSON.stringify(configData, null, 2) + '\n', 'utf-8');
284
+ // Save projectId to state file (.neurcode/config.json)
285
+ const { setProjectId } = await Promise.resolve().then(() => __importStar(require('../utils/state')));
286
+ setProjectId(projectId);
291
287
  console.log(chalk.green(`āœ… Project connected: ${project.name}`));
292
- console.log(chalk.dim(` Project ID saved to neurcode.config.json\n`));
288
+ console.log(chalk.dim(` Project ID saved to .neurcode/config.json\n`));
293
289
  }
294
290
  else {
295
291
  // No Git URL - use name-based project (will be created by API if needed)
@@ -335,7 +331,8 @@ async function planCommand(intent, options) {
335
331
  }
336
332
  }
337
333
  console.log(chalk.dim('šŸ¤– Generating plan...\n'));
338
- // Use projectId from options, config, or auto-detected
334
+ // Final projectId priority: options (explicit) > projectId (from above logic) > config (fallback)
335
+ // Note: projectId already includes state file check from above
339
336
  const finalProjectId = options.projectId || projectId || config.projectId;
340
337
  // Generate plan with enhanced intent (includes asset map context)
341
338
  const response = await client.generatePlan(enhancedIntent, files, finalProjectId);
@@ -387,7 +384,7 @@ async function planCommand(intent, options) {
387
384
  console.log(chalk.dim('\n No files to snapshot\n'));
388
385
  }
389
386
  }
390
- // Display the plan
387
+ // Display the plans
391
388
  displayPlan(response.plan);
392
389
  console.log(chalk.dim(`\nGenerated at: ${new Date(response.timestamp).toLocaleString()}`));
393
390
  // Display plan ID if available
@@ -395,43 +392,20 @@ async function planCommand(intent, options) {
395
392
  console.log(chalk.bold.cyan(`\nšŸ“Œ Plan ID: ${response.planId} (Saved)`));
396
393
  console.log(chalk.dim(' Run \'neurcode prompt <id>\' to generate a Cursor/AI prompt. (Ready now)'));
397
394
  }
398
- // Save sessionId and planId to config file for subsequent commands
395
+ // Save sessionId and planId to state file (.neurcode/config.json)
399
396
  try {
400
- const { writeFileSync, existsSync, readFileSync } = await Promise.resolve().then(() => __importStar(require('fs')));
401
- const configPath = (0, path_1.join)(process.cwd(), 'neurcode.config.json');
402
- let configData = {};
403
- if (existsSync(configPath)) {
404
- try {
405
- configData = JSON.parse(readFileSync(configPath, 'utf-8'));
406
- }
407
- catch {
408
- // Ignore parse errors, start fresh
409
- }
410
- }
411
- // Preserve existing config values
412
- if (config.apiKey) {
413
- configData.apiKey = config.apiKey;
414
- }
415
- if (config.projectId) {
416
- configData.projectId = config.projectId;
417
- }
418
- // Save planId and sessionId
419
397
  if (response.planId && response.planId !== 'unknown') {
420
- configData.lastPlanId = response.planId;
421
- }
422
- if (response.sessionId) {
423
- configData.sessionId = response.sessionId;
424
- configData.lastSessionId = response.sessionId;
398
+ (0, state_1.setLastPlanId)(response.planId);
425
399
  }
426
- writeFileSync(configPath, JSON.stringify(configData, null, 2) + '\n', 'utf-8');
427
400
  if (response.sessionId) {
428
- console.log(chalk.dim(` Session ID saved to neurcode.config.json`));
401
+ (0, state_1.setSessionId)(response.sessionId);
402
+ console.log(chalk.dim(` Session ID saved to .neurcode/config.json`));
429
403
  }
430
404
  }
431
- catch (configError) {
405
+ catch (stateError) {
432
406
  // Log warning but don't fail the command
433
407
  if (process.env.DEBUG) {
434
- console.warn(chalk.yellow(`āš ļø Could not save sessionId to config: ${configError instanceof Error ? configError.message : 'Unknown error'}`));
408
+ console.warn(chalk.yellow(`āš ļø Could not save sessionId to state: ${stateError instanceof Error ? stateError.message : 'Unknown error'}`));
435
409
  }
436
410
  }
437
411
  }