@proletariat/cli 0.3.47 → 0.3.49

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 (74) hide show
  1. package/dist/commands/caffeinate/index.d.ts +10 -0
  2. package/dist/commands/caffeinate/index.js +64 -0
  3. package/dist/commands/caffeinate/start.d.ts +14 -0
  4. package/dist/commands/caffeinate/start.js +86 -0
  5. package/dist/commands/caffeinate/status.d.ts +10 -0
  6. package/dist/commands/caffeinate/status.js +55 -0
  7. package/dist/commands/caffeinate/stop.d.ts +10 -0
  8. package/dist/commands/caffeinate/stop.js +47 -0
  9. package/dist/commands/claude/index.js +21 -21
  10. package/dist/commands/claude/open.js +1 -1
  11. package/dist/commands/commit.js +10 -8
  12. package/dist/commands/config/index.js +4 -5
  13. package/dist/commands/execution/config.d.ts +2 -2
  14. package/dist/commands/execution/config.js +18 -18
  15. package/dist/commands/execution/list.js +2 -2
  16. package/dist/commands/execution/view.js +2 -2
  17. package/dist/commands/init.js +9 -1
  18. package/dist/commands/orchestrator/attach.js +64 -14
  19. package/dist/commands/orchestrator/start.d.ts +5 -5
  20. package/dist/commands/orchestrator/start.js +45 -35
  21. package/dist/commands/orchestrator/status.js +64 -23
  22. package/dist/commands/orchestrator/stop.js +44 -12
  23. package/dist/commands/qa/index.js +12 -12
  24. package/dist/commands/session/attach.js +23 -0
  25. package/dist/commands/session/poke.js +1 -1
  26. package/dist/commands/staff/add.js +1 -1
  27. package/dist/commands/work/index.js +4 -0
  28. package/dist/commands/work/linear.d.ts +24 -0
  29. package/dist/commands/work/linear.js +218 -0
  30. package/dist/commands/work/revise.js +8 -8
  31. package/dist/commands/work/spawn.js +29 -20
  32. package/dist/commands/work/start.js +22 -12
  33. package/dist/commands/work/watch.js +3 -3
  34. package/dist/hooks/init.js +8 -0
  35. package/dist/lib/agents/index.js +2 -2
  36. package/dist/lib/caffeinate.d.ts +64 -0
  37. package/dist/lib/caffeinate.js +146 -0
  38. package/dist/lib/database/drizzle-schema.d.ts +7 -7
  39. package/dist/lib/database/drizzle-schema.js +1 -1
  40. package/dist/lib/execution/codex-adapter.d.ts +96 -0
  41. package/dist/lib/execution/codex-adapter.js +148 -0
  42. package/dist/lib/execution/config.d.ts +6 -6
  43. package/dist/lib/execution/config.js +17 -10
  44. package/dist/lib/execution/devcontainer.d.ts +3 -3
  45. package/dist/lib/execution/devcontainer.js +3 -3
  46. package/dist/lib/execution/index.d.ts +1 -0
  47. package/dist/lib/execution/index.js +1 -0
  48. package/dist/lib/execution/runners.d.ts +2 -2
  49. package/dist/lib/execution/runners.js +69 -26
  50. package/dist/lib/execution/spawner.js +3 -3
  51. package/dist/lib/execution/storage.d.ts +2 -2
  52. package/dist/lib/execution/storage.js +3 -3
  53. package/dist/lib/execution/types.d.ts +2 -2
  54. package/dist/lib/execution/types.js +1 -1
  55. package/dist/lib/external-issues/index.d.ts +1 -1
  56. package/dist/lib/external-issues/index.js +1 -1
  57. package/dist/lib/external-issues/linear.d.ts +43 -0
  58. package/dist/lib/external-issues/linear.js +261 -0
  59. package/dist/lib/external-issues/types.d.ts +67 -0
  60. package/dist/lib/external-issues/types.js +41 -0
  61. package/dist/lib/init/index.d.ts +4 -0
  62. package/dist/lib/init/index.js +11 -1
  63. package/dist/lib/machine-config.d.ts +1 -0
  64. package/dist/lib/machine-config.js +6 -3
  65. package/dist/lib/pmo/schema.d.ts +1 -1
  66. package/dist/lib/pmo/schema.js +1 -1
  67. package/dist/lib/pmo/storage/actions.js +3 -3
  68. package/dist/lib/pmo/storage/base.js +116 -6
  69. package/dist/lib/pmo/storage/epics.js +1 -1
  70. package/dist/lib/pmo/storage/tickets.js +2 -2
  71. package/dist/lib/pmo/storage/types.d.ts +2 -1
  72. package/dist/lib/repos/index.js +1 -1
  73. package/oclif.manifest.json +3052 -2721
  74. package/package.json +1 -1
