@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
@@ -0,0 +1,144 @@
1
+ import inquirer from 'inquirer';
2
+ import chalk from 'chalk';
3
+ import { PromptCommand } from '../../../lib/prompt-command.js';
4
+ import { machineOutputFlags } from '../../../lib/pmo/index.js';
5
+ import { getWorkspaceInfo } from '../../../lib/agents/commands.js';
6
+ import { ensureBuiltinThemes } from '../../../lib/themes.js';
7
+ import { getThemes, getAvailableThemeNames } from '../../../lib/database/index.js';
8
+ import { shouldOutputJson, outputPromptAsJson, createMetadata, buildPromptConfig, } from '../../../lib/prompt-json.js';
9
+ export default class AgentThemes extends PromptCommand {
10
+ static description = 'Manage agent naming themes';
11
+ static examples = [
12
+ '<%= config.bin %> <%= command.id %> list',
13
+ '<%= config.bin %> <%= command.id %> create greek-gods',
14
+ '<%= config.bin %> <%= command.id %> add-names greek-gods zeus athena',
15
+ ];
16
+ static flags = {
17
+ ...machineOutputFlags,
18
+ };
19
+ async run() {
20
+ const { flags } = await this.parse(AgentThemes);
21
+ const jsonMode = shouldOutputJson(flags);
22
+ const menuChoices = [
23
+ { id: 'list', name: 'List themes', command: 'prlt agent themes list --format json' },
24
+ { id: 'create', name: 'Create a new theme', command: 'prlt agent themes create --machine' },
25
+ { id: 'add-names', name: 'Add names to a theme', command: 'prlt agent themes add-names --machine' },
26
+ { id: 'cancel', name: 'Cancel', command: '' },
27
+ ];
28
+ const message = 'What would you like to do?';
29
+ if (jsonMode) {
30
+ outputPromptAsJson(buildPromptConfig('list', 'action', message, menuChoices.map(c => ({
31
+ name: c.name,
32
+ value: c.id,
33
+ command: c.command,
34
+ }))), createMetadata('agent themes', flags));
35
+ return;
36
+ }
37
+ this.log(chalk.bold('\nAgent Themes'));
38
+ this.log(chalk.dim('Optional themed name pools for your agents.\n'));
39
+ const { action } = await this.prompt([{
40
+ type: 'list',
41
+ name: 'action',
42
+ message,
43
+ choices: [
44
+ ...menuChoices.slice(0, 3).map(c => ({ name: c.name, value: c.id })),
45
+ new inquirer.Separator(),
46
+ { name: menuChoices[3].name, value: menuChoices[3].id }
47
+ ]
48
+ }], null);
49
+ if (action === 'cancel') {
50
+ this.log(chalk.dim('Cancelled.'));
51
+ return;
52
+ }
53
+ try {
54
+ switch (action) {
55
+ case 'list': {
56
+ const { default: ListCommand } = await import('./list.js');
57
+ const cmd = new ListCommand([], this.config);
58
+ await cmd.run();
59
+ break;
60
+ }
61
+ case 'create': {
62
+ const { themeName } = await this.prompt([{
63
+ type: 'input',
64
+ name: 'themeName',
65
+ message: 'Theme name:',
66
+ validate: (input) => {
67
+ if (!input.trim())
68
+ return 'Theme name is required';
69
+ return true;
70
+ }
71
+ }], null);
72
+ const normalized = themeName.trim().toLowerCase().replace(/\s+/g, '-').replace(/[^a-z0-9-]/g, '');
73
+ if (themeName.trim() !== normalized) {
74
+ this.log(chalk.blue(`Normalized: ${themeName.trim()} → ${normalized}`));
75
+ }
76
+ const { default: CreateCommand } = await import('./create.js');
77
+ const cmd = new CreateCommand([normalized], this.config);
78
+ await cmd.run();
79
+ const { addNamesNow } = await this.prompt([{
80
+ type: 'list',
81
+ name: 'addNamesNow',
82
+ message: 'Add names to this theme now?',
83
+ choices: [
84
+ { name: 'Yes', value: true },
85
+ { name: 'No', value: false },
86
+ ],
87
+ }], null);
88
+ if (addNamesNow) {
89
+ const { names } = await this.prompt([{
90
+ type: 'input',
91
+ name: 'names',
92
+ message: 'Enter names (space-separated):',
93
+ validate: (input) => input.trim() ? true : 'At least one name is required'
94
+ }], null);
95
+ const addArgs = [normalized, ...names.trim().split(/\s+/)];
96
+ const { default: AddNamesCommand } = await import('./add-names.js');
97
+ const addCmd = new AddNamesCommand(addArgs, this.config);
98
+ await addCmd.run();
99
+ }
100
+ break;
101
+ }
102
+ case 'add-names': {
103
+ const workspaceInfo = getWorkspaceInfo();
104
+ ensureBuiltinThemes(workspaceInfo.path);
105
+ const themes = getThemes(workspaceInfo.path);
106
+ if (themes.length === 0) {
107
+ this.log(chalk.yellow('No themes found. Create one first.'));
108
+ return;
109
+ }
110
+ const themeChoices = themes.map(t => {
111
+ const availableNames = getAvailableThemeNames(workspaceInfo.path, t.id);
112
+ const builtinTag = t.builtin ? chalk.dim(' [built-in]') : '';
113
+ return {
114
+ name: `${t.display_name}${builtinTag} ${chalk.dim(`(${availableNames.length} names available)`)}`,
115
+ value: t.id
116
+ };
117
+ });
118
+ const { selectedTheme } = await this.prompt([{
119
+ type: 'list',
120
+ name: 'selectedTheme',
121
+ message: 'Select theme to add names to:',
122
+ choices: themeChoices
123
+ }], null);
124
+ const { names } = await this.prompt([{
125
+ type: 'input',
126
+ name: 'names',
127
+ message: 'Names to add (space-separated):',
128
+ validate: (input) => input.trim() ? true : 'At least one name is required'
129
+ }], null);
130
+ const addArgs = [selectedTheme, ...names.trim().split(/\s+/)];
131
+ const { default: AddNamesCommand } = await import('./add-names.js');
132
+ const cmd = new AddNamesCommand(addArgs, this.config);
133
+ await cmd.run();
134
+ break;
135
+ }
136
+ default:
137
+ this.error(`Unknown action: ${action}`);
138
+ }
139
+ }
140
+ catch (error) {
141
+ this.error(error instanceof Error ? error.message : String(error));
142
+ }
143
+ }
144
+ }
@@ -0,0 +1 @@
1
+ export { default } from '../../theme/list.js';
@@ -0,0 +1 @@
1
+ export { default } from '../../theme/list.js';
@@ -0,0 +1 @@
1
+ export { default } from '../../theme/set.js';
@@ -0,0 +1 @@
1
+ export { default } from '../../theme/set.js';
@@ -0,0 +1 @@
1
+ export { default } from '../../theme/add-names.js';
@@ -0,0 +1 @@
1
+ export { default } from '../../theme/add-names.js';
@@ -0,0 +1 @@
1
+ export { default } from '../../theme/create.js';
@@ -0,0 +1 @@
1
+ export { default } from '../../theme/create.js';
@@ -0,0 +1 @@
1
+ export { default } from '../../theme/list.js';
@@ -0,0 +1 @@
1
+ export { default } from '../../theme/list.js';
@@ -3,6 +3,7 @@ import * as fs from 'node:fs';
3
3
  import * as path from 'node:path';
