@proletariat/cli 0.3.34 → 0.3.36

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 (198) hide show
  1. package/dist/commands/agent/auth.d.ts +15 -3
  2. package/dist/commands/agent/auth.js +136 -15
  3. package/dist/commands/agent/index.js +11 -2
  4. package/dist/commands/agent/list.js +16 -7
  5. package/dist/commands/agent/staff/add.d.ts +1 -0
  6. package/dist/commands/agent/staff/add.js +1 -0
  7. package/dist/commands/agent/staff/index.d.ts +15 -0
  8. package/dist/commands/agent/staff/index.js +83 -0
  9. package/dist/commands/agent/staff/list.d.ts +1 -0
  10. package/dist/commands/agent/staff/list.js +1 -0
  11. package/dist/commands/agent/staff/remove.d.ts +1 -0
  12. package/dist/commands/agent/staff/remove.js +1 -0
  13. package/dist/commands/agent/status.js +32 -4
  14. package/dist/commands/agent/themes/add-names.d.ts +1 -0
  15. package/dist/commands/agent/themes/add-names.js +1 -0
  16. package/dist/commands/agent/themes/create.d.ts +1 -0
  17. package/dist/commands/agent/themes/create.js +1 -0
  18. package/dist/commands/agent/themes/index.d.ts +10 -0
  19. package/dist/commands/agent/themes/index.js +144 -0
  20. package/dist/commands/agent/themes/list.d.ts +1 -0
  21. package/dist/commands/agent/themes/list.js +1 -0
  22. package/dist/commands/agent/themes/set.d.ts +1 -0
  23. package/dist/commands/agent/themes/set.js +1 -0
  24. package/dist/commands/agents/themes/add-names.d.ts +1 -0
  25. package/dist/commands/agents/themes/add-names.js +1 -0
  26. package/dist/commands/agents/themes/create.d.ts +1 -0
  27. package/dist/commands/agents/themes/create.js +1 -0
  28. package/dist/commands/agents/themes/list.d.ts +1 -0
  29. package/dist/commands/agents/themes/list.js +1 -0
  30. package/dist/commands/board/watch.js +6 -0
  31. package/dist/commands/branch/list.d.ts +1 -0
  32. package/dist/commands/branch/list.js +43 -12
  33. package/dist/commands/branch/where.js +3 -2
  34. package/dist/commands/category/list.d.ts +2 -1
  35. package/dist/commands/category/list.js +38 -13
  36. package/dist/commands/{claude.d.ts → claude/index.d.ts} +1 -1
  37. package/dist/commands/{claude.js → claude/index.js} +12 -12
  38. package/dist/commands/claude/open.d.ts +13 -0
  39. package/dist/commands/claude/open.js +175 -0
  40. package/dist/commands/diet.js +18 -2
  41. package/dist/commands/docker/logs.js +7 -3
  42. package/dist/commands/docker/shell.js +6 -0
  43. package/dist/commands/docker/start.js +20 -4
  44. package/dist/commands/docker/sync.d.ts +4 -0
  45. package/dist/commands/docker/sync.js +30 -2
  46. package/dist/commands/epic/show.d.ts +13 -0
  47. package/dist/commands/epic/show.js +16 -0
  48. package/dist/commands/epic/view.js +27 -0
  49. package/dist/commands/execution/config.d.ts +0 -4
  50. package/dist/commands/execution/config.js +10 -32
  51. package/dist/commands/execution/index.js +2 -1
  52. package/dist/commands/execution/logs.js +1 -1
  53. package/dist/commands/execution/stop.js +2 -1
  54. package/dist/commands/execution/view.js +22 -26
  55. package/dist/commands/init.js +2 -19
  56. package/dist/commands/label/create.d.ts +20 -0
  57. package/dist/commands/label/create.js +57 -0
  58. package/dist/commands/label/delete.d.ts +17 -0
  59. package/dist/commands/label/delete.js +32 -0
  60. package/dist/commands/label/group/create.d.ts +20 -0
  61. package/dist/commands/label/group/create.js +55 -0
  62. package/dist/commands/label/group/list.d.ts +14 -0
  63. package/dist/commands/label/group/list.js +52 -0
  64. package/dist/commands/label/index.d.ts +15 -0
  65. package/dist/commands/label/index.js +58 -0
  66. package/dist/commands/label/list.d.ts +16 -0
  67. package/dist/commands/label/list.js +83 -0
  68. package/dist/commands/link/list.js +3 -2
  69. package/dist/commands/mcp-server.js +27 -1
  70. package/dist/commands/phase/template/apply.d.ts +26 -0
  71. package/dist/commands/phase/template/apply.js +14 -0
  72. package/dist/commands/phase/template/create.d.ts +23 -0
  73. package/dist/commands/phase/template/create.js +14 -0
  74. package/dist/commands/phase/template/delete.d.ts +18 -0
  75. package/dist/commands/phase/template/delete.js +61 -0
  76. package/dist/commands/phase/template/list.d.ts +17 -0
  77. package/dist/commands/phase/template/list.js +89 -0
  78. package/dist/commands/phase/template/update.d.ts +1 -0
  79. package/dist/commands/phase/template/update.js +1 -0
  80. package/dist/commands/priority/add.js +1 -1
  81. package/dist/commands/project/create.js +3 -4
  82. package/dist/commands/project/update.js +5 -8
  83. package/dist/commands/pull.js +24 -0
  84. package/dist/commands/roadmap/generate.js +1 -2
  85. package/dist/commands/session/create.d.ts +19 -0
  86. package/dist/commands/session/create.js +102 -0
  87. package/dist/commands/session/health.js +2 -21
  88. package/dist/commands/session/index.js +14 -1
  89. package/dist/commands/session/list.js +26 -7
  90. package/dist/commands/session/peek.d.ts +38 -0
  91. package/dist/commands/session/peek.js +316 -0
  92. package/dist/commands/session/poke.d.ts +27 -0
  93. package/dist/commands/session/poke.js +219 -0
  94. package/dist/commands/spec/link/depends.d.ts +18 -0
  95. package/dist/commands/spec/link/depends.js +86 -0
  96. package/dist/commands/spec/link/index.d.ts +17 -0
  97. package/dist/commands/spec/link/index.js +92 -0
  98. package/dist/commands/spec/link/remove.d.ts +18 -0
  99. package/dist/commands/spec/link/remove.js +90 -0
  100. package/dist/commands/spec/view.js +29 -0
  101. package/dist/commands/support/logs.js +2 -2
  102. package/dist/commands/template/apply.js +5 -4
  103. package/dist/commands/template/create.js +1 -1
  104. package/dist/commands/template/list.js +2 -1
  105. package/dist/commands/theme/add-names.d.ts +4 -0
  106. package/dist/commands/theme/add-names.js +11 -1
  107. package/dist/commands/theme/create.d.ts +2 -0
  108. package/dist/commands/theme/create.js +8 -0
  109. package/dist/commands/ticket/bulk.js +2 -2
  110. package/dist/commands/ticket/complete.js +2 -2
  111. package/dist/commands/ticket/create.js +21 -0
  112. package/dist/commands/ticket/delete.js +8 -0
  113. package/dist/commands/ticket/edit.js +25 -0
  114. package/dist/commands/ticket/index.js +2 -2
  115. package/dist/commands/ticket/link/block.d.ts +15 -0
  116. package/dist/commands/ticket/link/block.js +95 -0
  117. package/dist/commands/ticket/link/index.d.ts +14 -0
  118. package/dist/commands/ticket/link/index.js +96 -0
  119. package/dist/commands/ticket/list.d.ts +1 -0
  120. package/dist/commands/ticket/list.js +6 -0
  121. package/dist/commands/ticket/move.js +25 -2
  122. package/dist/commands/ticket/resolve.js +4 -5
  123. package/dist/commands/ticket/show.d.ts +13 -0
  124. package/dist/commands/ticket/show.js +16 -0
  125. package/dist/commands/ticket/template/apply.d.ts +26 -0
  126. package/dist/commands/ticket/template/apply.js +14 -0
  127. package/dist/commands/ticket/template/delete.d.ts +18 -0
  128. package/dist/commands/ticket/template/delete.js +61 -0
  129. package/dist/commands/ticket/template/list.d.ts +17 -0
  130. package/dist/commands/ticket/template/list.js +78 -0
  131. package/dist/commands/ticket/template/save.d.ts +17 -0
  132. package/dist/commands/ticket/template/save.js +97 -0
  133. package/dist/commands/ticket/view.js +30 -0
  134. package/dist/commands/work/index.js +4 -0
  135. package/dist/commands/work/ready.js +17 -0
  136. package/dist/commands/work/resolve.js +1 -1
  137. package/dist/commands/work/spawn.js +4 -4
  138. package/dist/commands/work/start.d.ts +1 -0
  139. package/dist/commands/work/start.js +203 -93
  140. package/dist/commands/work/status.d.ts +14 -0
  141. package/dist/commands/work/status.js +60 -0
  142. package/dist/commands/workflow/index.js +2 -1
  143. package/dist/commands/workflow/show.d.ts +13 -0
  144. package/dist/commands/workflow/show.js +16 -0
  145. package/dist/commands/workspace/add.js +15 -0
  146. package/dist/commands/workspace/list.js +2 -1
  147. package/dist/commands/workspace/prune.js +5 -5
  148. package/dist/lib/branch/index.d.ts +1 -0
  149. package/dist/lib/database/index.d.ts +1 -1
  150. package/dist/lib/database/index.js +20 -0
  151. package/dist/lib/execution/config.d.ts +15 -1
  152. package/dist/lib/execution/config.js +28 -0
  153. package/dist/lib/execution/devcontainer.js +3 -1
  154. package/dist/lib/execution/runners.d.ts +18 -2
  155. package/dist/lib/execution/runners.js +71 -29
  156. package/dist/lib/execution/session-utils.d.ts +11 -1
  157. package/dist/lib/execution/session-utils.js +26 -1
  158. package/dist/lib/execution/storage.d.ts +5 -0
  159. package/dist/lib/execution/storage.js +18 -3
  160. package/dist/lib/execution/types.d.ts +3 -0
  161. package/dist/lib/flags/resolver.js +1 -0
  162. package/dist/lib/mcp/helpers.d.ts +1 -2
  163. package/dist/lib/mcp/tools/board.js +4 -6
  164. package/dist/lib/mcp/tools/cli-passthrough.js +25 -6
  165. package/dist/lib/mcp/tools/diet.js +1 -0
  166. package/dist/lib/mcp/tools/epic.js +8 -3
  167. package/dist/lib/mcp/tools/index.d.ts +1 -0
  168. package/dist/lib/mcp/tools/index.js +1 -0
  169. package/dist/lib/mcp/tools/label.d.ts +6 -0
  170. package/dist/lib/mcp/tools/label.js +338 -0
  171. package/dist/lib/mcp/tools/spec.js +1 -1
  172. package/dist/lib/mcp/tools/ticket.js +57 -19
  173. package/dist/lib/mcp/tools/work.js +96 -6
  174. package/dist/lib/mcp/types.d.ts +10 -0
  175. package/dist/lib/multiline-input.js +8 -19
  176. package/dist/lib/pmo/base-command.d.ts +0 -1
  177. package/dist/lib/pmo/base-command.js +4 -5
  178. package/dist/lib/pmo/schema.d.ts +6 -0
  179. package/dist/lib/pmo/schema.js +44 -0
  180. package/dist/lib/pmo/storage/actions.js +1 -1
  181. package/dist/lib/pmo/storage/base.d.ts +6 -0
  182. package/dist/lib/pmo/storage/base.js +311 -52
  183. package/dist/lib/pmo/storage/index.d.ts +23 -1
  184. package/dist/lib/pmo/storage/index.js +59 -1
  185. package/dist/lib/pmo/storage/labels.d.ts +55 -0
  186. package/dist/lib/pmo/storage/labels.js +346 -0
  187. package/dist/lib/pmo/storage/tickets.js +17 -0
  188. package/dist/lib/pmo/storage/types.d.ts +25 -0
  189. package/dist/lib/pmo/types.d.ts +44 -0
  190. package/dist/lib/pmo/utils.js +1 -1
  191. package/dist/lib/prompt-command.d.ts +20 -0
  192. package/dist/lib/prompt-command.js +38 -2
  193. package/dist/lib/prompt-json.d.ts +36 -4
  194. package/dist/lib/prompt-json.js +129 -7
  195. package/dist/lib/styles.d.ts +37 -0
  196. package/dist/lib/styles.js +73 -0
  197. package/oclif.manifest.json +6399 -3799
  198. package/package.json +1 -1