@@ -0,0 +1,10 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class Caffeinate extends Command {
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
+ };
9
+ run(): Promise<void>;
10
+ }
@@ -0,0 +1,64 @@
1
+ import { Command } from '@oclif/core';
2
+ import { styles } from '../../lib/styles.js';
3
+ import { shouldOutputJson } from '../../lib/prompt-json.js';
4
+ import { machineOutputFlags } from '../../lib/pmo/index.js';
5
+ import { FlagResolver } from '../../lib/flags/index.js';
6
+ import { isMacOS } from '../../lib/caffeinate.js';
7
+ export default class Caffeinate extends Command {
8
+ static description = 'Manage caffeinate to keep macOS awake';
9
+ static examples = [
10
+ '<%= config.bin %> caffeinate',
11
+ '<%= config.bin %> caffeinate start',
12
+ '<%= config.bin %> caffeinate status',
13
+ '<%= config.bin %> caffeinate stop',
14
+ '<%= config.bin %> caffeinate start --duration 3600',
15
+ '<%= config.bin %> caffeinate start --display',
16
+ ];
17
+ static flags = {
18
+ ...machineOutputFlags,
19
+ };
20
+ async run() {
21
+ const { flags } = await this.parse(Caffeinate);
22
+ const jsonMode = shouldOutputJson(flags);
23
+ if (!isMacOS()) {
24
+ if (jsonMode) {
25
+ this.log(JSON.stringify({
26
+ type: 'error',
27
+ error: { code: 'UNSUPPORTED_PLATFORM', message: `caffeinate is only supported on macOS (current platform: ${process.platform})` },
28
+ }, null, 2));
29
+ this.exit(1);
30
+ }
31
+ this.error(`caffeinate is only supported on macOS (current platform: ${process.platform})`);
32
+ }
33
+ const menuChoices = [
34
+ { name: 'Check caffeinate status', value: 'status', command: 'prlt caffeinate status --json' },
35
+ { name: 'Start caffeinate', value: 'start', command: 'prlt caffeinate start --json' },
36
+ { name: 'Stop caffeinate', value: 'stop', command: 'prlt caffeinate stop --json' },
37
+ { name: 'Exit', value: 'exit', command: 'prlt caffeinate --exit' },
38
+ ];
39
+ const resolver = new FlagResolver({
40
+ commandName: 'caffeinate',
41
+ baseCommand: 'prlt caffeinate',
42
+ jsonMode,
43
+ flags,
44
+ });
45
+ resolver.addPrompt({
46
+ flagName: 'action',
47
+ type: 'list',
48
+ message: 'What would you like to do?',
49
+ choices: () => menuChoices,
50
+ skipAutoCommand: true,
51
+ });
52
+ if (!jsonMode) {
53
+ this.log('');
54
+ this.log(styles.header('Caffeinate'));
55
+ this.log('');
56
+ }
57
+ const resolved = await resolver.resolve();
58
+ const action = resolved.action;
59
+ if (!action || action === 'exit') {
60
+ return;
61
+ }
62
+ await this.config.runCommand(`caffeinate:${action}`, []);
63
+ }
64
+ }
@@ -0,0 +1,14 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class CaffeinateStart extends Command {
3
+ static description: string;
4
+ static examples: string[];
5
+ static flags: {
6
+ duration: import("@oclif/core/interfaces").OptionFlag<number | undefined, import("@oclif/core/interfaces").CustomOptions>;
7
+ display: import("@oclif/core/interfaces").BooleanFlag<boolean>;
8
+ idle: import("@oclif/core/interfaces").BooleanFlag<boolean>;
9
+ system: import("@oclif/core/interfaces").BooleanFlag<boolean>;
10
+ json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
11
+ machine: import("@oclif/core/interfaces").BooleanFlag<boolean>;
12
+ };
13
+ run(): Promise<void>;
14
+ }
@@ -0,0 +1,86 @@
1
+ import { Command, Flags } from '@oclif/core';
2
+ import { styles } from '../../lib/styles.js';
3
+ import { shouldOutputJson } from '../../lib/prompt-json.js';
4
+ import { machineOutputFlags } from '../../lib/pmo/index.js';
5
+ import { isMacOS, startCaffeinate, getStatus } from '../../lib/caffeinate.js';
6
+ export default class CaffeinateStart extends Command {
7
+ static description = 'Start caffeinate to prevent macOS from sleeping';
8
+ static examples = [
9
+ '<%= config.bin %> caffeinate start',
10
+ '<%= config.bin %> caffeinate start --duration 3600',
11
+ '<%= config.bin %> caffeinate start --display',
12
+ ];
13
+ static flags = {
14
+ ...machineOutputFlags,
15
+ duration: Flags.integer({
16
+ char: 't',
17
+ description: 'Duration in seconds (default: indefinite)',
18
+ }),
19
+ display: Flags.boolean({
20
+ char: 'd',
21
+ description: 'Prevent display from sleeping (adds -d flag)',
22
+ default: false,
23
+ }),
24
+ idle: Flags.boolean({
25
+ char: 'i',
26
+ description: 'Prevent idle sleep (adds -i flag)',
27
+ default: false,
28
+ }),
29
+ system: Flags.boolean({
30
+ char: 's',
31
+ description: 'Prevent system sleep (adds -s flag)',
32
+ default: false,
33
+ }),
34
+ };
35
+ async run() {
36
+ const { flags } = await this.parse(CaffeinateStart);
37
+ const jsonMode = shouldOutputJson(flags);
38
+ if (!isMacOS()) {
39
+ if (jsonMode) {
40
+ this.log(JSON.stringify({
41
+ type: 'error',
42
+ error: { code: 'UNSUPPORTED_PLATFORM', message: `caffeinate is only supported on macOS (current platform: ${process.platform})` },
43
+ }, null, 2));
44
+ this.exit(1);
45
+ }
46
+ this.error(`caffeinate is only supported on macOS (current platform: ${process.platform})`);
47
+ }
48
+ // Build caffeinate flags
49
+ const caffeinateFlags = [];
50
+ if (flags.display)
51
+ caffeinateFlags.push('-d');
52
+ if (flags.idle)
53
+ caffeinateFlags.push('-i');
54
+ if (flags.system)
55
+ caffeinateFlags.push('-s');
56
+ // Check if already running (idempotent)
57
+ const { running, state: existingState } = getStatus();
58
+ if (running && existingState) {
59
+ if (jsonMode) {
60
+ this.log(JSON.stringify({
61
+ type: 'success',
62
+ result: { ...existingState, status: 'already_running' },
63
+ }, null, 2));
64
+ return;
65
+ }
66
+ this.log(`\n${styles.warning('caffeinate is already running')} ${styles.muted(`(PID: ${existingState.pid})`)}\n`);
67
+ return;
68
+ }
69
+ const state = startCaffeinate(caffeinateFlags, flags.duration);
70
+ if (jsonMode) {
71
+ this.log(JSON.stringify({
72
+ type: 'success',
73
+ result: { ...state, status: 'started' },
74
+ }, null, 2));
75
+ return;
76
+ }
77
+ this.log(`\n${styles.success('caffeinate started')} ${styles.muted(`(PID: ${state.pid})`)}`);
78
+ if (state.duration) {
79
+ this.log(styles.muted(` Duration: ${state.duration}s`));
80
+ }
81
+ if (state.flags.length > 0) {
82
+ this.log(styles.muted(` Flags: ${state.flags.join(' ')}`));
83
+ }
84
+ this.log('');
85
+ }
86
+ }
@@ -0,0 +1,10 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class CaffeinateStatus extends Command {
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
+ };
9
+ run(): Promise<void>;
10
+ }
@@ -0,0 +1,55 @@
1
+ import { Command } from '@oclif/core';
2
+ import { styles } from '../../lib/styles.js';
3
+ import { shouldOutputJson } from '../../lib/prompt-json.js';
4
+ import { machineOutputFlags } from '../../lib/pmo/index.js';
5
+ import { isMacOS, getStatus } from '../../lib/caffeinate.js';
6
+ export default class CaffeinateStatus extends Command {
7
+ static description = 'Check if caffeinate is running';
8
+ static examples = [
9
+ '<%= config.bin %> caffeinate status',
10
+ ];
11
+ static flags = {
12
+ ...machineOutputFlags,
13
+ };
14
+ async run() {
15
+ const { flags } = await this.parse(CaffeinateStatus);
16
+ const jsonMode = shouldOutputJson(flags);
17
+ if (!isMacOS()) {
18
+ if (jsonMode) {
19
+ this.log(JSON.stringify({
20
+ type: 'error',
21
+ error: { code: 'UNSUPPORTED_PLATFORM', message: `caffeinate is only supported on macOS (current platform: ${process.platform})` },
22
+ }, null, 2));
23
+ this.exit(1);
24
+ }
25
+ this.error(`caffeinate is only supported on macOS (current platform: ${process.platform})`);
26
+ }
27
+ const { running, state } = getStatus();
28
+ if (jsonMode) {
29
+ this.log(JSON.stringify({
30
+ type: 'success',
31
+ result: {
32
+ running,
33
+ ...(state ? { pid: state.pid, startedAt: state.startedAt, flags: state.flags, duration: state.duration ?? null } : {}),
34
+ },
35
+ }, null, 2));
36
+ return;
37
+ }
38
+ this.log(`\n${styles.header('Caffeinate Status')}`);
39
+ this.log('─'.repeat(40));
40
+ if (running && state) {
41
+ this.log(`${styles.success('Running')} ${styles.muted(`(PID: ${state.pid})`)}`);
42
+ this.log(styles.muted(` Started: ${state.startedAt}`));
43
+ if (state.flags.length > 0) {
44
+ this.log(styles.muted(` Flags: ${state.flags.join(' ')}`));
45
+ }
46
+ if (state.duration) {
47
+ this.log(styles.muted(` Duration: ${state.duration}s`));
48
+ }
49
+ }
50
+ else {
51
+ this.log(styles.muted('Not running'));
52
+ }
53
+ this.log('');
54
+ }
55
+ }
@@ -0,0 +1,10 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class CaffeinateStop extends Command {
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
+ };
9
+ run(): Promise<void>;
10
+ }
@@ -0,0 +1,47 @@
1
+ import { Command } from '@oclif/core';
2
+ import { styles } from '../../lib/styles.js';
3
+ import { shouldOutputJson } from '../../lib/prompt-json.js';
4
+ import { machineOutputFlags } from '../../lib/pmo/index.js';
5
+ import { isMacOS, stopCaffeinate, getStatus } from '../../lib/caffeinate.js';
6
+ export default class CaffeinateStop extends Command {
7
+ static description = 'Stop the managed caffeinate process';
8
+ static examples = [
9
+ '<%= config.bin %> caffeinate stop',
10
+ ];
11
+ static flags = {
12
+ ...machineOutputFlags,
13
+ };
14
+ async run() {
15
+ const { flags } = await this.parse(CaffeinateStop);
16
+ const jsonMode = shouldOutputJson(flags);
17
+ if (!isMacOS()) {
18
+ if (jsonMode) {
19
+ this.log(JSON.stringify({
20
+ type: 'error',
21
+ error: { code: 'UNSUPPORTED_PLATFORM', message: `caffeinate is only supported on macOS (current platform: ${process.platform})` },
22
+ }, null, 2));
23
+ this.exit(1);
24
+ }
25
+ this.error(`caffeinate is only supported on macOS (current platform: ${process.platform})`);
26
+ }
27
+ // Get current state for reporting
28
+ const { state } = getStatus();
29
+ const stopped = stopCaffeinate();
30
+ if (jsonMode) {
31
+ this.log(JSON.stringify({
32
+ type: 'success',
33
+ result: {
34
+ stopped,
35
+ pid: state?.pid ?? null,
36
+ },
37
+ }, null, 2));
38
+ return;
39
+ }
40
+ if (stopped) {
41
+ this.log(`\n${styles.success('caffeinate stopped')} ${styles.muted(`(PID: ${state?.pid})`)}\n`);
42
+ }
43
+ else {
44
+ this.log(`\n${styles.muted('caffeinate is not running')}\n`);
45
+ }
46
+ }
47
+ }
@@ -143,8 +143,8 @@ export default class Claude extends PromptCommand {
143
143
  else {
144
144
  // Build devcontainer label
145
145
  const devcontainerLabel = hasProjectDevcontainer
146
- ? '🐳 devcontainer (uses project config, sandboxed)'
147
- : '🐳 devcontainer (uses catch-all container, sandboxed)';
146
+ ? '🐳 devcontainer (uses project config, isolated)'
147
+ : '🐳 devcontainer (uses catch-all container, isolated)';
148
148
  // In JSON mode, output environment prompt and exit
149
149
  if (jsonMode) {
150
150
  await this.prompt([
@@ -267,15 +267,15 @@ export default class Claude extends PromptCommand {
267
267
  displayMode = selectedDisplay;
268
268
  }
269
269
  // Prompt for permission mode
270
- let sandboxed = true;
270
+ let permissionMode = 'safe';
271
271
  if (flags['permission-mode']) {
272
- sandboxed = flags['permission-mode'] === 'safe';
272
+ permissionMode = (flags['permission-mode'] || 'safe');
273
273
  }
274
274
  else {
275
- const { permissionMode } = await this.prompt([
275
+ const { selectedMode } = await this.prompt([
276
276
  {
277
277
  type: 'list',
278
- name: 'permissionMode',
278
+ name: 'selectedMode',
279
279
  message: 'Permission mode:',
280
280
  choices: [
281
281
  { name: '⚠️ danger - Skip permission checks (faster)', value: 'danger', command: `prlt claude --slug "${slug}" --environment ${environment} --display-mode ${displayMode} --permission-mode danger --json` },
@@ -286,10 +286,10 @@ export default class Claude extends PromptCommand {
286
286
  ], jsonModeConfig);
287
287
  if (jsonMode)
288
288
  return;
289
- sandboxed = permissionMode === 'safe';
289
+ permissionMode = selectedMode;
290
290
  }
291
291
  // Warn about uncommitted changes in danger mode
292
- if (!sandboxed && isGitRepo(workDir) && hasUncommittedChanges(workDir)) {
292
+ if (permissionMode === 'danger' && isGitRepo(workDir) && hasUncommittedChanges(workDir)) {
293
293
  this.log('');
294
294
  this.warn('Running in danger mode with uncommitted changes!');
295
295
  this.log(styles.muted(' Consider committing or stashing changes first.'));
@@ -347,7 +347,7 @@ export default class Claude extends PromptCommand {
347
347
  };
348
348
  // Load execution config (use defaults for yolo mode)
349
349
  const executionConfig = { ...DEFAULT_EXECUTION_CONFIG };
350
- executionConfig.sandboxed = sandboxed;
350
+ executionConfig.permissionMode = permissionMode;
351
351
  executionConfig.outputMode = 'interactive';
352
352
  // For terminal mode, prompt for terminal preference
353
353
  if (displayMode === 'terminal' && !jsonMode) {
@@ -384,7 +384,7 @@ export default class Claude extends PromptCommand {
384
384
  this.log(styles.muted(` Directory: ${workDir}`));
385
385
  this.log(styles.muted(` Environment: ${environment === 'devcontainer' ? '🐳' : '💻'} ${environment}`));
386
386
  this.log(styles.muted(` Display: ${displayMode}`));
387
- this.log(styles.muted(` Permissions: ${sandboxed ? '🔒 safe' : '⚠️ danger'}`));
387
+ this.log(styles.muted(` Permissions: ${permissionMode === 'safe' ? '🔒 safe' : '⚠️ danger'}`));
388
388
  if (flags.prompt) {
389
389
  this.log(styles.muted(` Initial prompt: "${flags.prompt.substring(0, 50)}${flags.prompt.length > 50 ? '...' : ''}"`));
390
390
  }
@@ -537,8 +537,8 @@ export default class Claude extends PromptCommand {
537
537
  const hasProjectDevcontainer = hasDevcontainerConfig(workDir);
538
538
  // Build devcontainer label
539
539
  const devcontainerLabel = hasProjectDevcontainer
540
- ? '🐳 devcontainer (uses project config, sandboxed)'
541
- : '🐳 devcontainer (uses catch-all container, sandboxed)';
540
+ ? '🐳 devcontainer (uses project config, isolated)'
541
+ : '🐳 devcontainer (uses catch-all container, isolated)';
542
542
  let environment = 'host';
543
543
  if (flags.environment) {
544
544
  environment = flags.environment;
@@ -670,16 +670,16 @@ export default class Claude extends PromptCommand {
670
670
  displayMode = selectedDisplay;
671
671
  }
672
672
  // Prompt for permission mode
673
- let sandboxed = true;
673
+ let permissionMode = 'safe';
674
674
  if (flags['permission-mode']) {
675
- sandboxed = flags['permission-mode'] === 'safe';
675
+ permissionMode = (flags['permission-mode'] || 'safe');
676
676
  }
677
677
  else {
678
678
  const containerNote = environment === 'devcontainer' ? ' (container provides additional isolation)' : '';
679
- const { permissionMode } = await this.prompt([
679
+ const { selectedMode } = await this.prompt([
680
680
  {
681
681
  type: 'list',
682
- name: 'permissionMode',
682
+ name: 'selectedMode',
683
683
  message: `Permission mode${containerNote}:`,
684
684
  choices: [
685
685
  { name: '⚠️ danger - Skip permission checks (faster)', value: 'danger', command: `prlt claude --project ${projectId} --title "${ticketTitle}" --environment ${environment} --display-mode ${displayMode} --permission-mode danger --json` },
@@ -692,10 +692,10 @@ export default class Claude extends PromptCommand {
692
692
  db.close();
693
693
  return;
694
694
  }
695
- sandboxed = permissionMode === 'safe';
695
+ permissionMode = selectedMode;
696
696
  }
697
697
  // Warn about uncommitted changes in danger mode
698
- if (!sandboxed && isGitRepo(workDir) && hasUncommittedChanges(workDir)) {
698
+ if (permissionMode === 'danger' && isGitRepo(workDir) && hasUncommittedChanges(workDir)) {
699
699
  this.log('');
700
700
  this.warn('Running in danger mode with uncommitted changes!');
701
701
  this.log(styles.muted(' Consider committing or stashing changes first.'));
@@ -777,14 +777,14 @@ export default class Claude extends PromptCommand {
777
777
  executor: 'claude-code',
778
778
  environment,
779
779
  displayMode,
780
- sandboxed,
780
+ permissionMode,
781
781
  branch: 'main',
782
782
  });
783
783
  // Update ticket assignee
784
784
  await storage.updateTicket(ticket.id, { assignee: agentName });
785
785
  // Load execution config
786
786
  const executionConfig = loadExecutionConfig(db);
787
- executionConfig.sandboxed = sandboxed;
787
+ executionConfig.permissionMode = permissionMode;
788
788
  executionConfig.outputMode = 'interactive';
789
789
  // For terminal mode, ensure terminal preference is set
790
790
  if (displayMode === 'terminal' && !jsonMode) {
@@ -808,7 +808,7 @@ export default class Claude extends PromptCommand {
808
808
  this.log(styles.muted(` Work ID: ${execution.id}`));
809
809
  this.log(styles.muted(` Environment: ${environment === 'devcontainer' ? '🐳' : '💻'} ${environment}`));
810
810
  this.log(styles.muted(` Display: ${displayMode}`));
811
- this.log(styles.muted(` Permissions: ${sandboxed ? '🔒 safe' : '⚠️ danger'}`));
811
+ this.log(styles.muted(` Permissions: ${permissionMode === 'safe' ? '🔒 safe' : '⚠️ danger'}`));
812
812
  if (flags.prompt) {
813
813
  this.log(styles.muted(` Initial prompt: "${flags.prompt.substring(0, 50)}${flags.prompt.length > 50 ? '...' : ''}"`));
814
814
  }
@@ -102,7 +102,7 @@ export default class Open extends PromptCommand {
102
102
  // Load execution config
103
103
  const executionConfig = { ...DEFAULT_EXECUTION_CONFIG };
104
104
  executionConfig.outputMode = 'interactive';
105
- executionConfig.sandboxed = false; // Default to dangerously-skip-permissions for quick open
105
+ executionConfig.permissionMode = 'danger'; // Default to danger mode for quick open
106
106
  // Try to load saved preferences from workspace DB or home dir
107
107
  const dbPath = hqPath
108
108
  ? path.join(hqPath, '.proletariat', 'workspace.db')
@@ -438,23 +438,25 @@ export default class Commit extends PromptCommand {
438
438
  }
439
439
  }
440
440
  // Check if there are staged changes
441
+ let hasStagedChanges = true;
441
442
  try {
442
443
  const staged = execSync('git diff --cached --name-only', {
443
444
  encoding: 'utf-8',
444
445
  stdio: ['pipe', 'pipe', 'pipe'],
445
446
  }).trim();
446
- if (!staged) {
447
- this.error('No staged changes to commit.\n\n' +
448
- 'Stage your changes first:\n' +
449
- ' git add <files>\n' +
450
- ' git add -A\n\n' +
451
- 'Or use --all flag:\n' +
452
- ' prlt commit --all "your message"');
453
- }
447
+ hasStagedChanges = staged.length > 0;
454
448
  }
455
449
  catch {
456
450
  // Ignore errors checking staged changes
457
451
  }
452
+ if (!hasStagedChanges) {
453
+ this.error('No staged changes to commit.\n\n' +
454
+ 'Stage your changes first:\n' +
455
+ ' git add <files>\n' +
456
+ ' git add -A\n\n' +
457
+ 'Or use --all flag:\n' +
458
+ ' prlt commit --all "your message"');
459
+ }
458
460
  // Create commit
459
461
  try {
460
462
  execSync(`git commit -m "${commitMessage.replace(/"/g, '\\"')}"`, {
@@ -77,10 +77,9 @@ export default class Config extends PromptCommand {
77
77
  }
78
78
  // Handle --list or --json flag without --setting (just show config)
79
79
  // Also handle non-TTY mode without explicit flags - output config as readable list
80
- const isExplicitJsonMode = (flags.json === true || flags.machine === true);
81
- const shouldShowConfigList = flags.list || (isExplicitJsonMode && !flags.setting) || (isNonTTY() && !flags.setting && !flags.set?.length);
80
+ const shouldShowConfigList = flags.list || (jsonMode && !flags.setting) || (isNonTTY() && !flags.setting && !flags.set?.length);
82
81
  if (shouldShowConfigList) {
83
- if (isExplicitJsonMode) {
82
+ if (jsonMode) {
84
83
  outputSuccessAsJson({
85
84
  terminal: {
86
85
  app: config.terminal.app,
@@ -93,7 +92,7 @@ export default class Config extends PromptCommand {
93
92
  defaultExecutor: config.defaultExecutor,
94
93
  defaultEnvironment: config.defaultEnvironment,
95
94
  outputMode: config.outputMode,
96
- sandboxed: config.sandboxed,
95
+ permissionMode: config.permissionMode,
97
96
  createPrDefault: config.createPrDefault ?? null,
98
97
  firewall: {
99
98
  allowlistDomains: config.firewall.allowlistDomains,
@@ -119,7 +118,7 @@ export default class Config extends PromptCommand {
119
118
  this.log(` defaultExecutor: ${config.defaultExecutor}`);
120
119
  this.log(` defaultEnvironment: ${config.defaultEnvironment}`);
121
120
  this.log(` outputMode: ${config.outputMode}`);
122
- this.log(` sandboxed: ${config.sandboxed}`);
121
+ this.log(` permissionMode: ${config.permissionMode}`);
123
122
  this.log(` createPrDefault: ${config.createPrDefault ?? 'not set (will prompt)'}`);
124
123
  this.log(` firewall.allowlistDomains: ${config.firewall.allowlistDomains.join(', ') || '(none)'}`);
125
124
  this.log('');
@@ -24,7 +24,7 @@ export default class ExecutionConfig extends PMOCommand {
24
24
  */
25
25
  private setOutputMode;
26
26
  /**
27
- * Save sandboxed preference to workspace settings
27
+ * Save permission mode preference to workspace settings
28
28
  */
29
- private setSandboxed;
29
+ private setPermissionMode;
30
30
  }
@@ -14,7 +14,7 @@ export default class ExecutionConfig extends PMOCommand {
14
14
  '<%= config.bin %> execution config --list # Show all settings',
15
15
  '<%= config.bin %> execution config --set defaultEnvironment host',
16
16
  '<%= config.bin %> execution config --set outputMode interactive',
17
- '<%= config.bin %> execution config --set sandboxed true',
17
+ '<%= config.bin %> execution config --set permissionMode safe',
18
18
  '<%= config.bin %> execution config --setting outputMode --json # Show output mode choices',
19
19
  ];
20
20
  static flags = {
@@ -91,7 +91,7 @@ export default class ExecutionConfig extends PMOCommand {
91
91
  defaultEnvironment: config.defaultEnvironment,
92
92
  defaultExecutor: config.defaultExecutor,
93
93
  outputMode: config.outputMode,
94
- sandboxed: config.sandboxed,
94
+ permissionMode: config.permissionMode,
95
95
  }, createMetadata('execution config', flags));
96
96
  }
97
97
  else {
@@ -105,7 +105,7 @@ export default class ExecutionConfig extends PMOCommand {
105
105
  this.log('');
106
106
  this.log(styles.emphasis('Output'));
107
107
  this.log(` outputMode: ${config.outputMode}`);
108
- this.log(` sandboxed: ${config.sandboxed}`);
108
+ this.log(` permissionMode: ${config.permissionMode}`);
109
109
  this.log('');
110
110
  this.log(styles.emphasis('Terminal'));
111
111
  this.log(` app: ${config.terminal.app}`);
@@ -131,7 +131,7 @@ export default class ExecutionConfig extends PMOCommand {
131
131
  const settingChoices = [
132
132
  { name: `Default Environment: ${config.defaultEnvironment}`, value: 'defaultEnvironment', command: 'prlt execution config --setting defaultEnvironment --json' },
133
133
  { name: `Output Mode: ${config.outputMode}`, value: 'outputMode', command: 'prlt execution config --setting outputMode --json' },
134
- { name: `Permission Mode: ${config.sandboxed ? 'safe' : 'danger'}`, value: 'sandboxed', command: 'prlt execution config --setting sandboxed --json' },
134
+ { name: `Permission Mode: ${config.permissionMode}`, value: 'permissionMode', command: 'prlt execution config --setting permissionMode --json' },
135
135
  { name: `Terminal App: ${config.terminal.app}`, value: 'terminal.app', command: 'prlt execution config --setting terminal.app --json' },
136
136
  { name: `Open Tabs in Background: ${config.terminal.openInBackground}`, value: 'terminal.openInBackground', command: 'prlt execution config --setting terminal.openInBackground --json' },
137
137
  { name: `Shell: ${config.shell}`, value: 'shell', command: 'prlt execution config --setting shell --json' },
@@ -177,7 +177,7 @@ export default class ExecutionConfig extends PMOCommand {
177
177
  case 'defaultEnvironment': {
178
178
  const envChoices = [
179
179
  { name: 'host - Run directly on host machine', value: 'host', command: 'prlt execution config --set "defaultEnvironment host" --json' },
180
- { name: 'devcontainer - Run in a devcontainer (sandboxed)', value: 'devcontainer', command: 'prlt execution config --set "defaultEnvironment devcontainer" --json' },
180
+ { name: 'devcontainer - Run in a devcontainer (isolated)', value: 'devcontainer', command: 'prlt execution config --set "defaultEnvironment devcontainer" --json' },
181
181
  { name: 'docker - Run in a Docker container', value: 'docker', command: 'prlt execution config --set "defaultEnvironment docker" --json' },
182
182
  { name: 'vm - Run on a remote VM', value: 'vm', command: 'prlt execution config --set "defaultEnvironment vm" --json' },
183
183
  ];
@@ -212,10 +212,10 @@ export default class ExecutionConfig extends PMOCommand {
212
212
  this.log(styles.success(`Output mode set to: ${newOutput}`));
213
213
  break;
214
214
  }
215
- case 'sandboxed': {
215
+ case 'permissionMode': {
216
216
  const permChoices = [
217
- { name: 'safe - Requires approval for dangerous operations (recommended)', value: 'true', command: 'prlt execution config --set "sandboxed true" --json' },
218
- { name: 'danger - Skip permission checks (--dangerously-skip-permissions)', value: 'false', command: 'prlt execution config --set "sandboxed false" --json' },
217
+ { name: '🔒 safe - Requires approval for dangerous operations (recommended)', value: 'safe', command: 'prlt execution config --set "permissionMode safe" --json' },
218
+ { name: '⚠️ danger - Skip permission checks (--dangerously-skip-permissions)', value: 'danger', command: 'prlt execution config --set "permissionMode danger" --json' },
219
219
  ];
220
220
  const { newPerm } = await this.prompt([
221
221
  {
@@ -223,11 +223,11 @@ export default class ExecutionConfig extends PMOCommand {
223
223
  name: 'newPerm',
224
224
  message: 'Select permission mode:',
225
225
  choices: permChoices,
226
- default: String(config.sandboxed),
226
+ default: config.permissionMode,
227
227
  },
228
228
  ], jsonModeConfig);
229
- this.setConfigValue(db, 'sandboxed', newPerm, false);
230
- this.log(styles.success(`Permission mode set to: ${newPerm === 'true' ? 'safe' : 'danger'}`));
229
+ this.setConfigValue(db, 'permissionMode', newPerm, false);
230
+ this.log(styles.success(`Permission mode set to: ${newPerm}`));
231
231
  break;
232
232
  }
233
233
  case 'terminal.app': {
@@ -324,7 +324,7 @@ export default class ExecutionConfig extends PMOCommand {
324
324
  const VALID_VALUES = {
325
325
  defaultenvironment: ['host', 'devcontainer', 'docker', 'vm'],
326
326
  outputmode: ['interactive', 'print'],
327
- sandboxed: ['true', 'false'],
327
+ permissionmode: ['safe', 'danger'],
328
328
  'terminal.app': ['Terminal', 'iTerm', 'Alacritty', 'Ghostty', 'Kitty', 'tmux', 'Warp', 'WezTerm'],
329
329
  'terminal.openinbackground': ['true', 'false'],
330
330
  shell: ['bash', 'zsh', 'fish'],
@@ -350,9 +350,9 @@ export default class ExecutionConfig extends PMOCommand {
350
350
  // Store output mode - need to add this to the config storage
351
351
  this.setOutputMode(db, value);
352
352
  break;
353
- case 'sandboxed':
354
- // Store sandboxed preference
355
- this.setSandboxed(db, value.toLowerCase() === 'true');
353
+ case 'permissionmode':
354
+ // Store permission mode preference
355
+ this.setPermissionMode(db, value);
356
356
  break;
357
357
  case 'terminal.app':
358
358
  saveTerminalApp(db, value);
@@ -389,9 +389,9 @@ export default class ExecutionConfig extends PMOCommand {
389
389
  saveExecutionSetting(db, 'outputMode', mode);
390
390
  }
391
391
  /**
392
- * Save sandboxed preference to workspace settings
392
+ * Save permission mode preference to workspace settings
393
393
  */
394
- setSandboxed(db, sandboxed) {
395
- saveExecutionSetting(db, 'sandboxed', sandboxed.toString());
394
+ setPermissionMode(db, mode) {
395
+ saveExecutionSetting(db, 'permissionMode', mode);
396
396
  }
397
397
  }
@@ -88,8 +88,8 @@ export default class ExecutionList extends PMOCommand {
88
88
  const timeAgo = formatTimeAgo(exec.startedAt);
89
89
  const envIcon = exec.environment === 'devcontainer' ? '🐳' : (exec.environment === 'host' ? '💻' : '📦');
90
90
  const envStr = `${envIcon} ${exec.environment}`;
91
- const permsStr = exec.sandboxed ? 'safe' : 'danger';
92
- const permsColor = exec.sandboxed ? styles.success : styles.warning;
91
+ const permsStr = exec.permissionMode;
92
+ const permsColor = exec.permissionMode === 'safe' ? styles.success : styles.warning;
93
93
  this.log(visualPadEnd(exec.id, 14) +
94
94
  visualPadEnd(exec.ticketId, 9) +
95
95
  visualPadEnd(exec.agentName, 10) +