4
4
  import chalk from 'chalk';
5
5
  import { PMOCommand, pmoBaseFlags, runWatcherForeground } from '../../lib/pmo/index.js';
6
+ import { shouldOutputJson } from '../../lib/prompt-json.js';
6
7
  import { styles } from '../../lib/styles.js';
7
8
  export default class BoardWatch extends PMOCommand {
8
9
  static description = 'Watch board.md for changes and auto-sync to SQLite';
@@ -23,6 +24,11 @@ export default class BoardWatch extends PMOCommand {
23
24
  }
24
25
  async execute() {
25
26
  const { flags } = await this.parse(BoardWatch);
27
+ if (shouldOutputJson(flags)) {
28
+ this.log(JSON.stringify({ type: 'error', error: { code: 'REQUIRES_TTY', message: 'board watch is a long-running interactive command. Use "prlt board" for non-interactive board data.' } }));
29
+ this.exit(1);
30
+ return;
31
+ }
26
32
  // Load PMO config
27
33
  const configPath = path.join(this.pmoPath, 'config.json');
28
34
  if (!fs.existsSync(configPath)) {
@@ -14,6 +14,7 @@ export default class BranchList extends PMOCommand {
14
14
  promptIfMultiple: boolean;
15
15
  };
16
16
  execute(): Promise<void>;
17
+ private listBranchesAcrossRepos;
17
18
  private outputTable;
18
19
  private outputCompact;
19
20
  }
@@ -2,6 +2,7 @@ import { Flags } from '@oclif/core';
2
2
  import { PMOCommand, pmoBaseFlags } from '../../lib/pmo/index.js';
3
3
  import { styles } from '../../lib/styles.js';
4
4
  import { BRANCH_TYPES, listBranches, isGitRepo, } from '../../lib/branch/index.js';
5
+ import { getWorkspaceRepoInfo } from '../../lib/repos/index.js';
5
6
  import { isNonTTY } from '../../lib/prompt-json.js';
6
7
  import { visualPadEnd } from '../../lib/string-utils.js';
7
8
  export default class BranchList extends PMOCommand {
@@ -40,12 +41,15 @@ export default class BranchList extends PMOCommand {
40
41
  if (flags.format === 'table' && isNonTTY()) {
41
42
  flags.format = 'json';
42
43
  }
43
- // Check if in git repo
44
- if (!isGitRepo()) {
45
- this.error('Not in a git repository.');
44
+ let branches;
45
+ if (isGitRepo()) {
46
+ // In a git repo - list branches for current repo
47
+ branches = listBranches(undefined, flags.all);
48
+ }
49
+ else {
50
+ // Not in a git repo - list branches across all registered HQ repos
51
+ branches = this.listBranchesAcrossRepos(flags.all);
46
52
  }
47
- // Get branches
48
- let branches = listBranches(undefined, flags.all);
49
53
  // Filter by type
50
54
  if (flags.type) {
51
55
  branches = branches.filter((b) => b.type === flags.type);
@@ -59,31 +63,55 @@ export default class BranchList extends PMOCommand {
59
63
  }
60
64
  return;
61
65
  }
66
+ // Check if we have multi-repo results
67
+ const hasRepoInfo = branches.some((b) => b.repo);
62
68
  // Output based on format
63
69
  switch (flags.format) {
64
70
  case 'json':
65
71
  this.log(JSON.stringify(branches, null, 2));
66
72
  break;
67
73
  case 'compact':
68
- this.outputCompact(branches);
74
+ this.outputCompact(branches, hasRepoInfo);
69
75
  break;
70
76
  case 'table':
71
77
  default:
72
- this.outputTable(branches);
78
+ this.outputTable(branches, hasRepoInfo);
73
79
  break;
74
80
  }
75
81
  }
76
- outputTable(branches) {
82
+ listBranchesAcrossRepos(includeRemote) {
83
+ let repoInfo;
84
+ try {
85
+ repoInfo = getWorkspaceRepoInfo();
86
+ }
87
+ catch {
88
+ this.error('Not in a git repository and no HQ workspace found.');
89
+ }
90
+ const allBranches = [];
91
+ for (const repo of repoInfo.repositories) {
92
+ if (repo.status === 'missing')
93
+ continue;
94
+ const repoBranches = listBranches(repo.fullPath, includeRemote);
95
+ for (const branch of repoBranches) {
96
+ branch.repo = repo.name;
97
+ allBranches.push(branch);
98
+ }
99
+ }
100
+ return allBranches;
101
+ }
102
+ outputTable(branches, hasRepoInfo = false) {
77
103
  this.log('');
78
104
  this.log(styles.header(`🌿 Branches (${branches.length})`));
79
105
  this.log('');
80
106
  // Header
81
- this.log(styles.muted(visualPadEnd('Name', 35) +
107
+ const repoHeader = hasRepoInfo ? visualPadEnd('Repo', 18) : '';
108
+ this.log(styles.muted(repoHeader +
109
+ visualPadEnd('Name', 35) +
82
110
  visualPadEnd('Type', 8) +
83
111
  visualPadEnd('Owner', 12) +
84
112
  visualPadEnd('Description', 25) +
85
113
  'Status'));
86
- this.log('─'.repeat(90));
114
+ this.log('─'.repeat(hasRepoInfo ? 108 : 90));
87
115
  // Rows
88
116
  for (const branch of branches) {
89
117
  const marker = branch.current ? '* ' : ' ';
@@ -91,6 +119,7 @@ export default class BranchList extends PMOCommand {
91
119
  const typeDisplay = branch.type || '-';
92
120
  const ownerDisplay = branch.owner || '-';
93
121
  const descDisplay = branch.description || '-';
122
+ const repoCol = hasRepoInfo ? visualPadEnd((branch.repo || '-').substring(0, 16), 18) : '';
94
123
  let status = 'local';
95
124
  if (branch.tracking) {
96
125
  status = `tracking ${branch.tracking}`;
@@ -99,6 +128,7 @@ export default class BranchList extends PMOCommand {
99
128
  status = 'current';
100
129
  }
101
130
  this.log(marker +
131
+ repoCol +
102
132
  nameStyle(visualPadEnd(branch.name.substring(0, 33), 33)) +
103
133
  visualPadEnd(typeDisplay, 8) +
104
134
  visualPadEnd(ownerDisplay.substring(0, 10), 12) +
@@ -109,14 +139,15 @@ export default class BranchList extends PMOCommand {
109
139
  this.log(styles.muted('Legend: * = current branch'));
110
140
  this.log('');
111
141
  }
112
- outputCompact(branches) {
142
+ outputCompact(branches, hasRepoInfo = false) {
113
143
  this.log('');
114
144
  for (const branch of branches) {
115
145
  const marker = branch.current ? '* ' : ' ';
116
146
  const icon = branch.type ? '🌿' : ' ';
117
147
  const typeInfo = branch.type ? ` (${branch.type})` : '';
148
+ const repoPrefix = hasRepoInfo && branch.repo ? `[${branch.repo}] ` : '';
118
149
  const nameStyle = branch.current ? styles.success : (s) => s;
119
- this.log(`${icon} ${marker}${nameStyle(branch.name)}${styles.muted(typeInfo)}`);
150
+ this.log(`${icon} ${marker}${repoPrefix}${nameStyle(branch.name)}${styles.muted(typeInfo)}`);
120
151
  }
121
152
  this.log('');
122
153
  }
@@ -2,6 +2,7 @@ import { Args } from '@oclif/core';
2
2
  import { execSync } from 'node:child_process';
3
3
  import * as path from 'node:path';
4
4
  import { PMOCommand, pmoBaseFlags } from '../../lib/pmo/index.js';
5
+ import { shouldOutputJson } from '../../lib/prompt-json.js';
5
6
  import { styles } from '../../lib/styles.js';
6
7
  import { isGitRepo, isTicketId } from '../../lib/branch/index.js';
7
8
  import { openWorkspaceDatabase } from '../../lib/database/index.js';
@@ -40,7 +41,7 @@ export default class BranchWhere extends PMOCommand {
40
41
  // Combine results, preferring git worktree info
41
42
  const allMatches = this.mergeResults(matches, dbMatches);
42
43
  if (allMatches.length === 0) {
43
- if (flags.json || flags.machine) {
44
+ if (shouldOutputJson(flags)) {
44
45
  this.log(JSON.stringify({ found: false, search, matches: [] }, null, 2));
45
46
  }
46
47
  else {
@@ -48,7 +49,7 @@ export default class BranchWhere extends PMOCommand {
48
49
  }
49
50
  return;
50
51
  }
51
- if (flags.json || flags.machine) {
52
+ if (shouldOutputJson(flags)) {
52
53
  this.log(JSON.stringify({
53
54
  found: true,
54
55
  search,
@@ -3,7 +3,7 @@ export default class CategoryList extends PMOCommand {
3
3
  static description: string;
4
4
  static examples: string[];
5
5
  static flags: {
6
- type: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
6
+ type: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
7
7
  builtin: import("@oclif/core/interfaces").BooleanFlag<boolean>;
8
8
  custom: import("@oclif/core/interfaces").BooleanFlag<boolean>;
9
9
  json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
@@ -14,5 +14,6 @@ export default class CategoryList extends PMOCommand {
14
14
  promptIfMultiple: boolean;
15
15
  };
16
16
  execute(): Promise<void>;
17
+ private printCategoryGroup;
17
18
  private printCategory;
18
19
  }
@@ -1,9 +1,11 @@
1
1
  import { Flags } from '@oclif/core';
2
2
  import { PMOCommand, pmoBaseFlags } from '../../lib/pmo/index.js';
3
+ import { shouldOutputJson } from '../../lib/prompt-json.js';
3
4
  import { styles } from '../../lib/styles.js';
4
5
  export default class CategoryList extends PMOCommand {
5
6
  static description = 'List categories for ticket or status types';
6
7
  static examples = [
8
+ '<%= config.bin %> <%= command.id %>',
7
9
  '<%= config.bin %> <%= command.id %> --type ticket',
8
10
  '<%= config.bin %> <%= command.id %> --type status',
9
11
  '<%= config.bin %> <%= command.id %> --type ticket --builtin',
@@ -13,9 +15,8 @@ export default class CategoryList extends PMOCommand {
13
15
  ...pmoBaseFlags,
14
16
  type: Flags.string({
15
17
  char: 't',
16
- description: 'Category type to list',
18
+ description: 'Category type to list (omit to list all)',
17
19
  options: ['ticket', 'status'],
18
- required: true,
19
20
  }),
20
21
  builtin: Flags.boolean({
21
22
  description: 'Show only built-in categories',
@@ -36,25 +37,52 @@ export default class CategoryList extends PMOCommand {
36
37
  async execute() {
37
38
  const { flags } = await this.parse(CategoryList);
38
39
  const categoryType = flags.type;
39
- let filter = { type: categoryType };
40
+ const filter = {};
41
+ if (categoryType)
42
+ filter.type = categoryType;
40
43
  if (flags.builtin)
41
44
  filter.isBuiltin = true;
42
45
  if (flags.custom)
43
46
  filter.isBuiltin = false;
44
47
  const categories = await this.storage.listCategories(filter);
45
- if (flags.json || flags.machine) {
48
+ if (shouldOutputJson(flags)) {
46
49
  this.log(JSON.stringify(categories, null, 2));
47
50
  return;
48
51
  }
49
52
  if (categories.length === 0) {
50
- this.log(styles.muted(`\nNo ${categoryType} categories found.`));
51
- this.log(styles.muted(`Create one: prlt category create --type ${categoryType}`));
53
+ const typeStr = categoryType ? `${categoryType} ` : '';
54
+ this.log(styles.muted(`\nNo ${typeStr}categories found.`));
55
+ this.log(styles.muted(`Create one: prlt category create --type ticket`));
52
56
  return;
53
57
  }
54
- const typeLabel = categoryType === 'ticket' ? 'Ticket' : 'Status';
55
- this.log(`\n📁 ${styles.emphasis(`${typeLabel} Categories`)}`);
56
- this.log(''.repeat(60));
57
- // Group by builtin vs custom
58
+ if (categoryType) {
59
+ // Single type: show as before
60
+ const typeLabel = categoryType === 'ticket' ? 'Ticket' : 'Status';
61
+ this.log(`\n📁 ${styles.emphasis(`${typeLabel} Categories`)}`);
62
+ this.log('═'.repeat(60));
63
+ this.printCategoryGroup(categories, flags);
64
+ this.log('');
65
+ this.log(styles.muted(`Create new: prlt category create --type ${categoryType} <name>`));
66
+ this.log('');
67
+ }
68
+ else {
69
+ // All types: group by type
70
+ const ticketCategories = categories.filter(c => c.type === 'ticket');
71
+ const statusCategories = categories.filter(c => c.type === 'status');
72
+ if (ticketCategories.length > 0) {
73
+ this.log(`\n📁 ${styles.emphasis('Ticket Categories')}`);
74
+ this.log('═'.repeat(60));
75
+ this.printCategoryGroup(ticketCategories, flags);
76
+ }
77
+ if (statusCategories.length > 0) {
78
+ this.log(`\n📁 ${styles.emphasis('Status Categories')}`);
79
+ this.log('═'.repeat(60));
80
+ this.printCategoryGroup(statusCategories, flags);
81
+ }
82
+ this.log('');
83
+ }
84
+ }
85
+ printCategoryGroup(categories, flags) {
58
86
  const builtinCategories = categories.filter(c => c.isBuiltin);
59
87
  const customCategories = categories.filter(c => !c.isBuiltin);
60
88
  if (builtinCategories.length > 0 && !flags.custom) {
@@ -71,9 +99,6 @@ export default class CategoryList extends PMOCommand {
71
99
  this.printCategory(category);
72
100
  }
73
101
  }
74
- this.log('');
75
- this.log(styles.muted(`Create new: prlt category create --type ${categoryType} <name>`));
76
- this.log('');
77
102
  }
78
103
  printCategory(category) {
79
104
  const builtinBadge = category.isBuiltin ? '' : ' [custom]';
@@ -1,4 +1,4 @@
1
- import { PromptCommand } from '../lib/prompt-command.js';
1
+ import { PromptCommand } from '../../lib/prompt-command.js';
2
2
  export default class Claude extends PromptCommand {
3
3
  static description: string;
4
4
  static examples: string[];
@@ -3,18 +3,18 @@ import * as fs from 'node:fs';
3
3
  import * as path from 'node:path';
4
4
  import * as os from 'node:os';
5
5
  import { execSync } from 'node:child_process';
6
- import { PromptCommand } from '../lib/prompt-command.js';
7
- import { machineOutputFlags } from '../lib/pmo/index.js';
6
+ import { PromptCommand } from '../../lib/prompt-command.js';
7
+ import { machineOutputFlags } from '../../lib/pmo/index.js';
8
8
  import Database from 'better-sqlite3';
9
- import { findHQRoot } from '../lib/workspace.js';
10
- import { getWorkspaceInfo, createEphemeralAgent, } from '../lib/agents/commands.js';
11
- import { shouldOutputJson, outputErrorAsJson, createMetadata, } from '../lib/prompt-json.js';
12
- import { styles } from '../lib/styles.js';
13
- import { DEFAULT_EXECUTION_CONFIG, } from '../lib/execution/types.js';
14
- import { runExecution, isDockerRunning, isGitHubTokenAvailable, isDevcontainerCliInstalled } from '../lib/execution/runners.js';
15
- import { ExecutionStorage } from '../lib/execution/storage.js';
16
- import { loadExecutionConfig, getTerminalApp, promptTerminalPreference, getShell, promptShellPreference, hasTerminalPreference, hasShellPreference, } from '../lib/execution/config.js';
17
- import { hasDevcontainerConfig } from '../lib/execution/devcontainer.js';
9
+ import { findHQRoot } from '../../lib/workspace.js';
10
+ import { getWorkspaceInfo, createEphemeralAgent, } from '../../lib/agents/commands.js';
11
+ import { shouldOutputJson, outputErrorAsJson, createMetadata, } from '../../lib/prompt-json.js';
12
+ import { styles } from '../../lib/styles.js';
13
+ import { DEFAULT_EXECUTION_CONFIG, } from '../../lib/execution/types.js';
14
+ import { runExecution, isDockerRunning, isGitHubTokenAvailable, isDevcontainerCliInstalled } from '../../lib/execution/runners.js';
15
+ import { ExecutionStorage } from '../../lib/execution/storage.js';
16
+ import { loadExecutionConfig, getTerminalApp, promptTerminalPreference, getShell, promptShellPreference, hasTerminalPreference, hasShellPreference, } from '../../lib/execution/config.js';
17
+ import { hasDevcontainerConfig } from '../../lib/execution/devcontainer.js';
18
18
  // Catch-all devcontainer image for directories without .devcontainer
19
19
  const CATCHALL_DEVCONTAINER_IMAGE = 'ghcr.io/chrismcdermut/proletariat-claude:latest';
20
20
  /**
@@ -450,7 +450,7 @@ export default class Claude extends PromptCommand {
450
450
  const executionStorage = new ExecutionStorage(db);
451
451
  try {
452
452
  // Import PMO storage for ticket/project operations
453
- const { getPMOContext } = await import('../lib/pmo/index.js');
453
+ const { getPMOContext } = await import('../../lib/pmo/index.js');
454
454
  let pmoPath;
455
455
  let storage;
456
456
  try {
@@ -0,0 +1,13 @@
1
+ import { PromptCommand } from '../../lib/prompt-command.js';
2
+ export default class Open extends PromptCommand {
3
+ static description: string;
4
+ static examples: string[];
5
+ static flags: {
6
+ agent: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
7
+ directory: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
8
+ prompt: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
9
+ json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
10
+ machine: import("@oclif/core/interfaces").BooleanFlag<boolean>;
11
+ };
12
+ run(): Promise<void>;
13
+ }