@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.
- package/dist/commands/caffeinate/index.d.ts +10 -0
- package/dist/commands/caffeinate/index.js +64 -0
- package/dist/commands/caffeinate/start.d.ts +14 -0
- package/dist/commands/caffeinate/start.js +86 -0
- package/dist/commands/caffeinate/status.d.ts +10 -0
- package/dist/commands/caffeinate/status.js +55 -0
- package/dist/commands/caffeinate/stop.d.ts +10 -0
- package/dist/commands/caffeinate/stop.js +47 -0
- package/dist/commands/claude/index.js +21 -21
- package/dist/commands/claude/open.js +1 -1
- package/dist/commands/commit.js +10 -8
- package/dist/commands/config/index.js +4 -5
- package/dist/commands/execution/config.d.ts +2 -2
- package/dist/commands/execution/config.js +18 -18
- package/dist/commands/execution/list.js +2 -2
- package/dist/commands/execution/view.js +2 -2
- package/dist/commands/init.js +9 -1
- package/dist/commands/orchestrator/attach.js +64 -14
- package/dist/commands/orchestrator/start.d.ts +5 -5
- package/dist/commands/orchestrator/start.js +45 -35
- package/dist/commands/orchestrator/status.js +64 -23
- package/dist/commands/orchestrator/stop.js +44 -12
- package/dist/commands/qa/index.js +12 -12
- package/dist/commands/session/attach.js +23 -0
- package/dist/commands/session/poke.js +1 -1
- package/dist/commands/staff/add.js +1 -1
- package/dist/commands/work/index.js +4 -0
- package/dist/commands/work/linear.d.ts +24 -0
- package/dist/commands/work/linear.js +218 -0
- package/dist/commands/work/revise.js +8 -8
- package/dist/commands/work/spawn.js +29 -20
- package/dist/commands/work/start.js +22 -12
- package/dist/commands/work/watch.js +3 -3
- package/dist/hooks/init.js +8 -0
- package/dist/lib/agents/index.js +2 -2
- package/dist/lib/caffeinate.d.ts +64 -0
- package/dist/lib/caffeinate.js +146 -0
- package/dist/lib/database/drizzle-schema.d.ts +7 -7
- package/dist/lib/database/drizzle-schema.js +1 -1
- package/dist/lib/execution/codex-adapter.d.ts +96 -0
- package/dist/lib/execution/codex-adapter.js +148 -0
- package/dist/lib/execution/config.d.ts +6 -6
- package/dist/lib/execution/config.js +17 -10
- package/dist/lib/execution/devcontainer.d.ts +3 -3
- package/dist/lib/execution/devcontainer.js +3 -3
- package/dist/lib/execution/index.d.ts +1 -0
- package/dist/lib/execution/index.js +1 -0
- package/dist/lib/execution/runners.d.ts +2 -2
- package/dist/lib/execution/runners.js +69 -26
- package/dist/lib/execution/spawner.js +3 -3
- package/dist/lib/execution/storage.d.ts +2 -2
- package/dist/lib/execution/storage.js +3 -3
- package/dist/lib/execution/types.d.ts +2 -2
- package/dist/lib/execution/types.js +1 -1
- package/dist/lib/external-issues/index.d.ts +1 -1
- package/dist/lib/external-issues/index.js +1 -1
- package/dist/lib/external-issues/linear.d.ts +43 -0
- package/dist/lib/external-issues/linear.js +261 -0
- package/dist/lib/external-issues/types.d.ts +67 -0
- package/dist/lib/external-issues/types.js +41 -0
- package/dist/lib/init/index.d.ts +4 -0
- package/dist/lib/init/index.js +11 -1
- package/dist/lib/machine-config.d.ts +1 -0
- package/dist/lib/machine-config.js +6 -3
- package/dist/lib/pmo/schema.d.ts +1 -1
- package/dist/lib/pmo/schema.js +1 -1
- package/dist/lib/pmo/storage/actions.js +3 -3
- package/dist/lib/pmo/storage/base.js +116 -6
- package/dist/lib/pmo/storage/epics.js +1 -1
- package/dist/lib/pmo/storage/tickets.js +2 -2
- package/dist/lib/pmo/storage/types.d.ts +2 -1
- package/dist/lib/repos/index.js +1 -1
- package/oclif.manifest.json +3052 -2721
- 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,
|
|
147
|
-
: '🐳 devcontainer (uses catch-all container,
|
|
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
|
|
270
|
+
let permissionMode = 'safe';
|
|
271
271
|
if (flags['permission-mode']) {
|
|
272
|
-
|
|
272
|
+
permissionMode = (flags['permission-mode'] || 'safe');
|
|
273
273
|
}
|
|
274
274
|
else {
|
|
275
|
-
const {
|
|
275
|
+
const { selectedMode } = await this.prompt([
|
|
276
276
|
{
|
|
277
277
|
type: 'list',
|
|
278
|
-
name: '
|
|
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
|
-
|
|
289
|
+
permissionMode = selectedMode;
|
|
290
290
|
}
|
|
291
291
|
// Warn about uncommitted changes in danger mode
|
|
292
|
-
if (
|
|
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.
|
|
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: ${
|
|
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,
|
|
541
|
-
: '🐳 devcontainer (uses catch-all container,
|
|
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
|
|
673
|
+
let permissionMode = 'safe';
|
|
674
674
|
if (flags['permission-mode']) {
|
|
675
|
-
|
|
675
|
+
permissionMode = (flags['permission-mode'] || 'safe');
|
|
676
676
|
}
|
|
677
677
|
else {
|
|
678
678
|
const containerNote = environment === 'devcontainer' ? ' (container provides additional isolation)' : '';
|
|
679
|
-
const {
|
|
679
|
+
const { selectedMode } = await this.prompt([
|
|
680
680
|
{
|
|
681
681
|
type: 'list',
|
|
682
|
-
name: '
|
|
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
|
-
|
|
695
|
+
permissionMode = selectedMode;
|
|
696
696
|
}
|
|
697
697
|
// Warn about uncommitted changes in danger mode
|
|
698
|
-
if (
|
|
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
|
-
|
|
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.
|
|
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: ${
|
|
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.
|
|
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')
|
package/dist/commands/commit.js
CHANGED
|
@@ -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
|
-
|
|
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
|
|
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 (
|
|
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
|
-
|
|
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(`
|
|
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
|
|
27
|
+
* Save permission mode preference to workspace settings
|
|
28
28
|
*/
|
|
29
|
-
private
|
|
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
|
|
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
|
-
|
|
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(`
|
|
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.
|
|
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 (
|
|
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 '
|
|
215
|
+
case 'permissionMode': {
|
|
216
216
|
const permChoices = [
|
|
217
|
-
{ name: 'safe
|
|
218
|
-
{ name: 'danger - Skip permission checks (--dangerously-skip-permissions)', value: '
|
|
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:
|
|
226
|
+
default: config.permissionMode,
|
|
227
227
|
},
|
|
228
228
|
], jsonModeConfig);
|
|
229
|
-
this.setConfigValue(db, '
|
|
230
|
-
this.log(styles.success(`Permission mode set to: ${newPerm
|
|
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
|
-
|
|
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 '
|
|
354
|
-
// Store
|
|
355
|
-
this.
|
|
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
|
|
392
|
+
* Save permission mode preference to workspace settings
|
|
393
393
|
*/
|
|
394
|
-
|
|
395
|
-
saveExecutionSetting(db, '
|
|
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.
|
|
92
|
-
const permsColor = exec.
|
|
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) +
|