@@ -6,7 +6,7 @@ import { styles } from '../../lib/styles.js';
6
6
  import { getWorkspaceInfo } from '../../lib/agents/commands.js';
7
7
  import { ExecutionStorage } from '../../lib/execution/storage.js';
8
8
  import { PMOCommand, pmoBaseFlags } from '../../lib/pmo/index.js';
9
- import { outputErrorAsJson, createMetadata, shouldOutputJson, } from '../../lib/prompt-json.js';
9
+ import { outputErrorAsJson, outputSuccessAsJson, createMetadata, shouldOutputJson, } from '../../lib/prompt-json.js';
10
10
  export default class ExecutionView extends PMOCommand {
11
11
  static description = 'View details of a specific execution';
12
12
  static examples = [
@@ -63,7 +63,7 @@ export default class ExecutionView extends PMOCommand {
63
63
  this.log(styles.muted('\nNo executions found.\n'));
64
64
  return;
65
65
  }
66
- const jsonModeConfig = (flags.json || flags.machine) ? { flags, commandName: 'execution view' } : null;
66
+ const jsonModeConfig = shouldOutputJson(flags) ? { flags, commandName: 'execution view' } : null;
67
67
  const { selectedId } = await this.prompt([
68
68
  {
69
69
  type: 'list',
@@ -85,30 +85,26 @@ export default class ExecutionView extends PMOCommand {
85
85
  }
86
86
  // If JSON mode with ID provided, output the execution data as JSON
87
87
  if (jsonMode && args.id) {
88
- console.log(JSON.stringify({
89
- success: true,
90
- data: {
91
- id: execution.id,
92
- ticketId: execution.ticketId,
93
- agentName: execution.agentName,
94
- executor: execution.executor,
95
- environment: execution.environment,
96
- displayMode: execution.displayMode,
97
- sandboxed: execution.sandboxed,
98
- status: execution.status,
99
- branch: execution.branch || null,
100
- pid: execution.pid || null,
101
- containerId: execution.containerId || null,
102
- sessionId: execution.sessionId || null,
103
- host: execution.host || null,
104
- logPath: execution.logPath || null,
105
- startedAt: execution.startedAt.toISOString(),
106
- completedAt: execution.completedAt?.toISOString() || null,
107
- exitCode: execution.exitCode ?? null,
108
- },
109
- metadata: createMetadata('execution view', flags),
110
- }, null, 2));
111
- return;
88
+ db.close();
89
+ outputSuccessAsJson({
90
+ id: execution.id,
91
+ ticketId: execution.ticketId,
92
+ agentName: execution.agentName,
93
+ executor: execution.executor,
94
+ environment: execution.environment,
95
+ displayMode: execution.displayMode,
96
+ sandboxed: execution.sandboxed,
97
+ status: execution.status,
98
+ branch: execution.branch || null,
99
+ pid: execution.pid || null,
100
+ containerId: execution.containerId || null,
101
+ sessionId: execution.sessionId || null,
102
+ host: execution.host || null,
103
+ logPath: execution.logPath || null,
104
+ startedAt: execution.startedAt.toISOString(),
105
+ completedAt: execution.completedAt?.toISOString() || null,
106
+ exitCode: execution.exitCode ?? null,
107
+ }, createMetadata('execution view', flags));
112
108
  }
113
109
  // Display execution details
114
110
  this.log('');
@@ -6,6 +6,7 @@ import { promptForHQName, promptForHQLocation, initializeHQ, showNextSteps, vali
6
6
  import { promptForAgentsWithTheme } from '../lib/agents/index.js';
7
7
  import { promptForRepositories } from '../lib/repos/index.js';
8
8
  import { promptForPMOSetup, machineOutputFlags } from '../lib/pmo/index.js';
9
+ import { shouldOutputJson } from '../lib/prompt-json.js';
9
10
  export default class Init extends Command {
10
11
  static description = 'Initialize an HQ (headquarters) for managing repositories, agents, and projects';
11
12
  static examples = [
@@ -41,27 +42,9 @@ export default class Init extends Command {
41
42
  };
42
43
  async run() {
43
44
  const { flags } = await this.parse(Init);
44
- if (flags.json || flags.machine) {
45
+ if (shouldOutputJson(flags)) {
45
46
  await this.runAgentMode(flags);
46
47
  }
47
- else if (!process.stdin.isTTY) {
48
- // Non-interactive environment (likely an AI agent)
49
- // Output guidance as JSON
50
- this.outputJson({
51
- success: false,
52
- error: 'Interactive mode requires a TTY. Use --json flag for agent mode.',
53
- hint: 'Run: prlt init --json --name <hq-name> [--path <path>] [--agents a1,a2] [--no-pmo]',
54
- flags: {
55
- '--json': 'Enable agent mode with JSON output',
56
- '--name, -n': 'HQ name (required)',
57
- '--path, -p': 'HQ path (defaults to ./{name}-hq)',
58
- '--agents, -a': 'Comma-separated agent names',
59
- '--repos, -r': 'Comma-separated repo paths',
60
- '--pmo/--no-pmo': 'Include PMO (default: true)',
61
- },
62
- });
63
- this.exit(1);
64
- }
65
48
  else {
66
49
  await this.runHumanMode();
67
50
  }
@@ -0,0 +1,20 @@
1
+ import { PMOCommand } from '../../lib/pmo/index.js';
2
+ export default class LabelCreate extends PMOCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {
6
+ name: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
7
+ };
8
+ static flags: {
9
+ color: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
10
+ description: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
11
+ group: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
12
+ json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
13
+ machine: import("@oclif/core/interfaces").BooleanFlag<boolean>;
14
+ project: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
15
+ };
16
+ protected getPMOOptions(): {
17
+ promptIfMultiple: boolean;
18
+ };
19
+ execute(): Promise<void>;
20
+ }
@@ -0,0 +1,57 @@
1
+ import { Args, Flags } from '@oclif/core';
2
+ import { PMOCommand, pmoBaseFlags } from '../../lib/pmo/index.js';
3
+ import { shouldOutputJson } from '../../lib/prompt-json.js';
4
+ import { styles } from '../../lib/styles.js';
5
+ export default class LabelCreate extends PMOCommand {
6
+ static description = 'Create a new label';
7
+ static examples = [
8
+ '<%= config.bin %> <%= command.id %> my-label',
9
+ '<%= config.bin %> <%= command.id %> urgent --color "#ff0000" --group type',
10
+ '<%= config.bin %> <%= command.id %> frontend --group area --description "Frontend work"',
11
+ ];
12
+ static args = {
13
+ name: Args.string({
14
+ description: 'Label name',
15
+ required: true,
16
+ }),
17
+ };
18
+ static flags = {
19
+ ...pmoBaseFlags,
20
+ color: Flags.string({
21
+ char: 'c',
22
+ description: 'Label color (hex, e.g. #ff0000)',
23
+ }),
24
+ description: Flags.string({
25
+ char: 'd',
26
+ description: 'Label description',
27
+ }),
28
+ group: Flags.string({
29
+ char: 'g',
30
+ description: 'Label group ID to add this label to',
31
+ }),
32
+ };
33
+ getPMOOptions() {
34
+ return { promptIfMultiple: false };
35
+ }
36
+ async execute() {
37
+ const { args, flags } = await this.parse(LabelCreate);
38
+ const label = await this.storage.createLabel({
39
+ name: args.name,
40
+ color: flags.color,
41
+ description: flags.description,
42
+ groupId: flags.group,
43
+ });
44
+ if (shouldOutputJson(flags)) {
45
+ this.log(JSON.stringify(label, null, 2));
46
+ return;
47
+ }
48
+ this.log(styles.success(`\nCreated label: ${label.name} (${label.id})`));
49
+ if (label.groupName) {
50
+ this.log(styles.muted(` Group: ${label.groupName}`));
51
+ }
52
+ if (label.color) {
53
+ this.log(styles.muted(` Color: ${label.color}`));
54
+ }
55
+ this.log('');
56
+ }
57
+ }
@@ -0,0 +1,17 @@
1
+ import { PMOCommand } from '../../lib/pmo/index.js';
2
+ export default class LabelDelete extends PMOCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {
6
+ id: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
7
+ };
8
+ static flags: {
9
+ json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
10
+ machine: import("@oclif/core/interfaces").BooleanFlag<boolean>;
11
+ project: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
12
+ };
13
+ protected getPMOOptions(): {
14
+ promptIfMultiple: boolean;
15
+ };
16
+ execute(): Promise<void>;
17
+ }
@@ -0,0 +1,32 @@
1
+ import { Args } from '@oclif/core';
2
+ import { PMOCommand, pmoBaseFlags } from '../../lib/pmo/index.js';
3
+ import { shouldOutputJson } from '../../lib/prompt-json.js';
4
+ import { styles } from '../../lib/styles.js';
5
+ export default class LabelDelete extends PMOCommand {
6
+ static description = 'Delete a label (removes from all tickets)';
7
+ static examples = [
8
+ '<%= config.bin %> <%= command.id %> my-label',
9
+ ];
10
+ static args = {
11
+ id: Args.string({
12
+ description: 'Label ID to delete',
13
+ required: true,
14
+ }),
15
+ };
16
+ static flags = {
17
+ ...pmoBaseFlags,
18
+ };
19
+ getPMOOptions() {
20
+ return { promptIfMultiple: false };
21
+ }
22
+ async execute() {
23
+ const { args, flags } = await this.parse(LabelDelete);
24
+ await this.storage.deleteLabel(args.id);
25
+ if (shouldOutputJson(flags)) {
26
+ this.log(JSON.stringify({ success: true, deleted: args.id }));
27
+ return;
28
+ }
29
+ this.log(styles.success(`\nDeleted label: ${args.id}`));
30
+ this.log('');
31
+ }
32
+ }
@@ -0,0 +1,20 @@
1
+ import { PMOCommand } from '../../../lib/pmo/index.js';
2
+ export default class LabelGroupCreate extends PMOCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static args: {
6
+ name: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
7
+ };
8
+ static flags: {
9
+ description: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
10
+ exclusive: import("@oclif/core/interfaces").BooleanFlag<boolean>;
11
+ required: import("@oclif/core/interfaces").BooleanFlag<boolean>;
12
+ json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
13
+ machine: import("@oclif/core/interfaces").BooleanFlag<boolean>;
14
+ project: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
15
+ };
16
+ protected getPMOOptions(): {
17
+ promptIfMultiple: boolean;
18
+ };
19
+ execute(): Promise<void>;
20
+ }
@@ -0,0 +1,55 @@
1
+ import { Args, Flags } from '@oclif/core';
2
+ import { PMOCommand, pmoBaseFlags } from '../../../lib/pmo/index.js';
3
+ import { shouldOutputJson } from '../../../lib/prompt-json.js';
4
+ import { styles } from '../../../lib/styles.js';
5
+ export default class LabelGroupCreate extends PMOCommand {
6
+ static description = 'Create a new label group';
7
+ static examples = [
8
+ '<%= config.bin %> <%= command.id %> Priority',
9
+ '<%= config.bin %> <%= command.id %> Severity --exclusive --required',
10
+ '<%= config.bin %> <%= command.id %> Tags --no-exclusive --description "Free-form tags"',
11
+ ];
12
+ static args = {
13
+ name: Args.string({
14
+ description: 'Group name',
15
+ required: true,
16
+ }),
17
+ };
18
+ static flags = {
19
+ ...pmoBaseFlags,
20
+ description: Flags.string({
21
+ char: 'd',
22
+ description: 'Group description',
23
+ }),
24
+ exclusive: Flags.boolean({
25
+ description: 'Only one label from this group per ticket (default: true)',
26
+ default: true,
27
+ allowNo: true,
28
+ }),
29
+ required: Flags.boolean({
30
+ description: 'Must have one label from this group',
31
+ default: false,
32
+ }),
33
+ };
34
+ getPMOOptions() {
35
+ return { promptIfMultiple: false };
36
+ }
37
+ async execute() {
38
+ const { args, flags } = await this.parse(LabelGroupCreate);
39
+ const group = await this.storage.createLabelGroup({
40
+ name: args.name,
41
+ description: flags.description,
42
+ isExclusive: flags.exclusive,
43
+ isRequired: flags.required,
44
+ });
45
+ if (shouldOutputJson(flags)) {
46
+ this.log(JSON.stringify(group, null, 2));
47
+ return;
48
+ }
49
+ const exclusive = group.isExclusive ? 'exclusive' : 'non-exclusive';
50
+ const required = group.isRequired ? ', required' : '';
51
+ this.log(styles.success(`\nCreated label group: ${group.name} (${group.id})`));
52
+ this.log(styles.muted(` ${exclusive}${required}`));
53
+ this.log('');
54
+ }
55
+ }
@@ -0,0 +1,14 @@
1
+ import { PMOCommand } from '../../../lib/pmo/index.js';
2
+ export default class LabelGroupList extends PMOCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static flags: {
6
+ json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
7
+ machine: import("@oclif/core/interfaces").BooleanFlag<boolean>;
8
+ project: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
9
+ };
10
+ protected getPMOOptions(): {
11
+ promptIfMultiple: boolean;
12
+ };
13
+ execute(): Promise<void>;
14
+ }
@@ -0,0 +1,52 @@
1
+ import { Flags } from '@oclif/core';
2
+ import { PMOCommand, pmoBaseFlags } from '../../../lib/pmo/index.js';
3
+ import { shouldOutputJson } from '../../../lib/prompt-json.js';
4
+ import { styles } from '../../../lib/styles.js';
5
+ export default class LabelGroupList extends PMOCommand {
6
+ static description = 'List label groups';
7
+ static examples = [
8
+ '<%= config.bin %> <%= command.id %>',
9
+ '<%= config.bin %> <%= command.id %> --json',
10
+ ];
11
+ static flags = {
12
+ ...pmoBaseFlags,
13
+ json: Flags.boolean({
14
+ description: 'Output as JSON',
15
+ default: false,
16
+ }),
17
+ };
18
+ getPMOOptions() {
19
+ return { promptIfMultiple: false };
20
+ }
21
+ async execute() {
22
+ const { flags } = await this.parse(LabelGroupList);
23
+ const groups = await this.storage.listLabelGroups();
24
+ if (shouldOutputJson(flags)) {
25
+ this.log(JSON.stringify(groups, null, 2));
26
+ return;
27
+ }
28
+ if (groups.length === 0) {
29
+ this.log(styles.muted('\nNo label groups found.'));
30
+ this.log(styles.muted('Create one: prlt label group create <name>'));
31
+ return;
32
+ }
33
+ this.log(`\n${styles.emphasis('Label Groups')}`);
34
+ this.log('═'.repeat(60));
35
+ for (const group of groups) {
36
+ const exclusive = group.isExclusive ? 'exclusive' : 'non-exclusive';
37
+ const required = group.isRequired ? ', required' : '';
38
+ this.log(`\n ${styles.emphasis(group.name)} ${styles.muted(`(${group.id})`)}`);
39
+ this.log(` ${styles.muted(`${exclusive}${required}`)}`);
40
+ if (group.description) {
41
+ this.log(` ${styles.muted(group.description)}`);
42
+ }
43
+ // Show labels in this group
44
+ const labels = await this.storage.listLabels({ groupId: group.id });
45
+ if (labels.length > 0) {
46
+ const labelNames = labels.map(l => l.name).join(', ');
47
+ this.log(` Labels: ${labelNames}`);
48
+ }
49
+ }
50
+ this.log('');
51
+ }
52
+ }
@@ -0,0 +1,15 @@
1
+ import { PMOCommand } from '../../lib/pmo/index.js';
2
+ export default class LabelIndex extends PMOCommand {
3
+ static description: string;
4
+ static aliases: string[];
5
+ static examples: string[];
6
+ static flags: {
7
+ json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
8
+ machine: import("@oclif/core/interfaces").BooleanFlag<boolean>;
9
+ project: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
10
+ };
11
+ protected getPMOOptions(): {
12
+ promptIfMultiple: boolean;
13
+ };
14
+ execute(): Promise<void>;
15
+ }
@@ -0,0 +1,58 @@
1
+ import { PMOCommand, pmoBaseFlags } from '../../lib/pmo/index.js';
2
+ import { shouldOutputJson } from '../../lib/prompt-json.js';
3
+ export default class LabelIndex extends PMOCommand {
4
+ static description = 'Manage labels and label groups';
5
+ static aliases = ['labels'];
6
+ static examples = [
7
+ '<%= config.bin %> <%= command.id %>',
8
+ '<%= config.bin %> label list',
9
+ '<%= config.bin %> label create my-label',
10
+ '<%= config.bin %> label group list',
11
+ ];
12
+ static flags = {
13
+ ...pmoBaseFlags,
14
+ };
15
+ getPMOOptions() {
16
+ return { promptIfMultiple: false };
17
+ }
18
+ async execute() {
19
+ const { flags } = await this.parse(LabelIndex);
20
+ const jsonMode = shouldOutputJson(flags);
21
+ const menuChoices = [
22
+ { id: 'list', name: 'List all labels', command: 'prlt label list' },
23
+ { id: 'create', name: 'Create new label', command: 'prlt label create' },
24
+ { id: 'delete', name: 'Delete label', command: 'prlt label delete' },
25
+ { id: 'groups', name: 'List label groups', command: 'prlt label group list' },
26
+ { id: 'create-group', name: 'Create label group', command: 'prlt label group create' },
27
+ { id: 'cancel', name: 'Cancel', command: '' },
28
+ ];
29
+ const action = await this.selectFromList({
30
+ message: 'Labels - What would you like to do?',
31
+ items: menuChoices,
32
+ getName: (c) => c.name,
33
+ getValue: (c) => c.id,
34
+ getCommand: (c) => c.command,
35
+ jsonMode: jsonMode ? { flags, commandName: 'label' } : null,
36
+ });
37
+ if (action === 'cancel' || !action) {
38
+ return;
39
+ }
40
+ switch (action) {
41
+ case 'list':
42
+ await this.config.runCommand('label:list');
43
+ break;
44
+ case 'create':
45
+ await this.config.runCommand('label:create');
46
+ break;
47
+ case 'delete':
48
+ await this.config.runCommand('label:delete');
49
+ break;
50
+ case 'groups':
51
+ await this.config.runCommand('label:group:list');
52
+ break;
53
+ case 'create-group':
54
+ await this.config.runCommand('label:group:create');
55
+ break;
56
+ }
57
+ }
58
+ }
@@ -0,0 +1,16 @@
1
+ import { PMOCommand } from '../../lib/pmo/index.js';
2
+ export default class LabelList extends PMOCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static flags: {
6
+ group: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
7
+ json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
8
+ machine: import("@oclif/core/interfaces").BooleanFlag<boolean>;
9
+ project: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
10
+ };
11
+ protected getPMOOptions(): {
12
+ promptIfMultiple: boolean;
13
+ };
14
+ execute(): Promise<void>;
15
+ private printLabel;
16
+ }
@@ -0,0 +1,83 @@
1
+ import { Flags } from '@oclif/core';
2
+ import { PMOCommand, pmoBaseFlags } from '../../lib/pmo/index.js';
3
+ import { shouldOutputJson } from '../../lib/prompt-json.js';
4
+ import { styles } from '../../lib/styles.js';
5
+ export default class LabelList extends PMOCommand {
6
+ static description = 'List labels, optionally filtered by group';
7
+ static examples = [
8
+ '<%= config.bin %> <%= command.id %>',
9
+ '<%= config.bin %> <%= command.id %> --group function',
10
+ '<%= config.bin %> <%= command.id %> --json',
11
+ ];
12
+ static flags = {
13
+ ...pmoBaseFlags,
14
+ group: Flags.string({
15
+ char: 'g',
16
+ description: 'Filter by group ID',
17
+ }),
18
+ json: Flags.boolean({
19
+ description: 'Output as JSON',
20
+ default: false,
21
+ }),
22
+ };
23
+ getPMOOptions() {
24
+ return { promptIfMultiple: false };
25
+ }
26
+ async execute() {
27
+ const { flags } = await this.parse(LabelList);
28
+ const labels = await this.storage.listLabels({
29
+ groupId: flags.group,
30
+ });
31
+ if (shouldOutputJson(flags)) {
32
+ this.log(JSON.stringify(labels, null, 2));
33
+ return;
34
+ }
35
+ if (labels.length === 0) {
36
+ this.log(styles.muted('\nNo labels found.'));
37
+ this.log(styles.muted('Create one: prlt label create <name>'));
38
+ return;
39
+ }
40
+ this.log(`\n${styles.emphasis('Labels')}`);
41
+ this.log('═'.repeat(60));
42
+ // Group labels by group
43
+ const grouped = new Map();
44
+ const ungrouped = [];
45
+ for (const label of labels) {
46
+ if (label.groupName) {
47
+ const group = grouped.get(label.groupName) || [];
48
+ group.push(label);
49
+ grouped.set(label.groupName, group);
50
+ }
51
+ else {
52
+ ungrouped.push(label);
53
+ }
54
+ }
55
+ for (const [groupName, groupLabels] of grouped) {
56
+ // Look up group info
57
+ const group = await this.storage.getLabelGroupByName(groupName);
58
+ const exclusive = group?.isExclusive ? ' (exclusive)' : '';
59
+ const required = group?.isRequired ? ' (required)' : '';
60
+ this.log(`\n${styles.emphasis(groupName)}${styles.muted(exclusive + required)}`);
61
+ this.log('─'.repeat(40));
62
+ for (const label of groupLabels) {
63
+ this.printLabel(label);
64
+ }
65
+ }
66
+ if (ungrouped.length > 0) {
67
+ this.log(`\n${styles.emphasis('Ungrouped')}`);
68
+ this.log('─'.repeat(40));
69
+ for (const label of ungrouped) {
70
+ this.printLabel(label);
71
+ }
72
+ }
73
+ this.log('');
74
+ }
75
+ printLabel(label) {
76
+ const colorDot = label.color ? `${label.color} ` : '';
77
+ const builtinBadge = label.isBuiltin ? '' : ' [custom]';
78
+ this.log(` ${colorDot}${styles.emphasis(label.name)} ${styles.muted(`(${label.id})`)}${builtinBadge}`);
79
+ if (label.description) {
80
+ this.log(` ${styles.muted(label.description)}`);
81
+ }
82
+ }
83
+ }
@@ -1,3 +1,4 @@
1
+ /* eslint-disable no-await-in-loop */
1
2
  import { Args, Flags } from '@oclif/core';
2
3
  import { PMOCommand, pmoBaseFlags } from '../../lib/pmo/index.js';
3
4
  import { styles } from '../../lib/styles.js';
@@ -107,7 +108,7 @@ export default class LinkList extends PMOCommand {
107
108
  }
108
109
  this.log('');
109
110
  }
110
- async listSpecLinks(specId, showAll) {
111
+ async listSpecLinks(specId, _showAll) {
111
112
  const spec = await this.storage.getSpec(specId);
112
113
  if (!spec) {
113
114
  this.error(`Spec not found: ${specId}`);
@@ -137,7 +138,7 @@ export default class LinkList extends PMOCommand {
137
138
  }
138
139
  this.log('');
139
140
  }
140
- async listEpicLinks(epicId, showAll) {
141
+ async listEpicLinks(epicId, _showAll) {
141
142
  const epic = await this.storage.getEpic(epicId);
142
143
  if (!epic) {
143
144
  this.error(`Epic not found: ${epicId}`);
@@ -18,8 +18,11 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
18
18
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
19
19
  import { execSync } from 'node:child_process';
20
20
  import * as path from 'node:path';
21
+ import Database from 'better-sqlite3';
21
22
  import { getPMOContext } from '../lib/pmo/pmo-context.js';
22
- import { registerTicketTools, registerProjectTools, registerBoardTools, registerSpecTools, registerEpicTools, registerWorkTools, registerWorkflowTools, registerStatusTools, registerPhaseTools, registerActionTools, registerRoadmapTools, registerCategoryTools, registerTemplateTools, registerViewTools, registerDietTools, registerAgentTools, registerDockerTools, registerRepoTools, registerBranchTools, registerGitHubTools, registerInitTools, registerUtilityTools, } from '../lib/mcp/index.js';
23
+ import { getWorkspaceInfo } from '../lib/agents/commands.js';
24
+ import { ExecutionStorage } from '../lib/execution/storage.js';
25
+ import { registerTicketTools, registerProjectTools, registerBoardTools, registerSpecTools, registerEpicTools, registerWorkTools, registerWorkflowTools, registerStatusTools, registerPhaseTools, registerActionTools, registerRoadmapTools, registerCategoryTools, registerTemplateTools, registerViewTools, registerDietTools, registerLabelTools, registerAgentTools, registerDockerTools, registerRepoTools, registerBranchTools, registerGitHubTools, registerInitTools, registerUtilityTools, } from '../lib/mcp/index.js';
23
26
  export default class McpServerCommand extends Command {
24
27
  static description = 'Start MCP server for AI agent integration (exposes all prlt commands as tools)';
25
28
  static hidden = true;
@@ -38,6 +41,25 @@ export default class McpServerCommand extends Command {
38
41
  name: 'prlt',
39
42
  version: this.config.version,
40
43
  });
44
+ // Try to initialize workspace context for execution support
45
+ let workspaceContext = null;
46
+ try {
47
+ const workspaceInfo = getWorkspaceInfo();
48
+ if (workspaceInfo && pmoContext) {
49
+ const dbPath = path.join(workspaceInfo.path, '.proletariat', 'workspace.db');
50
+ const db = new Database(dbPath);
51
+ const executionStorage = new ExecutionStorage(db);
52
+ workspaceContext = {
53
+ workspaceInfo,
54
+ executionStorage,
55
+ db,
56
+ pmoPath: pmoContext.pmoPath,
57
+ };
58
+ }
59
+ }
60
+ catch {
61
+ // Not in a workspace — workspace context will be null
62
+ }
41
63
  // Create tool context
42
64
  const ctx = {
43
65
  get storage() {
@@ -68,6 +90,9 @@ export default class McpServerCommand extends Command {
68
90
  throw error;
69
91
  }
70
92
  },
93
+ getWorkspaceContext: workspaceContext
94
+ ? () => workspaceContext
95
+ : undefined,
71
96
  };
72
97
  // Register all tool categories
73
98
  registerTicketTools(server, ctx);
@@ -85,6 +110,7 @@ export default class McpServerCommand extends Command {
85
110
  registerTemplateTools(server, ctx);
86
111
  registerViewTools(server, ctx);
87
112
  registerDietTools(server, ctx);
113
+ registerLabelTools(server, ctx);
88
114
  registerAgentTools(server, ctx);
89
115
  registerDockerTools(server, ctx);
90
116
  registerRepoTools(server, ctx);