thufir 2.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.
@@ -0,0 +1,547 @@
1
+ import * as p from '@clack/prompts';
2
+ import pc from 'picocolors';
3
+ import { execSync } from 'node:child_process';
4
+ import { basename } from 'node:path';
5
+ import { validateToken } from './api.js';
6
+ import { printBanner, printStepHeader, printRealignScreen, printMergeScreen, STEP_TITLES } from './ui/ascii.js';
7
+ const TRAIT_OPTIONS = [
8
+ { value: 'consultant', label: 'Top Consultant', hint: 'MBB problem-solving, pyramid communication, Zelazny data viz. Your McKinsey associate.' },
9
+ { value: 'psychology', label: 'Human Psychology', hint: 'Parts (IFS), systemic thinking (Hellinger), compassion. Understands people.' },
10
+ ];
11
+ const TRAIT_LABELS = {
12
+ 'mentat-core': 'Mentat Discipline',
13
+ 'consultant': 'Top Consultant',
14
+ 'psychology': 'Human Psychology',
15
+ };
16
+ const SKILL_PACKAGE_OPTIONS = [
17
+ { value: 'superpowers', label: 'Superpowers', hint: 'Brainstorming, TDD, systematic debugging, code review, plans' },
18
+ { value: 'gstack', label: 'gstack (Garry Tan)', hint: 'Browser QA, code review, shipping, CEO/eng plan review' },
19
+ ];
20
+ const SKILL_PACKAGE_LABELS = {
21
+ 'superpowers': 'Superpowers',
22
+ 'gstack': 'gstack (Garry Tan)',
23
+ };
24
+ const TRIGGER_OPTIONS = [
25
+ { value: 'brainstorming', label: '📋 Brainstorming', hint: 'requirements, creative work, problem solving' },
26
+ { value: 'plans', label: '📋 Implementation Plans', hint: 'break specs into step-by-step plans' },
27
+ { value: 'ceo-review', label: '📋 CEO/Product Review', hint: 'rethink requirements, find 10-star solution' },
28
+ { value: 'eng-review', label: '📋 Engineering Review', hint: 'lock architecture, map edge cases' },
29
+ { value: 'tdd', label: '🔧 Test-Driven Development', hint: 'write tests first, then implement' },
30
+ { value: 'code-review', label: '🔧 Code Review', hint: 'review before merging, verify feedback' },
31
+ { value: 'verification', label: '🔧 Verification', hint: 'run checks before claiming complete' },
32
+ { value: 'debugging', label: '🔧 Systematic Debugging', hint: 'scientific method for bugs' },
33
+ { value: 'browse', label: '🌐 Browser Automation', hint: 'test features in headless Chromium' },
34
+ { value: 'qa', label: '🌐 QA Testing', hint: 'systematic test → find → fix → verify' },
35
+ { value: 'design-review', label: '🌐 Design Audit', hint: '80-item visual/UX audit' },
36
+ { value: 'shipping', label: '🚀 Shipping', hint: 'tests, comments, push, PR' },
37
+ { value: 'parallel', label: '🚀 Parallel Agents', hint: 'dispatch subagents for independent tasks' },
38
+ { value: 'retro', label: '🚀 Retrospective', hint: 'commit history, work patterns' },
39
+ ];
40
+ const ALL_TRIGGER_VALUES = TRIGGER_OPTIONS.map(t => t.value);
41
+ async function promptAndValidateToken(savedToken) {
42
+ let tokenValue;
43
+ if (savedToken) {
44
+ tokenValue = savedToken;
45
+ p.log.info('Using saved token from .thufir.local');
46
+ }
47
+ else {
48
+ const token = await p.password({
49
+ message: 'Enter your access token',
50
+ });
51
+ if (p.isCancel(token))
52
+ return null;
53
+ tokenValue = token;
54
+ }
55
+ const s = p.spinner();
56
+ s.start('Validating token...');
57
+ const validation = await validateToken(tokenValue);
58
+ s.stop(validation.valid ? 'Token validated' : 'Token invalid');
59
+ if (!validation.valid) {
60
+ p.log.error(validation.error || 'Invalid token');
61
+ return null;
62
+ }
63
+ p.log.success(`${validation.projects_remaining} project${validation.projects_remaining === 1 ? '' : 's'} remaining, expires ${validation.expires?.split('T')[0]}`);
64
+ return tokenValue;
65
+ }
66
+ const TOTAL_STEPS = 7;
67
+ export async function runPrompts(analysis, savedToken) {
68
+ const cwd = process.cwd();
69
+ let step = 1;
70
+ let token = '';
71
+ let userName = '';
72
+ let colleagueName = 'Thufir';
73
+ let projectMode = 'single';
74
+ let projectDescription = '';
75
+ let projectFocus = 'hybrid';
76
+ let traits = ['mentat-core', 'consultant', 'psychology'];
77
+ let skillPackages = [];
78
+ let skillTriggers = [];
79
+ let setupGitHub = 'skip';
80
+ let repoName = basename(cwd);
81
+ // Skip token step if we have a saved token
82
+ if (savedToken) {
83
+ const s = p.spinner();
84
+ printBanner();
85
+ s.start('Validating saved token...');
86
+ const validation = await validateToken(savedToken);
87
+ s.stop(validation.valid ? 'Token validated' : 'Token invalid');
88
+ if (validation.valid) {
89
+ token = savedToken;
90
+ step = 2;
91
+ }
92
+ else {
93
+ p.log.warn('Saved token is no longer valid. Please enter a new one.');
94
+ }
95
+ }
96
+ while (step <= TOTAL_STEPS) {
97
+ if (step === 1) {
98
+ printBanner();
99
+ const result = await promptAndValidateToken();
100
+ if (result === null)
101
+ return null;
102
+ token = result;
103
+ step = 2;
104
+ continue;
105
+ }
106
+ if (step === 2) {
107
+ printStepHeader(2, TOTAL_STEPS, STEP_TITLES[2]);
108
+ const nameResult = await p.text({
109
+ message: "What's your name?",
110
+ placeholder: 'Your name',
111
+ defaultValue: userName || undefined,
112
+ validate: (v) => !v || v.length === 0 ? 'Name is required' : undefined,
113
+ });
114
+ if (p.isCancel(nameResult)) {
115
+ step = 1;
116
+ continue;
117
+ }
118
+ userName = nameResult;
119
+ const colleagueResult = await p.text({
120
+ message: 'What should your AI colleague be called?',
121
+ placeholder: 'Thufir',
122
+ defaultValue: colleagueName,
123
+ });
124
+ if (p.isCancel(colleagueResult)) {
125
+ step = 1;
126
+ continue;
127
+ }
128
+ colleagueName = colleagueResult || 'Thufir';
129
+ step = 3;
130
+ continue;
131
+ }
132
+ if (step === 3) {
133
+ printStepHeader(3, TOTAL_STEPS, STEP_TITLES[3]);
134
+ const modeResult = await p.select({
135
+ message: 'What kind of project is this?',
136
+ options: [
137
+ { value: 'single', label: 'Single project', hint: 'one repo, focused scope' },
138
+ { value: 'multi', label: 'Multi-project orchestrator', hint: 'manages sub-projects (coming soon)' },
139
+ ],
140
+ });
141
+ if (p.isCancel(modeResult)) {
142
+ step = 2;
143
+ continue;
144
+ }
145
+ projectMode = modeResult;
146
+ if (projectMode === 'multi') {
147
+ p.log.warn('Multi-project mode templates are coming soon. Setting up single-project for now.');
148
+ }
149
+ const descResult = await p.text({
150
+ message: 'What is this project about?',
151
+ placeholder: 'A coaching business website with client portal',
152
+ defaultValue: projectDescription || undefined,
153
+ validate: (v) => !v || v.length === 0 ? 'Please describe your project' : undefined,
154
+ });
155
+ if (p.isCancel(descResult)) {
156
+ step = 2;
157
+ continue;
158
+ }
159
+ projectDescription = descResult;
160
+ const focusResult = await p.select({
161
+ message: 'Which best describes the focus?',
162
+ options: [
163
+ { value: 'code', label: 'Mostly code', hint: 'building software, APIs, frontends' },
164
+ { value: 'planning', label: 'Mostly planning', hint: 'business docs, research, strategy' },
165
+ { value: 'hybrid', label: 'Both', hint: 'code AND business/project management' },
166
+ ],
167
+ });
168
+ if (p.isCancel(focusResult)) {
169
+ step = 2;
170
+ continue;
171
+ }
172
+ projectFocus = focusResult;
173
+ step = 4;
174
+ continue;
175
+ }
176
+ if (step === 4) {
177
+ printStepHeader(4, TOTAL_STEPS, STEP_TITLES[4]);
178
+ console.log(` ${pc.green('✓')} ${pc.bold('Mentat Discipline')} ${pc.dim('(core — always installed)')}`);
179
+ console.log(pc.dim(' The brain. Learns, structures, remembers. Direct and precise.'));
180
+ console.log();
181
+ const traitsResult = await p.multiselect({
182
+ message: 'Additional personality traits:',
183
+ options: TRAIT_OPTIONS,
184
+ initialValues: traits.filter(t => t !== 'mentat-core'),
185
+ required: false,
186
+ });
187
+ if (p.isCancel(traitsResult)) {
188
+ step = 3;
189
+ continue;
190
+ }
191
+ traits = ['mentat-core', ...(traitsResult || [])];
192
+ // Confirm selection
193
+ const selected = traits.map(t => TRAIT_LABELS[t] || t).join(', ');
194
+ console.log();
195
+ console.log(pc.dim(` Selected: ${selected}`));
196
+ const ok = await p.select({
197
+ message: 'Continue with these traits?',
198
+ options: [
199
+ { value: 'yes', label: '✓ Continue', hint: 'proceed to next step' },
200
+ { value: 'no', label: '← Re-select', hint: 'choose again' },
201
+ ],
202
+ });
203
+ if (p.isCancel(ok)) {
204
+ step = 3;
205
+ continue;
206
+ }
207
+ if (ok === 'no')
208
+ continue; // Re-run step 4
209
+ step = 5;
210
+ continue;
211
+ }
212
+ if (step === 5) {
213
+ printStepHeader(5, TOTAL_STEPS, STEP_TITLES[5]);
214
+ console.log(pc.yellow(` ⚠ Skills install to ~/.claude/skills/ and will be`));
215
+ console.log(pc.yellow(` available in ALL your Claude Code projects.`));
216
+ console.log();
217
+ const defaultSkills = skillPackages.length > 0 ? skillPackages : ['superpowers', 'gstack'];
218
+ const skillsResult = await p.multiselect({
219
+ message: 'Which skill packages should be available?',
220
+ options: SKILL_PACKAGE_OPTIONS,
221
+ initialValues: defaultSkills,
222
+ required: false,
223
+ });
224
+ if (p.isCancel(skillsResult)) {
225
+ step = 4;
226
+ continue;
227
+ }
228
+ skillPackages = skillsResult || [];
229
+ // Confirm
230
+ const selected = skillPackages.map(s => SKILL_PACKAGE_LABELS[s] || s).join(', ') || 'none';
231
+ console.log();
232
+ console.log(pc.dim(` Selected: ${selected}`));
233
+ const ok = await p.select({
234
+ message: 'Continue with these packages?',
235
+ options: [
236
+ { value: 'yes', label: '✓ Continue', hint: 'proceed to next step' },
237
+ { value: 'no', label: '← Re-select', hint: 'choose again' },
238
+ ],
239
+ });
240
+ if (p.isCancel(ok)) {
241
+ step = 4;
242
+ continue;
243
+ }
244
+ if (ok === 'no')
245
+ continue; // Re-run step 5
246
+ // If no packages selected, skip trigger selection
247
+ if (skillPackages.length === 0) {
248
+ skillTriggers = [];
249
+ step = 7;
250
+ }
251
+ else {
252
+ step = 6;
253
+ }
254
+ continue;
255
+ }
256
+ if (step === 6) {
257
+ printStepHeader(6, TOTAL_STEPS, STEP_TITLES[6]);
258
+ console.log(pc.dim(' These determine when your colleague automatically invokes skills.'));
259
+ console.log(pc.dim(' All are ON by default — deselect any you don\'t want.'));
260
+ console.log();
261
+ const defaults = skillTriggers.length > 0 ? skillTriggers : ALL_TRIGGER_VALUES;
262
+ const triggersResult = await p.multiselect({
263
+ message: 'Active skill triggers:',
264
+ options: TRIGGER_OPTIONS,
265
+ initialValues: defaults,
266
+ required: false,
267
+ });
268
+ if (p.isCancel(triggersResult)) {
269
+ step = 5;
270
+ continue;
271
+ }
272
+ skillTriggers = triggersResult || [];
273
+ // Confirm
274
+ console.log();
275
+ console.log(pc.dim(` ${skillTriggers.length} of ${ALL_TRIGGER_VALUES.length} triggers active`));
276
+ const ok = await p.select({
277
+ message: 'Continue with these triggers?',
278
+ options: [
279
+ { value: 'yes', label: '✓ Continue', hint: 'proceed to review' },
280
+ { value: 'no', label: '← Re-select', hint: 'choose again' },
281
+ ],
282
+ });
283
+ if (p.isCancel(ok)) {
284
+ step = 5;
285
+ continue;
286
+ }
287
+ if (ok === 'no')
288
+ continue; // Re-run step 6
289
+ step = 7;
290
+ continue;
291
+ }
292
+ if (step === 7) {
293
+ printStepHeader(7, TOTAL_STEPS, STEP_TITLES[7]);
294
+ // Show summary
295
+ console.log(pc.bold(' Review & Confirm'));
296
+ console.log();
297
+ console.log(` Colleague: ${pc.yellow(pc.bold(colleagueName))}`);
298
+ console.log(` User: ${pc.bold(userName)}`);
299
+ console.log(` Project: ${pc.dim(projectDescription)}`);
300
+ console.log(` Focus: ${pc.dim(projectFocus)}`);
301
+ console.log(` Traits: ${pc.dim(traits.map(t => TRAIT_LABELS[t] || t).join(', ') || 'none')}`);
302
+ console.log(` Skills: ${pc.dim(skillPackages.map(s => SKILL_PACKAGE_LABELS[s] || s).join(', ') || 'none')}`);
303
+ console.log(` Active triggers: ${pc.dim(`${skillTriggers.length} of ${ALL_TRIGGER_VALUES.length}`)}`);
304
+ console.log();
305
+ // Repo analysis
306
+ console.log(pc.bold(' Repository'));
307
+ const checks = [
308
+ [analysis.isGitRepo, 'Git repo detected', 'No git repo (will initialize)'],
309
+ [analysis.hasAgentsMd, 'AGENTS.md found', 'No AGENTS.md'],
310
+ [analysis.hasClaudeMd, 'CLAUDE.md found', 'No CLAUDE.md'],
311
+ [analysis.hasCursorRules, '.cursorrules found', 'No .cursorrules'],
312
+ [analysis.hasGitHubRemote, `GitHub remote: ${analysis.gitHubRemoteUrl}`, 'GitHub remote: not configured'],
313
+ [analysis.hasGhCli, 'gh CLI: installed', 'gh CLI: not found'],
314
+ ];
315
+ for (const [found, yes, no] of checks) {
316
+ console.log(` ${found ? pc.green('✓') : pc.dim('✗')} ${found ? yes : pc.dim(no)}`);
317
+ }
318
+ console.log();
319
+ // GitHub setup (only if no remote)
320
+ let repoName = basename(cwd);
321
+ if (!analysis.hasGitHubRemote) {
322
+ if (!analysis.hasGhCli) {
323
+ p.log.warn(`gh CLI not found. Install it with: ${pc.bold('brew install gh')}`);
324
+ p.log.info('Skipping GitHub setup for now.');
325
+ setupGitHub = 'skip';
326
+ }
327
+ else {
328
+ // Check if gh is authenticated
329
+ let ghAuthed = false;
330
+ try {
331
+ execSync('gh auth status', { stdio: 'ignore' });
332
+ ghAuthed = true;
333
+ }
334
+ catch { /* not logged in */ }
335
+ if (!ghAuthed) {
336
+ p.log.warn('GitHub CLI is installed but not logged in.');
337
+ const loginChoice = await p.confirm({
338
+ message: 'Would you like to log in to GitHub now?',
339
+ });
340
+ if (!p.isCancel(loginChoice) && loginChoice) {
341
+ try {
342
+ execSync('gh auth login', { stdio: 'inherit' });
343
+ ghAuthed = true;
344
+ p.log.success('Logged in to GitHub.');
345
+ }
346
+ catch {
347
+ p.log.warn('GitHub login failed. Skipping GitHub setup.');
348
+ }
349
+ }
350
+ }
351
+ if (ghAuthed) {
352
+ const ghChoice = await p.select({
353
+ message: 'Set up a GitHub repository?',
354
+ options: [
355
+ { value: 'create', label: 'Yes, create a new private repo' },
356
+ { value: 'connect', label: 'Yes, connect to an existing repo' },
357
+ { value: 'skip', label: 'Skip for now' },
358
+ ],
359
+ });
360
+ if (p.isCancel(ghChoice)) {
361
+ step = skillPackages.length > 0 ? 6 : 5;
362
+ continue;
363
+ }
364
+ setupGitHub = ghChoice;
365
+ if (setupGitHub === 'create') {
366
+ const nameResult = await p.text({
367
+ message: 'Repository name:',
368
+ placeholder: basename(cwd),
369
+ defaultValue: basename(cwd),
370
+ });
371
+ if (p.isCancel(nameResult)) {
372
+ step = skillPackages.length > 0 ? 6 : 5;
373
+ continue;
374
+ }
375
+ repoName = nameResult || basename(cwd);
376
+ }
377
+ }
378
+ else {
379
+ setupGitHub = 'skip';
380
+ }
381
+ }
382
+ }
383
+ const confirm = await p.select({
384
+ message: 'Ready to install?',
385
+ options: [
386
+ { value: 'confirm', label: 'Install Thufir', hint: 'set up your AI colleague' },
387
+ { value: 'back', label: 'Go back', hint: 'change settings' },
388
+ ],
389
+ });
390
+ if (p.isCancel(confirm) || confirm === 'back') {
391
+ step = skillPackages.length > 0 ? 6 : 5;
392
+ continue;
393
+ }
394
+ step = TOTAL_STEPS + 1; // Exit the loop
395
+ continue;
396
+ }
397
+ }
398
+ return {
399
+ token,
400
+ userName,
401
+ colleagueName,
402
+ projectMode,
403
+ projectDescription,
404
+ projectFocus,
405
+ traits,
406
+ skillPackages,
407
+ skillTriggers,
408
+ setupGitHub,
409
+ repoName,
410
+ };
411
+ }
412
+ export async function runMergePrompts(analysis) {
413
+ printMergeScreen();
414
+ p.log.info('This repo has existing agent files. Thufir will:');
415
+ console.log(pc.dim(' 1. Back up your current agent files'));
416
+ console.log(pc.dim(' 2. Set up Thufir conventions'));
417
+ console.log(pc.dim(' 3. Merge your original intentions into the new structure'));
418
+ console.log(pc.dim(' 4. Run a local agent to reorganize the repo'));
419
+ console.log();
420
+ const proceed = await p.confirm({
421
+ message: 'Would you like to proceed with merge?',
422
+ });
423
+ if (p.isCancel(proceed) || !proceed)
424
+ return null;
425
+ // Then run the normal prompts (token, name, traits, etc.)
426
+ return runPrompts(analysis);
427
+ }
428
+ export async function runRealignPrompts(settings, savedToken) {
429
+ printRealignScreen();
430
+ // Show current config
431
+ const traitLabels = (settings.traits || []).map(t => TRAIT_LABELS[t] || t).join(', ');
432
+ const skillLabels = (settings.skillPackages || []).map(s => SKILL_PACKAGE_LABELS[s] || s).join(', ');
433
+ p.log.info('Found existing Thufir configuration:');
434
+ console.log(` Colleague: ${pc.bold(settings.colleague_name)}`);
435
+ console.log(` User: ${pc.bold(settings.user_name)}`);
436
+ console.log(` Focus: ${pc.bold(settings.project_focus)}`);
437
+ console.log(` Traits: ${pc.bold(traitLabels || 'none')}`);
438
+ console.log(` Skills: ${pc.bold(skillLabels || 'none')}`);
439
+ console.log(` Last aligned: ${pc.bold(settings.last_realigned || settings.initialized)}`);
440
+ console.log();
441
+ // Ask what to do
442
+ const action = await p.select({
443
+ message: 'What would you like to do?',
444
+ options: [
445
+ { value: 'realign', label: 'Realign', hint: 'update to latest Thufir with current settings' },
446
+ { value: 'reconfigure', label: 'Reconfigure', hint: 'change personality traits and settings' },
447
+ { value: 'cancel', label: 'Cancel' },
448
+ ],
449
+ });
450
+ if (p.isCancel(action))
451
+ return null;
452
+ if (action === 'cancel')
453
+ return null;
454
+ // Validate token
455
+ const token = await promptAndValidateToken(savedToken);
456
+ if (!token)
457
+ return null;
458
+ if (action === 'realign') {
459
+ return {
460
+ action: 'realign',
461
+ answers: {
462
+ token,
463
+ userName: settings.user_name,
464
+ colleagueName: settings.colleague_name,
465
+ projectMode: settings.project_mode || 'single',
466
+ projectDescription: settings.project_description || '',
467
+ projectFocus: settings.project_focus || 'hybrid',
468
+ traits: settings.traits || [],
469
+ skillPackages: settings.skillPackages || [],
470
+ skillTriggers: settings.skillTriggers || [],
471
+ setupGitHub: 'skip',
472
+ repoName: '',
473
+ },
474
+ };
475
+ }
476
+ // Reconfigure — step through changeable settings
477
+ printStepHeader(1, 4, 'Reconfigure');
478
+ const colleagueName = await p.text({
479
+ message: 'What should your AI colleague be called?',
480
+ placeholder: settings.colleague_name,
481
+ defaultValue: settings.colleague_name,
482
+ });
483
+ if (p.isCancel(colleagueName))
484
+ return null;
485
+ printStepHeader(2, 4, 'Reconfigure');
486
+ const projectFocus = await p.select({
487
+ message: 'Which best describes the focus?',
488
+ options: [
489
+ { value: 'code', label: 'Mostly code', hint: 'building software, APIs, frontends' },
490
+ { value: 'planning', label: 'Mostly planning', hint: 'business docs, research, strategy' },
491
+ { value: 'hybrid', label: 'Both', hint: 'code AND business/project management' },
492
+ ],
493
+ initialValue: settings.project_focus || 'hybrid',
494
+ });
495
+ if (p.isCancel(projectFocus))
496
+ return null;
497
+ printStepHeader(3, 4, 'Reconfigure');
498
+ const traits = await p.multiselect({
499
+ message: 'Which thinking styles should your colleague use?\n (space = toggle, enter = confirm selection)',
500
+ options: TRAIT_OPTIONS,
501
+ initialValues: settings.traits || ['thufir'],
502
+ required: false,
503
+ });
504
+ if (p.isCancel(traits))
505
+ return null;
506
+ const skillPackages = await p.multiselect({
507
+ message: 'Which skill packages should be available?\n (space = toggle, enter = confirm selection)',
508
+ options: SKILL_PACKAGE_OPTIONS,
509
+ initialValues: settings.skillPackages || [],
510
+ required: false,
511
+ });
512
+ if (p.isCancel(skillPackages))
513
+ return null;
514
+ let skillTriggers = settings.skillTriggers || [];
515
+ if (skillPackages.length > 0) {
516
+ printStepHeader(4, 4, 'Reconfigure');
517
+ const defaults = skillTriggers.length > 0 ? skillTriggers : ALL_TRIGGER_VALUES;
518
+ const triggersResult = await p.multiselect({
519
+ message: 'Which skill triggers should be active?\n (space = toggle, enter = confirm selection)',
520
+ options: TRIGGER_OPTIONS,
521
+ initialValues: defaults,
522
+ required: false,
523
+ });
524
+ if (p.isCancel(triggersResult))
525
+ return null;
526
+ skillTriggers = triggersResult || [];
527
+ }
528
+ else {
529
+ skillTriggers = [];
530
+ }
531
+ return {
532
+ action: 'reconfigure',
533
+ answers: {
534
+ token,
535
+ userName: settings.user_name,
536
+ colleagueName: colleagueName || settings.colleague_name,
537
+ projectMode: settings.project_mode || 'single',
538
+ projectDescription: settings.project_description || '',
539
+ projectFocus: projectFocus,
540
+ traits: traits || [],
541
+ skillPackages: skillPackages || [],
542
+ skillTriggers,
543
+ setupGitHub: 'skip',
544
+ repoName: '',
545
+ },
546
+ };
547
+ }
@@ -0,0 +1,13 @@
1
+ import type { InitAnswers } from './prompts.js';
2
+ export interface ScaffoldResult {
3
+ filesCreated: string[];
4
+ gitInitialized: boolean;
5
+ }
6
+ export declare function scaffold(cwd: string, answers: InitAnswers, analysis: {
7
+ isGitRepo: boolean;
8
+ hasGitHubRemote: boolean;
9
+ }, isRealign?: boolean): ScaffoldResult;
10
+ export declare function backupAgentFiles(cwd: string): string[];
11
+ export declare function generateMergePrompt(cwd: string, answers: InitAnswers, backedUpFiles: string[]): string;
12
+ export declare function createInitialCommit(cwd: string, files: string[], colleagueName: string): void;
13
+ export declare function setupGitHub(cwd: string, mode: 'create' | 'connect', repoName?: string): boolean;