@proletariat/cli 0.3.9 → 0.3.11
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/README.md +25 -0
- package/bin/dev.js +0 -0
- package/dist/commands/action/index.js +1 -1
- package/dist/commands/action/run.js +8 -12
- package/dist/commands/agent/auth.d.ts +30 -0
- package/dist/commands/agent/auth.js +172 -0
- package/dist/commands/agent/discover.d.ts +9 -0
- package/dist/commands/agent/discover.js +67 -0
- package/dist/commands/agent/index.js +47 -12
- package/dist/commands/agent/list.d.ts +4 -1
- package/dist/commands/agent/list.js +78 -16
- package/dist/commands/agent/login.js +35 -31
- package/dist/commands/agent/restart.js +2 -0
- package/dist/commands/agent/shell.js +78 -19
- package/dist/commands/agent/staff/add.js +1 -12
- package/dist/commands/agent/staff/remove.js +9 -7
- package/dist/commands/agent/status.js +17 -4
- package/dist/commands/agent/temp/cleanup.js +7 -3
- package/dist/commands/agent/themes/index.js +4 -5
- package/dist/commands/agent/themes/list.js +5 -5
- package/dist/commands/agent/visit.js +17 -4
- package/dist/commands/branch/create.d.ts +4 -0
- package/dist/commands/branch/create.js +16 -8
- package/dist/commands/branch/index.js +1 -1
- package/dist/commands/branch/where.js +1 -0
- package/dist/commands/claude.d.ts +38 -0
- package/dist/commands/claude.js +899 -0
- package/dist/commands/commit.js +1 -1
- package/dist/commands/config/index.d.ts +12 -0
- package/dist/commands/config/index.js +271 -0
- package/dist/commands/docker/clean.js +2 -2
- package/dist/commands/docker/index.js +2 -2
- package/dist/commands/docker/list.js +3 -8
- package/dist/commands/docker/logs.js +2 -2
- package/dist/commands/docker/prune.js +1 -1
- package/dist/commands/docker/restart.js +2 -2
- package/dist/commands/docker/shell.js +2 -2
- package/dist/commands/docker/start.js +2 -2
- package/dist/commands/docker/status.js +1 -1
- package/dist/commands/docker/stop.js +2 -2
- package/dist/commands/docker/sync.js +2 -2
- package/dist/commands/epic/index.js +1 -1
- package/dist/commands/epic/link/index.js +25 -14
- package/dist/commands/epic/link/remove.js +2 -0
- package/dist/commands/epic/list.js +5 -5
- package/dist/commands/epic/progress.js +10 -4
- package/dist/commands/epic/spec.js +2 -0
- package/dist/commands/epic/ticket.js +3 -0
- package/dist/commands/execution/stop.js +1 -0
- package/dist/commands/init.js +4 -4
- package/dist/commands/project/index.js +1 -1
- package/dist/commands/project/spec.js +7 -0
- package/dist/commands/repo/add.js +1 -0
- package/dist/commands/repo/remove.js +1 -0
- package/dist/commands/roadmap/add-project.d.ts +18 -0
- package/dist/commands/roadmap/add-project.js +135 -0
- package/dist/commands/roadmap/create.d.ts +22 -0
- package/dist/commands/roadmap/create.js +156 -0
- package/dist/commands/roadmap/delete.d.ts +17 -0
- package/dist/commands/roadmap/delete.js +104 -0
- package/dist/commands/roadmap/generate.d.ts +22 -0
- package/dist/commands/roadmap/generate.js +201 -0
- package/dist/commands/roadmap/index.d.ts +13 -0
- package/dist/commands/roadmap/index.js +61 -0
- package/dist/commands/roadmap/list.d.ts +12 -0
- package/dist/commands/roadmap/list.js +42 -0
- package/dist/commands/roadmap/remove-project.d.ts +18 -0
- package/dist/commands/roadmap/remove-project.js +147 -0
- package/dist/commands/roadmap/reorder.d.ts +17 -0
- package/dist/commands/roadmap/reorder.js +157 -0
- package/dist/commands/roadmap/update.d.ts +19 -0
- package/dist/commands/roadmap/update.js +136 -0
- package/dist/commands/roadmap/view.d.ts +16 -0
- package/dist/commands/roadmap/view.js +103 -0
- package/dist/commands/spec/index.js +1 -1
- package/dist/commands/spec/link/index.js +24 -13
- package/dist/commands/spec/link/remove.js +2 -0
- package/dist/commands/status/index.js +1 -1
- package/dist/commands/status/list.js +0 -8
- package/dist/commands/template/delete.js +2 -0
- package/dist/commands/terminal/title.d.ts +12 -0
- package/dist/commands/terminal/title.js +48 -0
- package/dist/commands/ticket/complete.js +2 -0
- package/dist/commands/ticket/create.js +4 -2
- package/dist/commands/ticket/delete.js +2 -0
- package/dist/commands/ticket/edit.js +8 -2
- package/dist/commands/ticket/link/index.js +17 -3
- package/dist/commands/ticket/link/remove.js +2 -0
- package/dist/commands/ticket/list.js +1 -2
- package/dist/commands/ticket/move.js +2 -0
- package/dist/commands/ticket/project.js +3 -1
- package/dist/commands/ticket/reassign.js +2 -0
- package/dist/commands/ticket/spec.js +4 -2
- package/dist/commands/ticket/template/apply.js +4 -3
- package/dist/commands/ticket/template/create.js +2 -0
- package/dist/commands/ticket/template/index.js +1 -1
- package/dist/commands/ticket/update.js +2 -0
- package/dist/commands/work/index.js +1 -1
- package/dist/commands/work/revise.js +7 -1
- package/dist/commands/work/spawn.d.ts +2 -1
- package/dist/commands/work/spawn.js +131 -36
- package/dist/commands/work/start.d.ts +2 -1
- package/dist/commands/work/start.js +349 -69
- package/dist/commands/work/watch.js +10 -2
- package/dist/commands/workflow/create.js +3 -3
- package/dist/commands/workflow/switch.js +2 -1
- package/dist/commands/workspace/remove.js +0 -8
- package/dist/commands/workspace/use.js +1 -9
- package/dist/lib/agents/commands.js +18 -13
- package/dist/lib/database/index.d.ts +19 -12
- package/dist/lib/database/index.js +158 -42
- package/dist/lib/docker/resolve.js +1 -1
- package/dist/lib/execution/config.d.ts +6 -0
- package/dist/lib/execution/config.js +15 -2
- package/dist/lib/execution/devcontainer.d.ts +2 -0
- package/dist/lib/execution/devcontainer.js +41 -9
- package/dist/lib/execution/runners.d.ts +85 -3
- package/dist/lib/execution/runners.js +925 -228
- package/dist/lib/execution/spawner.d.ts +2 -2
- package/dist/lib/execution/spawner.js +4 -3
- package/dist/lib/execution/storage.d.ts +2 -1
- package/dist/lib/execution/storage.js +9 -13
- package/dist/lib/execution/types.d.ts +10 -1
- package/dist/lib/execution/types.js +3 -1
- package/dist/lib/init/index.js +1 -0
- package/dist/lib/machine-config.js +1 -1
- package/dist/lib/pmo/base-command.js +5 -9
- package/dist/lib/pmo/index.js +2 -0
- package/dist/lib/pmo/schema.d.ts +6 -0
- package/dist/lib/pmo/schema.js +36 -0
- package/dist/lib/pmo/storage/base.js +3 -3
- package/dist/lib/pmo/storage/index.d.ts +16 -1
- package/dist/lib/pmo/storage/index.js +45 -0
- package/dist/lib/pmo/storage/roadmaps.d.ts +62 -0
- package/dist/lib/pmo/storage/roadmaps.js +301 -0
- package/dist/lib/pmo/storage/specs.js +2 -0
- package/dist/lib/pmo/storage/types.d.ts +14 -0
- package/dist/lib/pmo/sync-manager.d.ts +1 -1
- package/dist/lib/pmo/sync-manager.js +1 -1
- package/dist/lib/pmo/types.d.ts +41 -0
- package/dist/lib/pmo/utils.d.ts +2 -0
- package/dist/lib/pmo/utils.js +22 -1
- package/dist/lib/repos/index.js +7 -1
- package/dist/lib/terminal.d.ts +31 -0
- package/dist/lib/terminal.js +48 -0
- package/dist/lib/themes.d.ts +21 -3
- package/dist/lib/themes.js +80 -23
- package/dist/lib/workspace-config.d.ts +80 -0
- package/dist/lib/workspace-config.js +100 -0
- package/oclif.manifest.json +4065 -3225
- package/package.json +10 -6
- package/LICENSE +0 -21
|
@@ -8,7 +8,6 @@ export default class WorkStart extends PMOCommand {
|
|
|
8
8
|
static flags: {
|
|
9
9
|
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
10
10
|
all: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
11
|
-
mode: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
11
|
executor: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
12
|
action: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
13
|
prompt: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
@@ -17,6 +16,7 @@ export default class WorkStart extends PMOCommand {
|
|
|
17
16
|
'vm-host': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
18
17
|
'run-on-host': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
19
18
|
reconfigure: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
19
|
+
'permission-mode': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
20
20
|
'skip-permissions': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
21
21
|
'create-pr': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
22
22
|
'no-pr': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
@@ -25,6 +25,7 @@ export default class WorkStart extends PMOCommand {
|
|
|
25
25
|
session: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
26
26
|
agent: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
27
27
|
ephemeral: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
28
|
+
focus: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
28
29
|
project: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
29
30
|
};
|
|
30
31
|
execute(): Promise<void>;
|
|
@@ -5,12 +5,12 @@ import { execSync } from 'node:child_process';
|
|
|
5
5
|
import inquirer from 'inquirer';
|
|
6
6
|
import Database from 'better-sqlite3';
|
|
7
7
|
import { PMOCommand, pmoBaseFlags, autoExportToBoard } from '../../lib/pmo/index.js';
|
|
8
|
-
import { shouldOutputJson, outputErrorAsJson, createMetadata, } from '../../lib/prompt-json.js';
|
|
8
|
+
import { shouldOutputJson, outputPromptAsJson, outputErrorAsJson, createMetadata, buildPromptConfig, } from '../../lib/prompt-json.js';
|
|
9
9
|
import { getWorkColumnSetting, findColumnByName } from '../../lib/pmo/utils.js';
|
|
10
10
|
import { styles } from '../../lib/styles.js';
|
|
11
11
|
import { getWorkspaceInfo, createEphemeralAgent, getTicketTmuxSession, killTmuxSession, } from '../../lib/agents/commands.js';
|
|
12
12
|
import { generateBranchName, DEFAULT_EXECUTION_CONFIG, } from '../../lib/execution/types.js';
|
|
13
|
-
import { runExecution, isDockerRunning } from '../../lib/execution/runners.js';
|
|
13
|
+
import { runExecution, isDockerRunning, isGitHubTokenAvailable, isDevcontainerCliInstalled, dockerCredentialsExist, getDockerCredentialInfo } from '../../lib/execution/runners.js';
|
|
14
14
|
import { ExecutionStorage, ContainerStorage } from '../../lib/execution/storage.js';
|
|
15
15
|
import { loadExecutionConfig, getTerminalApp, promptTerminalPreference, getShell, promptShellPreference, hasTerminalPreference, hasShellPreference, getOrPromptCoderName } from '../../lib/execution/config.js';
|
|
16
16
|
import { hasDevcontainerConfig } from '../../lib/execution/devcontainer.js';
|
|
@@ -92,11 +92,6 @@ export default class WorkStart extends PMOCommand {
|
|
|
92
92
|
description: 'Start work on all unassigned backlog tickets (batch mode)',
|
|
93
93
|
default: false,
|
|
94
94
|
}),
|
|
95
|
-
mode: Flags.string({
|
|
96
|
-
char: 'm',
|
|
97
|
-
description: 'Runtime mode',
|
|
98
|
-
options: ['foreground', 'background', 'tmux', 'terminal', 'devcontainer', 'docker', 'vm'],
|
|
99
|
-
}),
|
|
100
95
|
executor: Flags.string({
|
|
101
96
|
char: 'e',
|
|
102
97
|
description: 'Override executor',
|
|
@@ -131,8 +126,12 @@ export default class WorkStart extends PMOCommand {
|
|
|
131
126
|
description: 'Re-prompt for terminal app preference',
|
|
132
127
|
default: false,
|
|
133
128
|
}),
|
|
129
|
+
'permission-mode': Flags.string({
|
|
130
|
+
description: 'Permission mode for Claude Code (danger=skip checks, safe=require approval)',
|
|
131
|
+
options: ['danger', 'safe'],
|
|
132
|
+
}),
|
|
134
133
|
'skip-permissions': Flags.boolean({
|
|
135
|
-
description: 'Skip permission
|
|
134
|
+
description: 'Skip permission checks (shorthand for --permission-mode danger)',
|
|
136
135
|
default: false,
|
|
137
136
|
}),
|
|
138
137
|
'create-pr': Flags.boolean({
|
|
@@ -150,8 +149,8 @@ export default class WorkStart extends PMOCommand {
|
|
|
150
149
|
}),
|
|
151
150
|
display: Flags.string({
|
|
152
151
|
char: 'd',
|
|
153
|
-
description: 'Display mode
|
|
154
|
-
options: ['terminal', 'background'],
|
|
152
|
+
description: 'Display mode (foreground=current terminal, terminal=new tab, background=detached)',
|
|
153
|
+
options: ['foreground', 'terminal', 'background'],
|
|
155
154
|
}),
|
|
156
155
|
session: Flags.string({
|
|
157
156
|
char: 's',
|
|
@@ -166,10 +165,24 @@ export default class WorkStart extends PMOCommand {
|
|
|
166
165
|
description: 'Create an ephemeral agent on-demand (auto-generates name)',
|
|
167
166
|
default: false,
|
|
168
167
|
}),
|
|
168
|
+
focus: Flags.boolean({
|
|
169
|
+
description: 'Bring terminal to foreground when opening new tabs (default: opens in background)',
|
|
170
|
+
default: false,
|
|
171
|
+
}),
|
|
169
172
|
};
|
|
170
173
|
async execute() {
|
|
171
174
|
const { args, flags } = await this.parse(WorkStart);
|
|
172
175
|
const projectId = flags.project;
|
|
176
|
+
// Handle --skip-permissions flag (alias for --permission-mode danger)
|
|
177
|
+
// Check for conflicting flags first
|
|
178
|
+
if (flags['skip-permissions'] && flags['permission-mode']) {
|
|
179
|
+
this.error('Cannot use both --skip-permissions and --permission-mode flags.\n' +
|
|
180
|
+
'Use only one: --skip-permissions OR --permission-mode danger/safe');
|
|
181
|
+
}
|
|
182
|
+
// Apply --skip-permissions as --permission-mode danger
|
|
183
|
+
if (flags['skip-permissions']) {
|
|
184
|
+
flags['permission-mode'] = 'danger';
|
|
185
|
+
}
|
|
173
186
|
// Check if JSON output mode is active
|
|
174
187
|
const jsonMode = shouldOutputJson(flags);
|
|
175
188
|
// Helper to handle errors in JSON mode
|
|
@@ -394,7 +407,7 @@ export default class WorkStart extends PMOCommand {
|
|
|
394
407
|
// At this point agentName is guaranteed to be set
|
|
395
408
|
const assignedAgent = agentName;
|
|
396
409
|
// Validate agent - for non-ephemeral agents, check if it exists in workspace
|
|
397
|
-
|
|
410
|
+
const agentInfo = workspaceInfo.agents.find((a) => a.name === assignedAgent);
|
|
398
411
|
if (!isEphemeralAgent && !agentInfo) {
|
|
399
412
|
db.close();
|
|
400
413
|
this.error(`Agent "${assignedAgent}" not found in workspace.\n` +
|
|
@@ -576,6 +589,7 @@ export default class WorkStart extends PMOCommand {
|
|
|
576
589
|
}
|
|
577
590
|
actionChoices.push(new inquirer.Separator('── Custom ──'));
|
|
578
591
|
actionChoices.push({ name: 'Custom prompt...', value: '__custom__' });
|
|
592
|
+
actionChoices.push({ name: 'Ad-hoc session - unstructured exploration/debugging', value: '__adhoc__' });
|
|
579
593
|
const { selectedActionId } = await inquirer.prompt([
|
|
580
594
|
{
|
|
581
595
|
type: 'list',
|
|
@@ -595,6 +609,19 @@ export default class WorkStart extends PMOCommand {
|
|
|
595
609
|
]);
|
|
596
610
|
customPrompt = customInput.trim();
|
|
597
611
|
}
|
|
612
|
+
else if (selectedActionId === '__adhoc__') {
|
|
613
|
+
// Ad-hoc session - no specific action, just launch Claude for exploration
|
|
614
|
+
selectedAction = {
|
|
615
|
+
id: 'adhoc',
|
|
616
|
+
name: 'Ad-hoc',
|
|
617
|
+
description: 'Unstructured exploration and debugging',
|
|
618
|
+
prompt: 'You are working on an ad-hoc session for exploration and debugging. Help the user with whatever they need.',
|
|
619
|
+
modifiesCode: false,
|
|
620
|
+
defaultMoveToCategory: 'started',
|
|
621
|
+
isBuiltin: false,
|
|
622
|
+
createdAt: new Date(),
|
|
623
|
+
};
|
|
624
|
+
}
|
|
598
625
|
else {
|
|
599
626
|
selectedAction = await this.storage.getAction(selectedActionId);
|
|
600
627
|
}
|
|
@@ -635,22 +662,37 @@ export default class WorkStart extends PMOCommand {
|
|
|
635
662
|
let environment = 'host';
|
|
636
663
|
let displayMode = 'terminal';
|
|
637
664
|
let sandboxed = false; // Whether --dangerously-skip-permissions is NOT used
|
|
638
|
-
if (hasDevcontainer && !flags.
|
|
665
|
+
if (hasDevcontainer && !flags.display && !flags['run-on-host']) {
|
|
639
666
|
// Agent has devcontainer - prompt for environment choice
|
|
667
|
+
// Check devcontainer prerequisites upfront
|
|
668
|
+
const dockerRunning = isDockerRunning();
|
|
669
|
+
const devcontainerCliInstalled = isDevcontainerCliInstalled();
|
|
670
|
+
const devcontainerReady = dockerRunning && devcontainerCliInstalled;
|
|
671
|
+
// Build missing requirements message for devcontainer option
|
|
672
|
+
let devcontainerLabel = '🐳 devcontainer (sandboxed, recommended)';
|
|
673
|
+
if (!devcontainerReady) {
|
|
674
|
+
const missing = [];
|
|
675
|
+
if (!dockerRunning)
|
|
676
|
+
missing.push('Docker');
|
|
677
|
+
if (!devcontainerCliInstalled)
|
|
678
|
+
missing.push('devcontainer CLI');
|
|
679
|
+
devcontainerLabel = `🐳 devcontainer (requires: ${missing.join(', ')})`;
|
|
680
|
+
}
|
|
640
681
|
// Loop to allow re-selection if Docker isn't running
|
|
641
682
|
let environmentSelected = false;
|
|
642
683
|
while (!environmentSelected) {
|
|
684
|
+
// eslint-disable-next-line no-await-in-loop -- Interactive loop with retry on Docker check
|
|
643
685
|
const { selectedEnvironment } = await inquirer.prompt([
|
|
644
686
|
{
|
|
645
687
|
type: 'list',
|
|
646
688
|
name: 'selectedEnvironment',
|
|
647
689
|
message: 'Where should the agent run?',
|
|
648
690
|
choices: [
|
|
649
|
-
{ name:
|
|
691
|
+
{ name: devcontainerLabel, value: 'devcontainer', disabled: !devcontainerReady },
|
|
650
692
|
{ name: '💻 host (runs directly on your machine)', value: 'host' },
|
|
651
693
|
{ name: '✗ cancel', value: 'cancel' },
|
|
652
694
|
],
|
|
653
|
-
default: 'devcontainer',
|
|
695
|
+
default: devcontainerReady ? 'devcontainer' : 'host',
|
|
654
696
|
},
|
|
655
697
|
]);
|
|
656
698
|
if (selectedEnvironment === 'cancel') {
|
|
@@ -659,7 +701,7 @@ export default class WorkStart extends PMOCommand {
|
|
|
659
701
|
return;
|
|
660
702
|
}
|
|
661
703
|
if (selectedEnvironment === 'devcontainer') {
|
|
662
|
-
//
|
|
704
|
+
// Double-check prerequisites (in case user retried after starting Docker)
|
|
663
705
|
if (!isDockerRunning()) {
|
|
664
706
|
this.log('');
|
|
665
707
|
this.warn('Docker is not running.\n' +
|
|
@@ -668,8 +710,74 @@ export default class WorkStart extends PMOCommand {
|
|
|
668
710
|
this.log('');
|
|
669
711
|
continue; // Re-prompt for environment selection
|
|
670
712
|
}
|
|
713
|
+
// Check devcontainer CLI is installed
|
|
714
|
+
if (!isDevcontainerCliInstalled()) {
|
|
715
|
+
this.log('');
|
|
716
|
+
this.warn('devcontainer CLI is not installed.\n' +
|
|
717
|
+
'Install with: npm install -g @devcontainers/cli\n' +
|
|
718
|
+
'Or select "host" to run directly on your machine.');
|
|
719
|
+
this.log('');
|
|
720
|
+
continue; // Re-prompt for environment selection
|
|
721
|
+
}
|
|
722
|
+
// Check GitHub token is available for git push operations
|
|
723
|
+
if (!isGitHubTokenAvailable()) {
|
|
724
|
+
const tokenChoices = [
|
|
725
|
+
{ name: 'Yes, continue anyway (git push may fail)', value: 'continue' },
|
|
726
|
+
{ name: 'No, let me run gh auth login first', value: 'cancel' },
|
|
727
|
+
{ name: 'Switch to host mode instead', value: 'host' },
|
|
728
|
+
];
|
|
729
|
+
const tokenMessage = 'GitHub token not found. Git push may fail. Continue without token?';
|
|
730
|
+
if (jsonMode) {
|
|
731
|
+
outputPromptAsJson(buildPromptConfig('list', 'tokenAction', tokenMessage, tokenChoices), createMetadata('work start', flags));
|
|
732
|
+
db.close();
|
|
733
|
+
return;
|
|
734
|
+
}
|
|
735
|
+
this.log('');
|
|
736
|
+
this.warn('GitHub token not found.\n' +
|
|
737
|
+
'Git push operations may fail inside the container.\n' +
|
|
738
|
+
'Run `gh auth login` to authenticate, or continue without token.');
|
|
739
|
+
this.log('');
|
|
740
|
+
// eslint-disable-next-line no-await-in-loop -- Interactive user prompt in loop
|
|
741
|
+
const { tokenAction } = await inquirer.prompt([
|
|
742
|
+
{
|
|
743
|
+
type: 'list',
|
|
744
|
+
name: 'tokenAction',
|
|
745
|
+
message: tokenMessage,
|
|
746
|
+
choices: tokenChoices,
|
|
747
|
+
default: 'continue',
|
|
748
|
+
},
|
|
749
|
+
]);
|
|
750
|
+
if (tokenAction === 'cancel') {
|
|
751
|
+
db.close();
|
|
752
|
+
this.log(styles.muted('Run `gh auth login` and try again.'));
|
|
753
|
+
return;
|
|
754
|
+
}
|
|
755
|
+
if (tokenAction === 'host') {
|
|
756
|
+
environment = 'host';
|
|
757
|
+
// Skip to host mode prompts
|
|
758
|
+
// eslint-disable-next-line no-await-in-loop -- Follow-up prompt after user selection
|
|
759
|
+
const { selectedDisplay } = await inquirer.prompt([
|
|
760
|
+
{
|
|
761
|
+
type: 'list',
|
|
762
|
+
name: 'selectedDisplay',
|
|
763
|
+
message: 'How should the agent output be displayed?',
|
|
764
|
+
choices: [
|
|
765
|
+
{ name: '🖥️ New tab - Opens in new terminal tab (recommended)', value: 'terminal' },
|
|
766
|
+
{ name: '▶️ Foreground - Run in current terminal (blocking)', value: 'foreground' },
|
|
767
|
+
{ name: '📦 Background - Runs detached, reattach with: prlt session attach', value: 'background' },
|
|
768
|
+
],
|
|
769
|
+
default: 'terminal',
|
|
770
|
+
},
|
|
771
|
+
]);
|
|
772
|
+
displayMode = selectedDisplay;
|
|
773
|
+
environmentSelected = true;
|
|
774
|
+
continue;
|
|
775
|
+
}
|
|
776
|
+
// tokenAction === 'continue' - fall through to devcontainer setup
|
|
777
|
+
}
|
|
671
778
|
environment = 'devcontainer';
|
|
672
779
|
// Pick display mode for devcontainer
|
|
780
|
+
// eslint-disable-next-line no-await-in-loop -- Follow-up prompt after selection
|
|
673
781
|
const { selectedDisplay } = await inquirer.prompt([
|
|
674
782
|
{
|
|
675
783
|
type: 'list',
|
|
@@ -677,6 +785,7 @@ export default class WorkStart extends PMOCommand {
|
|
|
677
785
|
message: 'How should the agent output be displayed?',
|
|
678
786
|
choices: [
|
|
679
787
|
{ name: '🖥️ New tab - Opens in new terminal tab (recommended)', value: 'terminal' },
|
|
788
|
+
{ name: '▶️ Foreground - Run in current terminal (blocking)', value: 'foreground' },
|
|
680
789
|
{ name: '📦 Background - Runs detached, reattach with: prlt session attach', value: 'background' },
|
|
681
790
|
],
|
|
682
791
|
default: 'terminal',
|
|
@@ -689,6 +798,7 @@ export default class WorkStart extends PMOCommand {
|
|
|
689
798
|
else {
|
|
690
799
|
// User chose host
|
|
691
800
|
environment = 'host';
|
|
801
|
+
// eslint-disable-next-line no-await-in-loop -- Follow-up prompt after selection
|
|
692
802
|
const { selectedDisplay } = await inquirer.prompt([
|
|
693
803
|
{
|
|
694
804
|
type: 'list',
|
|
@@ -696,6 +806,7 @@ export default class WorkStart extends PMOCommand {
|
|
|
696
806
|
message: 'How should the agent output be displayed?',
|
|
697
807
|
choices: [
|
|
698
808
|
{ name: '🖥️ New tab - Opens in new terminal tab (recommended)', value: 'terminal' },
|
|
809
|
+
{ name: '▶️ Foreground - Run in current terminal (blocking)', value: 'foreground' },
|
|
699
810
|
{ name: '📦 Background - Runs detached, reattach with: prlt session attach', value: 'background' },
|
|
700
811
|
],
|
|
701
812
|
default: 'terminal',
|
|
@@ -707,15 +818,11 @@ export default class WorkStart extends PMOCommand {
|
|
|
707
818
|
}
|
|
708
819
|
}
|
|
709
820
|
else if (useDevcontainer) {
|
|
710
|
-
// Devcontainer with explicit
|
|
821
|
+
// Devcontainer with explicit display flag
|
|
711
822
|
environment = 'devcontainer';
|
|
712
|
-
// Use --display flag if provided, otherwise fall back to --mode or default to 'terminal'
|
|
713
823
|
if (flags.display) {
|
|
714
824
|
displayMode = flags.display;
|
|
715
825
|
}
|
|
716
|
-
else if (flags.mode && ['terminal', 'background'].includes(flags.mode)) {
|
|
717
|
-
displayMode = flags.mode;
|
|
718
|
-
}
|
|
719
826
|
else {
|
|
720
827
|
// Default to terminal for devcontainer (opens new tab instead of blocking current terminal)
|
|
721
828
|
displayMode = 'terminal';
|
|
@@ -723,27 +830,14 @@ export default class WorkStart extends PMOCommand {
|
|
|
723
830
|
}
|
|
724
831
|
else {
|
|
725
832
|
// No devcontainer or --run-on-host - host mode selection
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
if (flagMode === 'docker') {
|
|
730
|
-
environment = 'docker';
|
|
731
|
-
displayMode = 'terminal';
|
|
732
|
-
}
|
|
733
|
-
else if (flagMode === 'vm') {
|
|
734
|
-
environment = 'vm';
|
|
735
|
-
displayMode = 'terminal';
|
|
736
|
-
}
|
|
737
|
-
else {
|
|
738
|
-
// Host environment: terminal/background are display modes
|
|
739
|
-
environment = 'host';
|
|
740
|
-
displayMode = flagMode;
|
|
741
|
-
}
|
|
833
|
+
environment = 'host';
|
|
834
|
+
if (flags.display) {
|
|
835
|
+
displayMode = flags.display;
|
|
742
836
|
}
|
|
743
837
|
else {
|
|
744
838
|
const warningMsg = flags['run-on-host']
|
|
745
|
-
? 'Select
|
|
746
|
-
: 'Select
|
|
839
|
+
? 'Select display mode (--run-on-host: bypassing devcontainer):'
|
|
840
|
+
: 'Select display mode (no devcontainer - running on host):';
|
|
747
841
|
const { selectedMode } = await inquirer.prompt([
|
|
748
842
|
{
|
|
749
843
|
type: 'list',
|
|
@@ -751,53 +845,127 @@ export default class WorkStart extends PMOCommand {
|
|
|
751
845
|
message: warningMsg,
|
|
752
846
|
choices: [
|
|
753
847
|
{ name: '🖥️ New tab - Opens in new terminal tab (recommended)', value: 'terminal' },
|
|
848
|
+
{ name: '▶️ Foreground - Run in current terminal (blocking)', value: 'foreground' },
|
|
754
849
|
{ name: '📦 Background - Runs detached, reattach with: prlt session attach', value: 'background' },
|
|
755
|
-
new inquirer.Separator('── Sandboxed (requires setup) ──'),
|
|
756
|
-
{ name: '🐳 Docker - Container with worktree mounted', value: 'docker' },
|
|
757
|
-
new inquirer.Separator('── Remote ──'),
|
|
758
|
-
{ name: '☁️ VM - Remote VM via SSH', value: 'vm' },
|
|
759
850
|
],
|
|
760
851
|
default: 'terminal',
|
|
761
852
|
},
|
|
762
853
|
]);
|
|
763
|
-
|
|
764
|
-
if (selectedMode === 'docker') {
|
|
765
|
-
environment = 'docker';
|
|
766
|
-
displayMode = 'terminal';
|
|
767
|
-
}
|
|
768
|
-
else if (selectedMode === 'vm') {
|
|
769
|
-
environment = 'vm';
|
|
770
|
-
displayMode = 'terminal';
|
|
771
|
-
}
|
|
772
|
-
else {
|
|
773
|
-
// Host environment: terminal/background are display modes
|
|
774
|
-
environment = 'host';
|
|
775
|
-
displayMode = selectedMode;
|
|
776
|
-
}
|
|
854
|
+
displayMode = selectedMode;
|
|
777
855
|
}
|
|
778
856
|
}
|
|
779
857
|
const executor = flags.executor || DEFAULT_EXECUTION_CONFIG.defaultExecutor;
|
|
780
858
|
// Default to interactive output mode (streaming UI)
|
|
781
859
|
// Can be overridden via --output flag if needed
|
|
782
|
-
|
|
860
|
+
const outputMode = flags.output || DEFAULT_EXECUTION_CONFIG.outputMode;
|
|
861
|
+
// Check Docker credentials for devcontainer environment
|
|
862
|
+
if (environment === 'devcontainer') {
|
|
863
|
+
const hasCredentials = dockerCredentialsExist();
|
|
864
|
+
if (!hasCredentials) {
|
|
865
|
+
this.log('');
|
|
866
|
+
this.log(styles.warning('⚠️ No Claude Code credentials found for Docker containers'));
|
|
867
|
+
this.log(styles.muted(' Agents will fail with 401 authentication errors without credentials.'));
|
|
868
|
+
this.log('');
|
|
869
|
+
const { authAction } = await inquirer.prompt([
|
|
870
|
+
{
|
|
871
|
+
type: 'list',
|
|
872
|
+
name: 'authAction',
|
|
873
|
+
message: 'What would you like to do?',
|
|
874
|
+
choices: [
|
|
875
|
+
{ name: `🔐 Run ${this.config.bin} agent auth now (one-time setup)`, value: 'auth' },
|
|
876
|
+
{ name: '💻 Switch to host environment instead', value: 'host' },
|
|
877
|
+
{ name: '⏩ Continue anyway (must run /login in first agent)', value: 'continue' },
|
|
878
|
+
{ name: '✗ Cancel', value: 'cancel' },
|
|
879
|
+
],
|
|
880
|
+
},
|
|
881
|
+
]);
|
|
882
|
+
if (authAction === 'cancel') {
|
|
883
|
+
db.close();
|
|
884
|
+
this.log(styles.muted('Cancelled.'));
|
|
885
|
+
return;
|
|
886
|
+
}
|
|
887
|
+
if (authAction === 'host') {
|
|
888
|
+
environment = 'host';
|
|
889
|
+
this.log(styles.muted('Switched to host environment.'));
|
|
890
|
+
}
|
|
891
|
+
else if (authAction === 'auth') {
|
|
892
|
+
this.log('');
|
|
893
|
+
this.log(styles.primary(`Opening ${this.config.bin} agent auth in new tab...`));
|
|
894
|
+
this.log('');
|
|
895
|
+
// Open auth in a new terminal tab
|
|
896
|
+
const authCmd = `${process.argv[1]} agent auth`;
|
|
897
|
+
try {
|
|
898
|
+
execSync(`osascript -e '
|
|
899
|
+
tell application "iTerm"
|
|
900
|
+
tell current window
|
|
901
|
+
create tab with default profile
|
|
902
|
+
tell current session
|
|
903
|
+
write text "${authCmd}"
|
|
904
|
+
end tell
|
|
905
|
+
end tell
|
|
906
|
+
end tell
|
|
907
|
+
'`);
|
|
908
|
+
}
|
|
909
|
+
catch {
|
|
910
|
+
// Fallback: try Terminal.app
|
|
911
|
+
try {
|
|
912
|
+
execSync(`osascript -e 'tell application "Terminal" to do script "${authCmd}"'`);
|
|
913
|
+
}
|
|
914
|
+
catch {
|
|
915
|
+
this.log(styles.warning('Could not open new terminal tab.'));
|
|
916
|
+
this.log(styles.muted(`Please run manually: ${authCmd}`));
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
this.log(styles.muted('Complete the /login flow in the new tab, then press Enter here...'));
|
|
920
|
+
this.log('');
|
|
921
|
+
// Wait for user to complete auth
|
|
922
|
+
await inquirer.prompt([{
|
|
923
|
+
type: 'input',
|
|
924
|
+
name: 'done',
|
|
925
|
+
message: 'Press Enter when authentication is complete:',
|
|
926
|
+
}]);
|
|
927
|
+
// Check if credentials now exist
|
|
928
|
+
if (!dockerCredentialsExist()) {
|
|
929
|
+
this.log('');
|
|
930
|
+
this.log(styles.warning('Authentication did not complete. No credentials found.'));
|
|
931
|
+
db.close();
|
|
932
|
+
return;
|
|
933
|
+
}
|
|
934
|
+
const info = getDockerCredentialInfo();
|
|
935
|
+
this.log('');
|
|
936
|
+
this.log(styles.success('✓ Credentials configured'));
|
|
937
|
+
if (info) {
|
|
938
|
+
this.log(styles.muted(` Subscription: ${info.subscriptionType || 'unknown'}`));
|
|
939
|
+
this.log(styles.muted(` Expires: ${info.expiresAt.toLocaleDateString()}`));
|
|
940
|
+
}
|
|
941
|
+
this.log('');
|
|
942
|
+
}
|
|
943
|
+
// authAction === 'continue' falls through
|
|
944
|
+
}
|
|
945
|
+
}
|
|
783
946
|
// Prompt for permissions mode (all environments)
|
|
784
|
-
// Skip prompt if --
|
|
785
|
-
if (flags['
|
|
786
|
-
sandboxed =
|
|
947
|
+
// Skip prompt if --permission-mode flag is set
|
|
948
|
+
if (flags['permission-mode']) {
|
|
949
|
+
sandboxed = flags['permission-mode'] === 'safe';
|
|
787
950
|
}
|
|
788
951
|
else {
|
|
789
|
-
const containerNote =
|
|
952
|
+
const containerNote = environment === 'devcontainer'
|
|
790
953
|
? ' (container provides additional isolation)'
|
|
791
954
|
: '';
|
|
955
|
+
const permissionChoices = [
|
|
956
|
+
{ name: '⚠️ danger - Skip permission checks (faster, container provides isolation)', value: 'danger', command: `prlt work start ${ticketId} --skip-permissions` },
|
|
957
|
+
{ name: '🔒 safe - Requires approval for dangerous operations', value: 'safe' },
|
|
958
|
+
];
|
|
959
|
+
// Handle JSON mode
|
|
960
|
+
if (jsonMode) {
|
|
961
|
+
outputPromptAsJson(buildPromptConfig('list', 'permissionMode', `Permission mode for Claude Code${containerNote}:`, permissionChoices, 'danger'), createMetadata('work start', flags));
|
|
962
|
+
}
|
|
792
963
|
const { permissionMode } = await inquirer.prompt([
|
|
793
964
|
{
|
|
794
965
|
type: 'list',
|
|
795
966
|
name: 'permissionMode',
|
|
796
967
|
message: `Permission mode for Claude Code${containerNote}:`,
|
|
797
|
-
choices:
|
|
798
|
-
{ name: '⚠️ danger - Skip permission checks (faster, container provides isolation)', value: 'danger' },
|
|
799
|
-
{ name: '🔒 safe - Requires approval for dangerous operations', value: 'safe' },
|
|
800
|
-
],
|
|
968
|
+
choices: permissionChoices,
|
|
801
969
|
default: 'danger',
|
|
802
970
|
},
|
|
803
971
|
]);
|
|
@@ -836,7 +1004,7 @@ export default class WorkStart extends PMOCommand {
|
|
|
836
1004
|
this.log(styles.muted(` Action: ${context.actionName || 'None'}`));
|
|
837
1005
|
this.log(styles.muted(` Executor: ${executor}`));
|
|
838
1006
|
// Environment info
|
|
839
|
-
const envIcon = environment === 'devcontainer' ? '🐳' :
|
|
1007
|
+
const envIcon = environment === 'devcontainer' ? '🐳' : '💻';
|
|
840
1008
|
this.log(styles.muted(` Environment: ${envIcon} ${environment}`));
|
|
841
1009
|
this.log(styles.muted(` Display: ${displayMode}`));
|
|
842
1010
|
// Permissions info
|
|
@@ -1069,6 +1237,10 @@ export default class WorkStart extends PMOCommand {
|
|
|
1069
1237
|
executionConfig.outputMode = outputMode;
|
|
1070
1238
|
// Set sandboxed mode (determines whether --dangerously-skip-permissions is used)
|
|
1071
1239
|
executionConfig.sandboxed = sandboxed;
|
|
1240
|
+
// Handle --focus flag: when set, bring terminal to foreground instead of opening in background
|
|
1241
|
+
if (flags.focus) {
|
|
1242
|
+
executionConfig.terminal.openInBackground = false;
|
|
1243
|
+
}
|
|
1072
1244
|
// Run execution
|
|
1073
1245
|
this.log(styles.muted('Starting agent...'));
|
|
1074
1246
|
const sessionManager = (flags.session || 'tmux');
|
|
@@ -1149,7 +1321,8 @@ export default class WorkStart extends PMOCommand {
|
|
|
1149
1321
|
*/
|
|
1150
1322
|
async runBatchMode(workspaceInfo, db, executionStorage, flags) {
|
|
1151
1323
|
// Get all tickets and filter to backlog/unstarted (not in progress)
|
|
1152
|
-
// Note: In batch mode, we
|
|
1324
|
+
// Note: In batch mode, we get all tickets across all projects (pass undefined for projectId)
|
|
1325
|
+
// eslint-disable-next-line unicorn/no-useless-undefined
|
|
1153
1326
|
const allTickets = await this.storage.listTickets(undefined);
|
|
1154
1327
|
const backlogTickets = allTickets.filter(t => t.statusCategory === 'backlog' || t.statusCategory === 'unstarted' || !t.statusCategory);
|
|
1155
1328
|
if (backlogTickets.length === 0) {
|
|
@@ -1199,6 +1372,110 @@ export default class WorkStart extends PMOCommand {
|
|
|
1199
1372
|
this.log(styles.muted('Cancelled.'));
|
|
1200
1373
|
return;
|
|
1201
1374
|
}
|
|
1375
|
+
// Prompt for permissions mode once for all tickets (TKT-513)
|
|
1376
|
+
let batchPermissionMode = flags['permission-mode'];
|
|
1377
|
+
if (!batchPermissionMode) {
|
|
1378
|
+
const { permissionMode } = await inquirer.prompt([
|
|
1379
|
+
{
|
|
1380
|
+
type: 'list',
|
|
1381
|
+
name: 'permissionMode',
|
|
1382
|
+
message: 'Permission mode for Claude Code:',
|
|
1383
|
+
choices: [
|
|
1384
|
+
{ name: '⚠️ danger - Skip permission checks (faster, container provides isolation)', value: 'danger' },
|
|
1385
|
+
{ name: '🔒 safe - Requires approval for dangerous operations', value: 'safe' },
|
|
1386
|
+
],
|
|
1387
|
+
default: 'danger',
|
|
1388
|
+
},
|
|
1389
|
+
]);
|
|
1390
|
+
batchPermissionMode = permissionMode;
|
|
1391
|
+
}
|
|
1392
|
+
// Check Docker credentials if any agents use devcontainers
|
|
1393
|
+
const anyUseDevcontainer = availableAgents.some(agent => {
|
|
1394
|
+
const agentDir = path.join(workspaceInfo.agentsPath, agent.name);
|
|
1395
|
+
return hasDevcontainerConfig(agentDir) && !flags['run-on-host'];
|
|
1396
|
+
});
|
|
1397
|
+
if (anyUseDevcontainer) {
|
|
1398
|
+
const hasCredentials = dockerCredentialsExist();
|
|
1399
|
+
if (!hasCredentials) {
|
|
1400
|
+
this.log('');
|
|
1401
|
+
this.log(styles.warning('⚠️ No Claude Code credentials found for Docker containers'));
|
|
1402
|
+
this.log(styles.muted(' Agents will fail with 401 authentication errors without credentials.'));
|
|
1403
|
+
this.log('');
|
|
1404
|
+
const { authAction } = await inquirer.prompt([
|
|
1405
|
+
{
|
|
1406
|
+
type: 'list',
|
|
1407
|
+
name: 'authAction',
|
|
1408
|
+
message: 'What would you like to do?',
|
|
1409
|
+
choices: [
|
|
1410
|
+
{ name: `🔐 Run ${this.config.bin} agent auth now (one-time setup)`, value: 'auth' },
|
|
1411
|
+
{ name: '💻 Run all agents on host instead (--run-on-host)', value: 'host' },
|
|
1412
|
+
{ name: '✗ Cancel', value: 'cancel' },
|
|
1413
|
+
],
|
|
1414
|
+
},
|
|
1415
|
+
]);
|
|
1416
|
+
if (authAction === 'cancel') {
|
|
1417
|
+
db.close();
|
|
1418
|
+
this.log(styles.muted('Cancelled.'));
|
|
1419
|
+
return;
|
|
1420
|
+
}
|
|
1421
|
+
if (authAction === 'host') {
|
|
1422
|
+
flags['run-on-host'] = true;
|
|
1423
|
+
this.log(styles.muted('All agents will run on host.'));
|
|
1424
|
+
}
|
|
1425
|
+
else if (authAction === 'auth') {
|
|
1426
|
+
this.log('');
|
|
1427
|
+
this.log(styles.primary(`Opening ${this.config.bin} agent auth in new tab...`));
|
|
1428
|
+
this.log('');
|
|
1429
|
+
// Open auth in a new terminal tab
|
|
1430
|
+
const authCmd = `${process.argv[1]} agent auth`;
|
|
1431
|
+
try {
|
|
1432
|
+
execSync(`osascript -e '
|
|
1433
|
+
tell application "iTerm"
|
|
1434
|
+
tell current window
|
|
1435
|
+
create tab with default profile
|
|
1436
|
+
tell current session
|
|
1437
|
+
write text "${authCmd}"
|
|
1438
|
+
end tell
|
|
1439
|
+
end tell
|
|
1440
|
+
end tell
|
|
1441
|
+
'`);
|
|
1442
|
+
}
|
|
1443
|
+
catch {
|
|
1444
|
+
// Fallback: try Terminal.app
|
|
1445
|
+
try {
|
|
1446
|
+
execSync(`osascript -e 'tell application "Terminal" to do script "${authCmd}"'`);
|
|
1447
|
+
}
|
|
1448
|
+
catch {
|
|
1449
|
+
this.log(styles.warning('Could not open new terminal tab.'));
|
|
1450
|
+
this.log(styles.muted(`Please run manually: ${authCmd}`));
|
|
1451
|
+
}
|
|
1452
|
+
}
|
|
1453
|
+
this.log(styles.muted('Complete the /login flow in the new tab, then press Enter here...'));
|
|
1454
|
+
this.log('');
|
|
1455
|
+
// Wait for user to complete auth
|
|
1456
|
+
await inquirer.prompt([{
|
|
1457
|
+
type: 'input',
|
|
1458
|
+
name: 'done',
|
|
1459
|
+
message: 'Press Enter when authentication is complete:',
|
|
1460
|
+
}]);
|
|
1461
|
+
// Check if credentials now exist
|
|
1462
|
+
if (!dockerCredentialsExist()) {
|
|
1463
|
+
this.log('');
|
|
1464
|
+
this.log(styles.warning('Authentication did not complete. No credentials found.'));
|
|
1465
|
+
db.close();
|
|
1466
|
+
return;
|
|
1467
|
+
}
|
|
1468
|
+
const info = getDockerCredentialInfo();
|
|
1469
|
+
this.log('');
|
|
1470
|
+
this.log(styles.success('✓ Credentials configured'));
|
|
1471
|
+
if (info) {
|
|
1472
|
+
this.log(styles.muted(` Subscription: ${info.subscriptionType || 'unknown'}`));
|
|
1473
|
+
this.log(styles.muted(` Expires: ${info.expiresAt.toLocaleDateString()}`));
|
|
1474
|
+
}
|
|
1475
|
+
this.log('');
|
|
1476
|
+
}
|
|
1477
|
+
}
|
|
1478
|
+
}
|
|
1202
1479
|
// Assign tickets to agents (round-robin)
|
|
1203
1480
|
const assignments = [];
|
|
1204
1481
|
for (let i = 0; i < backlogTickets.length; i++) {
|
|
@@ -1213,13 +1490,16 @@ export default class WorkStart extends PMOCommand {
|
|
|
1213
1490
|
this.log(styles.muted(`Starting ${ticket.id} with ${agent.name}...`));
|
|
1214
1491
|
// Use the work:start command for each ticket
|
|
1215
1492
|
// Pass --project from ticket to avoid re-prompting for project selection
|
|
1493
|
+
// Pass --permission-mode to skip prompts in recursive calls (TKT-513)
|
|
1494
|
+
// eslint-disable-next-line no-await-in-loop -- Sequential spawning with user feedback
|
|
1216
1495
|
await this.config.runCommand('work:start', [
|
|
1217
1496
|
ticket.id,
|
|
1218
1497
|
...(ticket.projectId ? ['--project', ticket.projectId] : []),
|
|
1219
|
-
'--
|
|
1498
|
+
'--display', flags.display || 'background',
|
|
1220
1499
|
...(flags.executor ? ['--executor', flags.executor] : []),
|
|
1221
1500
|
...(flags['run-on-host'] ? ['--run-on-host'] : []),
|
|
1222
1501
|
...(flags.force ? ['--force'] : []),
|
|
1502
|
+
'--permission-mode', batchPermissionMode,
|
|
1223
1503
|
]);
|
|
1224
1504
|
successCount++;
|
|
1225
1505
|
}
|
|
@@ -1317,7 +1597,7 @@ export default class WorkStart extends PMOCommand {
|
|
|
1317
1597
|
// Non-interactive defaults
|
|
1318
1598
|
const environment = useDevcontainer ? 'devcontainer' : 'host';
|
|
1319
1599
|
const displayMode = 'terminal';
|
|
1320
|
-
const sandboxed =
|
|
1600
|
+
const sandboxed = flags['permission-mode'] === 'safe';
|
|
1321
1601
|
const executor = flags.executor || DEFAULT_EXECUTION_CONFIG.defaultExecutor;
|
|
1322
1602
|
const outputMode = 'interactive';
|
|
1323
1603
|
// Handle git branch - only if action modifies code
|