jerad-cli 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 (53) hide show
  1. package/dist/commands/dev.d.ts +3 -0
  2. package/dist/commands/dev.d.ts.map +1 -0
  3. package/dist/commands/dev.js +149 -0
  4. package/dist/commands/dev.js.map +1 -0
  5. package/dist/commands/link.d.ts +3 -0
  6. package/dist/commands/link.d.ts.map +1 -0
  7. package/dist/commands/link.js +49 -0
  8. package/dist/commands/link.js.map +1 -0
  9. package/dist/commands/login.d.ts +3 -0
  10. package/dist/commands/login.d.ts.map +1 -0
  11. package/dist/commands/login.js +35 -0
  12. package/dist/commands/login.js.map +1 -0
  13. package/dist/commands/logout.d.ts +3 -0
  14. package/dist/commands/logout.d.ts.map +1 -0
  15. package/dist/commands/logout.js +31 -0
  16. package/dist/commands/logout.js.map +1 -0
  17. package/dist/commands/next.d.ts +3 -0
  18. package/dist/commands/next.d.ts.map +1 -0
  19. package/dist/commands/next.js +163 -0
  20. package/dist/commands/next.js.map +1 -0
  21. package/dist/commands/status.d.ts +3 -0
  22. package/dist/commands/status.d.ts.map +1 -0
  23. package/dist/commands/status.js +79 -0
  24. package/dist/commands/status.js.map +1 -0
  25. package/dist/commands/whoami.d.ts +3 -0
  26. package/dist/commands/whoami.d.ts.map +1 -0
  27. package/dist/commands/whoami.js +44 -0
  28. package/dist/commands/whoami.js.map +1 -0
  29. package/dist/index.d.ts +3 -0
  30. package/dist/index.d.ts.map +1 -0
  31. package/dist/index.js +26 -0
  32. package/dist/index.js.map +1 -0
  33. package/dist/lib/api.d.ts +49 -0
  34. package/dist/lib/api.d.ts.map +1 -0
  35. package/dist/lib/api.js +83 -0
  36. package/dist/lib/api.js.map +1 -0
  37. package/dist/lib/claude-code.d.ts +11 -0
  38. package/dist/lib/claude-code.d.ts.map +1 -0
  39. package/dist/lib/claude-code.js +67 -0
  40. package/dist/lib/claude-code.js.map +1 -0
  41. package/dist/lib/config.d.ts +26 -0
  42. package/dist/lib/config.d.ts.map +1 -0
  43. package/dist/lib/config.js +87 -0
  44. package/dist/lib/config.js.map +1 -0
  45. package/dist/lib/git.d.ts +10 -0
  46. package/dist/lib/git.d.ts.map +1 -0
  47. package/dist/lib/git.js +77 -0
  48. package/dist/lib/git.js.map +1 -0
  49. package/dist/ui/task-display.d.ts +22 -0
  50. package/dist/ui/task-display.d.ts.map +1 -0
  51. package/dist/ui/task-display.js +177 -0
  52. package/dist/ui/task-display.js.map +1 -0
  53. package/package.json +52 -0
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare const devCommand: Command;
3
+ //# sourceMappingURL=dev.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAqBpC,eAAO,MAAM,UAAU,SA6KnB,CAAC"}
@@ -0,0 +1,149 @@
1
+ import { Command } from 'commander';
2
+ import chalk from 'chalk';
3
+ import inquirer from 'inquirer';
4
+ import { isAuthenticated, isProjectLinked, getProjectConfig } from '../lib/config.js';
5
+ import { getApiClient } from '../lib/api.js';
6
+ import { isGitRepo, createBranch, createStoryBranchName } from '../lib/git.js';
7
+ import { checkClaudeInstalled, runClaudeCodeInteractive } from '../lib/claude-code.js';
8
+ import { displayHeader, displayTaskCard, displayError, displayWarning, displayBranchCreated, displayStartingClaude, displayClaudeComplete, displaySuccess, } from '../ui/task-display.js';
9
+ const POLL_INTERVAL = 5000; // 5 seconds
10
+ export const devCommand = new Command('dev')
11
+ .description('Start dev mode - watch for in-progress tasks and run Claude Code')
12
+ .option('-n, --no-git', 'Skip git branch creation')
13
+ .option('-p, --poll <seconds>', 'Poll interval in seconds', '5')
14
+ .action(async (options) => {
15
+ // Validate environment
16
+ if (!isAuthenticated()) {
17
+ displayError('Not logged in. Run: jerad login <token>');
18
+ process.exit(1);
19
+ }
20
+ if (!isProjectLinked()) {
21
+ displayError('No project linked. Run: jerad link <project-id>');
22
+ process.exit(1);
23
+ }
24
+ // Check Claude Code installation
25
+ const claudeInstalled = await checkClaudeInstalled();
26
+ if (!claudeInstalled) {
27
+ displayError('Claude Code is not installed.');
28
+ console.log(chalk.gray('Install it with: npm install -g @anthropic-ai/claude-code'));
29
+ process.exit(1);
30
+ }
31
+ // Check git repo if git is enabled
32
+ if (options.git !== false) {
33
+ const isGit = await isGitRepo();
34
+ if (!isGit) {
35
+ displayWarning('Not in a git repository. Git features will be disabled.');
36
+ options.git = false;
37
+ }
38
+ }
39
+ const projectConfig = getProjectConfig();
40
+ const pollInterval = (parseInt(options.poll || '5', 10) || 5) * 1000;
41
+ // Display header
42
+ displayHeader(projectConfig.projectName);
43
+ const api = getApiClient();
44
+ let lastProcessedStoryId = null;
45
+ let isProcessing = false; // Prevent concurrent prompts
46
+ // Main polling loop
47
+ const poll = async () => {
48
+ // Skip if we're already processing a task
49
+ if (isProcessing) {
50
+ return;
51
+ }
52
+ try {
53
+ const inProgressStories = await api.getInProgressStories(projectConfig.projectId);
54
+ if (inProgressStories.length > 0) {
55
+ const story = inProgressStories[0];
56
+ // Skip if we already processed this story
57
+ if (story._id === lastProcessedStoryId) {
58
+ return;
59
+ }
60
+ // Mark as processing to prevent duplicate prompts
61
+ isProcessing = true;
62
+ // Get full story with prompt
63
+ const fullStory = await api.getStory(projectConfig.projectId, story._id);
64
+ // Display task card
65
+ displayTaskCard(fullStory);
66
+ // Ask user if they want to start
67
+ const { confirm } = await inquirer.prompt([
68
+ {
69
+ type: 'confirm',
70
+ name: 'confirm',
71
+ message: 'Start this task?',
72
+ default: true,
73
+ },
74
+ ]);
75
+ // Mark as processed immediately to prevent re-prompting
76
+ lastProcessedStoryId = story._id;
77
+ if (confirm) {
78
+ // Create git branch if enabled
79
+ if (options.git !== false) {
80
+ const branchName = createStoryBranchName(story._id, story.title);
81
+ displayBranchCreated(branchName);
82
+ try {
83
+ await createBranch(branchName);
84
+ // Update story with branch name
85
+ await api.updateStoryStatus(projectConfig.projectId, story._id, 'in_progress', branchName);
86
+ }
87
+ catch (error) {
88
+ displayWarning(`Could not create branch: ${error instanceof Error ? error.message : 'Unknown error'}`);
89
+ }
90
+ }
91
+ // Start Claude Code
92
+ displayStartingClaude();
93
+ try {
94
+ await runClaudeCodeInteractive(fullStory.prompt);
95
+ displayClaudeComplete();
96
+ // Ask if task is complete
97
+ const { taskComplete } = await inquirer.prompt([
98
+ {
99
+ type: 'confirm',
100
+ name: 'taskComplete',
101
+ message: 'Mark task as complete and move to Review?',
102
+ default: false,
103
+ },
104
+ ]);
105
+ if (taskComplete) {
106
+ await api.updateStoryStatus(projectConfig.projectId, story._id, 'review');
107
+ displaySuccess('Task moved to Review');
108
+ // Clear processed ID so we can pick up next task
109
+ lastProcessedStoryId = null;
110
+ }
111
+ }
112
+ catch (error) {
113
+ displayError(`Claude Code error: ${error instanceof Error ? error.message : 'Unknown error'}`);
114
+ }
115
+ // Re-display header
116
+ console.log();
117
+ displayHeader(projectConfig.projectName);
118
+ }
119
+ else {
120
+ // User declined
121
+ console.log(chalk.gray('\nWaiting for task status change...\n'));
122
+ }
123
+ // Done processing
124
+ isProcessing = false;
125
+ }
126
+ }
127
+ catch (error) {
128
+ // Reset processing flag on error
129
+ isProcessing = false;
130
+ // Silently handle polling errors to avoid spamming the console
131
+ if (process.env.DEBUG) {
132
+ console.error('Polling error:', error);
133
+ }
134
+ }
135
+ };
136
+ // Initial poll
137
+ await poll();
138
+ // Set up polling interval
139
+ const intervalId = setInterval(poll, pollInterval);
140
+ // Handle graceful shutdown
141
+ process.on('SIGINT', () => {
142
+ clearInterval(intervalId);
143
+ console.log(chalk.gray('\n\nExiting dev mode...'));
144
+ process.exit(0);
145
+ });
146
+ // Keep the process running
147
+ console.log(chalk.gray(`Polling every ${pollInterval / 1000} seconds. Press Ctrl+C to exit.\n`));
148
+ });
149
+ //# sourceMappingURL=dev.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev.js","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare const linkCommand: Command;
3
+ //# sourceMappingURL=link.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"link.d.ts","sourceRoot":"","sources":["../../src/commands/link.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,eAAO,MAAM,WAAW,SA8CpB,CAAC"}
@@ -0,0 +1,49 @@
1
+ import { Command } from 'commander';
2
+ import ora from 'ora';
3
+ import { isAuthenticated, setProjectConfig, isProjectLinked, getProjectConfig } from '../lib/config.js';
4
+ import { getApiClient } from '../lib/api.js';
5
+ import { displaySuccess, displayError, displayWarning, displayInfo } from '../ui/task-display.js';
6
+ export const linkCommand = new Command('link')
7
+ .description('Link current directory to a Jerad project')
8
+ .argument('<project>', 'Project ID or slug')
9
+ .option('-f, --force', 'Overwrite existing link')
10
+ .action(async (projectIdOrSlug, options) => {
11
+ if (!isAuthenticated()) {
12
+ displayError('Not logged in. Run: jerad login <token>');
13
+ process.exit(1);
14
+ }
15
+ // Check if already linked
16
+ if (isProjectLinked() && !options.force) {
17
+ const existing = getProjectConfig();
18
+ displayWarning(`Already linked to project: ${existing?.projectName}`);
19
+ displayInfo('Use --force to overwrite');
20
+ process.exit(1);
21
+ }
22
+ const spinner = ora('Linking project...').start();
23
+ try {
24
+ const api = getApiClient();
25
+ // Try to fetch by slug first, then by ID
26
+ let project;
27
+ try {
28
+ project = await api.getProjectBySlug(projectIdOrSlug);
29
+ }
30
+ catch {
31
+ project = await api.getProject(projectIdOrSlug);
32
+ }
33
+ // Save project config
34
+ setProjectConfig({
35
+ projectId: project._id,
36
+ projectName: project.name,
37
+ projectSlug: project.slug,
38
+ linkedAt: new Date().toISOString(),
39
+ });
40
+ spinner.stop();
41
+ displaySuccess(`Linked to project: ${project.name}`);
42
+ }
43
+ catch (error) {
44
+ spinner.stop();
45
+ displayError(error instanceof Error ? error.message : 'Failed to link project');
46
+ process.exit(1);
47
+ }
48
+ });
49
+ //# sourceMappingURL=link.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"link.js","sourceRoot":"","sources":["../../src/commands/link.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACxG,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAElG,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC;KAC3C,WAAW,CAAC,2CAA2C,CAAC;KACxD,QAAQ,CAAC,WAAW,EAAE,oBAAoB,CAAC;KAC3C,MAAM,CAAC,aAAa,EAAE,yBAAyB,CAAC;KAChD,MAAM,CAAC,KAAK,EAAE,eAAuB,EAAE,OAA4B,EAAE,EAAE;IACtE,IAAI,CAAC,eAAe,EAAE,EAAE,CAAC;QACvB,YAAY,CAAC,yCAAyC,CAAC,CAAC;QACxD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,0BAA0B;IAC1B,IAAI,eAAe,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACxC,MAAM,QAAQ,GAAG,gBAAgB,EAAE,CAAC;QACpC,cAAc,CAAC,8BAA8B,QAAQ,EAAE,WAAW,EAAE,CAAC,CAAC;QACtE,WAAW,CAAC,0BAA0B,CAAC,CAAC;QACxC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,OAAO,GAAG,GAAG,CAAC,oBAAoB,CAAC,CAAC,KAAK,EAAE,CAAC;IAElD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAY,EAAE,CAAC;QAE3B,yCAAyC;QACzC,IAAI,OAAO,CAAC;QACZ,IAAI,CAAC;YACH,OAAO,GAAG,MAAM,GAAG,CAAC,gBAAgB,CAAC,eAAe,CAAC,CAAC;QACxD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,GAAG,MAAM,GAAG,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC;QAClD,CAAC;QAED,sBAAsB;QACtB,gBAAgB,CAAC;YACf,SAAS,EAAE,OAAO,CAAC,GAAG;YACtB,WAAW,EAAE,OAAO,CAAC,IAAI;YACzB,WAAW,EAAE,OAAO,CAAC,IAAI;YACzB,QAAQ,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACnC,CAAC,CAAC;QAEH,OAAO,CAAC,IAAI,EAAE,CAAC;QACf,cAAc,CAAC,sBAAsB,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IACvD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,IAAI,EAAE,CAAC;QACf,YAAY,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAC;QAChF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare const loginCommand: Command;
3
+ //# sourceMappingURL=login.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,eAAO,MAAM,YAAY,SA+BrB,CAAC"}
@@ -0,0 +1,35 @@
1
+ import { Command } from 'commander';
2
+ import ora from 'ora';
3
+ import { setToken, setUser } from '../lib/config.js';
4
+ import { getApiClient, resetApiClient } from '../lib/api.js';
5
+ import { displaySuccess, displayError } from '../ui/task-display.js';
6
+ export const loginCommand = new Command('login')
7
+ .description('Authenticate with Jerad using your CLI token')
8
+ .argument('<token>', 'Your CLI token from Jerad settings')
9
+ .action(async (token) => {
10
+ const spinner = ora('Validating token...').start();
11
+ try {
12
+ // Set the token first so API client can use it
13
+ setToken(token);
14
+ resetApiClient();
15
+ // Validate the token
16
+ const api = getApiClient();
17
+ const user = await api.validateToken();
18
+ // Save user info
19
+ setUser({
20
+ id: user.id,
21
+ email: user.email,
22
+ name: user.name,
23
+ });
24
+ spinner.stop();
25
+ displaySuccess(`Logged in as ${user.email}`);
26
+ }
27
+ catch (error) {
28
+ spinner.stop();
29
+ // Clear invalid token
30
+ setToken('');
31
+ displayError(error instanceof Error ? error.message : 'Login failed');
32
+ process.exit(1);
33
+ }
34
+ });
35
+ //# sourceMappingURL=login.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAErE,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC;KAC7C,WAAW,CAAC,8CAA8C,CAAC;KAC3D,QAAQ,CAAC,SAAS,EAAE,oCAAoC,CAAC;KACzD,MAAM,CAAC,KAAK,EAAE,KAAa,EAAE,EAAE;IAC9B,MAAM,OAAO,GAAG,GAAG,CAAC,qBAAqB,CAAC,CAAC,KAAK,EAAE,CAAC;IAEnD,IAAI,CAAC;QACH,+CAA+C;QAC/C,QAAQ,CAAC,KAAK,CAAC,CAAC;QAChB,cAAc,EAAE,CAAC;QAEjB,qBAAqB;QACrB,MAAM,GAAG,GAAG,YAAY,EAAE,CAAC;QAC3B,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,aAAa,EAAE,CAAC;QAEvC,iBAAiB;QACjB,OAAO,CAAC;YACN,EAAE,EAAE,IAAI,CAAC,EAAE;YACX,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,IAAI,EAAE,IAAI,CAAC,IAAI;SAChB,CAAC,CAAC;QAEH,OAAO,CAAC,IAAI,EAAE,CAAC;QACf,cAAc,CAAC,gBAAgB,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;IAC/C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,IAAI,EAAE,CAAC;QACf,sBAAsB;QACtB,QAAQ,CAAC,EAAE,CAAC,CAAC;QACb,YAAY,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC;QACtE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare const logoutCommand: Command;
3
+ //# sourceMappingURL=logout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logout.d.ts","sourceRoot":"","sources":["../../src/commands/logout.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,eAAO,MAAM,aAAa,SA6BtB,CAAC"}
@@ -0,0 +1,31 @@
1
+ import { Command } from 'commander';
2
+ import inquirer from 'inquirer';
3
+ import { clearToken, isAuthenticated, getUser } from '../lib/config.js';
4
+ import { displaySuccess, displayWarning } from '../ui/task-display.js';
5
+ export const logoutCommand = new Command('logout')
6
+ .description('Log out and clear stored credentials')
7
+ .option('-f, --force', 'Skip confirmation prompt')
8
+ .action(async (options) => {
9
+ if (!isAuthenticated()) {
10
+ displayWarning('Not currently logged in');
11
+ return;
12
+ }
13
+ const user = getUser();
14
+ if (!options.force) {
15
+ const { confirm } = await inquirer.prompt([
16
+ {
17
+ type: 'confirm',
18
+ name: 'confirm',
19
+ message: `Log out ${user?.email || 'current user'}?`,
20
+ default: false,
21
+ },
22
+ ]);
23
+ if (!confirm) {
24
+ console.log('Cancelled');
25
+ return;
26
+ }
27
+ }
28
+ clearToken();
29
+ displaySuccess('Logged out successfully');
30
+ });
31
+ //# sourceMappingURL=logout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logout.js","sourceRoot":"","sources":["../../src/commands/logout.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,QAAQ,MAAM,UAAU,CAAC;AAChC,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AACxE,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvE,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC;KAC/C,WAAW,CAAC,sCAAsC,CAAC;KACnD,MAAM,CAAC,aAAa,EAAE,0BAA0B,CAAC;KACjD,MAAM,CAAC,KAAK,EAAE,OAA4B,EAAE,EAAE;IAC7C,IAAI,CAAC,eAAe,EAAE,EAAE,CAAC;QACvB,cAAc,CAAC,yBAAyB,CAAC,CAAC;QAC1C,OAAO;IACT,CAAC;IAED,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IAEvB,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACnB,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC;YACxC;gBACE,IAAI,EAAE,SAAS;gBACf,IAAI,EAAE,SAAS;gBACf,OAAO,EAAE,WAAW,IAAI,EAAE,KAAK,IAAI,cAAc,GAAG;gBACpD,OAAO,EAAE,KAAK;aACf;SACF,CAAC,CAAC;QAEH,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;YACzB,OAAO;QACT,CAAC;IACH,CAAC;IAED,UAAU,EAAE,CAAC;IACb,cAAc,CAAC,yBAAyB,CAAC,CAAC;AAC5C,CAAC,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare const nextCommand: Command;
3
+ //# sourceMappingURL=next.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"next.d.ts","sourceRoot":"","sources":["../../src/commands/next.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAmBpC,eAAO,MAAM,WAAW,SA8GpB,CAAC"}
@@ -0,0 +1,163 @@
1
+ import { Command } from 'commander';
2
+ import chalk from 'chalk';
3
+ import inquirer from 'inquirer';
4
+ import ora from 'ora';
5
+ import { isAuthenticated, isProjectLinked, getProjectConfig } from '../lib/config.js';
6
+ import { getApiClient } from '../lib/api.js';
7
+ import { isGitRepo, createBranch, createStoryBranchName } from '../lib/git.js';
8
+ import { checkClaudeInstalled, runClaudeCodeInteractive } from '../lib/claude-code.js';
9
+ import { displayTaskCard, displayError, displayWarning, displayInfo, displayBranchCreated, displayStartingClaude, displayClaudeComplete, displaySuccess, } from '../ui/task-display.js';
10
+ export const nextCommand = new Command('next')
11
+ .description('Pick up the next To Do story and start working on it')
12
+ .option('-n, --no-git', 'Skip git branch creation')
13
+ .option('--no-claude', 'Skip starting Claude Code (just move status)')
14
+ .action(async (options) => {
15
+ // Validate environment
16
+ if (!isAuthenticated()) {
17
+ displayError('Not logged in. Run: jerad login <token>');
18
+ process.exit(1);
19
+ }
20
+ if (!isProjectLinked()) {
21
+ displayError('No project linked. Run: jerad link <project-id>');
22
+ process.exit(1);
23
+ }
24
+ const projectConfig = getProjectConfig();
25
+ const api = getApiClient();
26
+ // Check for existing in-progress stories
27
+ const spinner = ora('Checking for tasks...').start();
28
+ try {
29
+ const inProgressStories = await api.getInProgressStories(projectConfig.projectId);
30
+ if (inProgressStories.length > 0) {
31
+ spinner.stop();
32
+ displayWarning('You already have a task in progress:');
33
+ console.log(chalk.yellow(` • ${inProgressStories[0].title}`));
34
+ console.log();
35
+ const { continueExisting } = await inquirer.prompt([
36
+ {
37
+ type: 'confirm',
38
+ name: 'continueExisting',
39
+ message: 'Continue with existing task?',
40
+ default: true,
41
+ },
42
+ ]);
43
+ if (continueExisting) {
44
+ const story = inProgressStories[0];
45
+ const fullStory = await api.getStory(projectConfig.projectId, story._id);
46
+ await startTask(fullStory, options, projectConfig, api);
47
+ return;
48
+ }
49
+ const { startNew } = await inquirer.prompt([
50
+ {
51
+ type: 'confirm',
52
+ name: 'startNew',
53
+ message: 'Move existing task back to To Do and start a new one?',
54
+ default: false,
55
+ },
56
+ ]);
57
+ if (!startNew) {
58
+ console.log(chalk.gray('Cancelled'));
59
+ return;
60
+ }
61
+ // Move existing task back to todo
62
+ await api.updateStoryStatus(projectConfig.projectId, inProgressStories[0]._id, 'todo');
63
+ displayInfo(`Moved "${inProgressStories[0].title}" back to To Do`);
64
+ }
65
+ else {
66
+ spinner.stop();
67
+ }
68
+ // Get next todo story
69
+ const nextSpinner = ora('Fetching next task...').start();
70
+ const nextStory = await api.getNextTodoStory(projectConfig.projectId);
71
+ if (!nextStory) {
72
+ nextSpinner.stop();
73
+ displayInfo('No tasks in To Do. All caught up! 🎉');
74
+ return;
75
+ }
76
+ nextSpinner.stop();
77
+ // Get full story with prompt
78
+ const fullStory = await api.getStory(projectConfig.projectId, nextStory._id);
79
+ // Display task card
80
+ displayTaskCard(fullStory);
81
+ // Confirm starting the task
82
+ const { confirm } = await inquirer.prompt([
83
+ {
84
+ type: 'confirm',
85
+ name: 'confirm',
86
+ message: 'Start this task?',
87
+ default: true,
88
+ },
89
+ ]);
90
+ if (!confirm) {
91
+ console.log(chalk.gray('Cancelled'));
92
+ return;
93
+ }
94
+ // Move to in_progress
95
+ await api.updateStoryStatus(projectConfig.projectId, nextStory._id, 'in_progress');
96
+ await startTask(fullStory, options, projectConfig, api);
97
+ }
98
+ catch (error) {
99
+ spinner.stop();
100
+ displayError(error instanceof Error ? error.message : 'Failed to fetch tasks');
101
+ process.exit(1);
102
+ }
103
+ });
104
+ async function startTask(story, options, projectConfig, api) {
105
+ // Check git repo if git is enabled
106
+ let useGit = options.git !== false;
107
+ if (useGit) {
108
+ const isGit = await isGitRepo();
109
+ if (!isGit) {
110
+ displayWarning('Not in a git repository. Skipping branch creation.');
111
+ useGit = false;
112
+ }
113
+ }
114
+ // Create git branch if enabled
115
+ if (useGit) {
116
+ const branchName = createStoryBranchName(story._id, story.title);
117
+ displayBranchCreated(branchName);
118
+ try {
119
+ await createBranch(branchName);
120
+ // Update story with branch name
121
+ await api.updateStoryStatus(projectConfig.projectId, story._id, 'in_progress', branchName);
122
+ }
123
+ catch (error) {
124
+ displayWarning(`Could not create branch: ${error instanceof Error ? error.message : 'Unknown error'}`);
125
+ }
126
+ }
127
+ // Start Claude Code if enabled
128
+ if (options.claude !== false) {
129
+ const claudeInstalled = await checkClaudeInstalled();
130
+ if (!claudeInstalled) {
131
+ displayError('Claude Code is not installed.');
132
+ console.log(chalk.gray('Install it with: npm install -g @anthropic-ai/claude-code'));
133
+ console.log(chalk.gray('Or run with --no-claude to skip'));
134
+ return;
135
+ }
136
+ displayStartingClaude();
137
+ try {
138
+ await runClaudeCodeInteractive(story.prompt);
139
+ displayClaudeComplete();
140
+ // Ask if task is complete
141
+ const { taskComplete } = await inquirer.prompt([
142
+ {
143
+ type: 'confirm',
144
+ name: 'taskComplete',
145
+ message: 'Mark task as complete and move to Review?',
146
+ default: false,
147
+ },
148
+ ]);
149
+ if (taskComplete) {
150
+ await api.updateStoryStatus(projectConfig.projectId, story._id, 'review');
151
+ displaySuccess('Task moved to Review');
152
+ }
153
+ }
154
+ catch (error) {
155
+ displayError(`Claude Code error: ${error instanceof Error ? error.message : 'Unknown error'}`);
156
+ }
157
+ }
158
+ else {
159
+ displaySuccess('Task moved to In Progress');
160
+ console.log(chalk.gray('\nRun Claude Code manually with the task prompt, then update status in Jerad.'));
161
+ }
162
+ }
163
+ //# sourceMappingURL=next.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"next.js","sourceRoot":"","sources":["../../src/commands/next.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare const statusCommand: Command;
3
+ //# sourceMappingURL=status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOpC,eAAO,MAAM,aAAa,SA+EtB,CAAC"}
@@ -0,0 +1,79 @@
1
+ import { Command } from 'commander';
2
+ import chalk from 'chalk';
3
+ import ora from 'ora';
4
+ import { isAuthenticated, isProjectLinked, getProjectConfig, getUser } from '../lib/config.js';
5
+ import { getApiClient } from '../lib/api.js';
6
+ import { displayError, displayWarning } from '../ui/task-display.js';
7
+ export const statusCommand = new Command('status')
8
+ .description('Show current project status and pending tasks')
9
+ .action(async () => {
10
+ // Check auth
11
+ if (!isAuthenticated()) {
12
+ displayWarning('Not logged in. Run: jerad login <token>');
13
+ process.exit(1);
14
+ }
15
+ // Check project link
16
+ if (!isProjectLinked()) {
17
+ displayWarning('No project linked. Run: jerad link <project-id>');
18
+ process.exit(1);
19
+ }
20
+ const projectConfig = getProjectConfig();
21
+ const user = getUser();
22
+ const spinner = ora('Fetching project status...').start();
23
+ try {
24
+ const api = getApiClient();
25
+ const stories = await api.getStories(projectConfig.projectId);
26
+ // Calculate stats
27
+ const stats = {
28
+ total: stories.length,
29
+ backlog: stories.filter((s) => s.status === 'backlog').length,
30
+ todo: stories.filter((s) => s.status === 'todo').length,
31
+ inProgress: stories.filter((s) => s.status === 'in_progress').length,
32
+ review: stories.filter((s) => s.status === 'review').length,
33
+ done: stories.filter((s) => s.status === 'done').length,
34
+ };
35
+ spinner.stop();
36
+ // Display status
37
+ console.log();
38
+ console.log(chalk.bold.cyan('📊 Project Status'));
39
+ console.log(chalk.gray('─'.repeat(40)));
40
+ console.log();
41
+ console.log(` ${chalk.bold('Project:')} ${chalk.white(projectConfig.projectName)}`);
42
+ console.log(` ${chalk.bold('User:')} ${chalk.white(user?.email || 'Unknown')}`);
43
+ console.log();
44
+ console.log(chalk.bold(' Stories:'));
45
+ console.log(` ${chalk.gray('Backlog:')} ${chalk.white(stats.backlog)}`);
46
+ console.log(` ${chalk.blue('To Do:')} ${chalk.white(stats.todo)}`);
47
+ console.log(` ${chalk.yellow('In Progress:')} ${chalk.white(stats.inProgress)}`);
48
+ console.log(` ${chalk.magenta('Review:')} ${chalk.white(stats.review)}`);
49
+ console.log(` ${chalk.green('Done:')} ${chalk.white(stats.done)}`);
50
+ console.log(` ${chalk.bold('Total:')} ${chalk.white(stats.total)}`);
51
+ console.log();
52
+ // Show in-progress tasks
53
+ if (stats.inProgress > 0) {
54
+ const inProgressStories = stories.filter((s) => s.status === 'in_progress');
55
+ console.log(chalk.bold.yellow('📌 In Progress:'));
56
+ for (const story of inProgressStories) {
57
+ console.log(` • ${story.title} ${chalk.gray(`(${story.storyPoints} pts)`)}`);
58
+ }
59
+ console.log();
60
+ }
61
+ // Show next todo
62
+ if (stats.todo > 0) {
63
+ const nextTodo = stories.find((s) => s.status === 'todo');
64
+ if (nextTodo) {
65
+ console.log(chalk.bold.blue('⏭️ Next up:'));
66
+ console.log(` ${nextTodo.title} ${chalk.gray(`(${nextTodo.storyPoints} pts)`)}`);
67
+ console.log();
68
+ console.log(chalk.gray(' Run `jerad next` to start this task'));
69
+ console.log();
70
+ }
71
+ }
72
+ }
73
+ catch (error) {
74
+ spinner.stop();
75
+ displayError(error instanceof Error ? error.message : 'Failed to fetch status');
76
+ process.exit(1);
77
+ }
78
+ });
79
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare const whoamiCommand: Command;
3
+ //# sourceMappingURL=whoami.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"whoami.d.ts","sourceRoot":"","sources":["../../src/commands/whoami.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOpC,eAAO,MAAM,aAAa,SAsCtB,CAAC"}