Skip to content

feat(agents): replace yolo mode with 3-way permission mode#1155

Draft
athal7 wants to merge 5 commits into
RunMaestro:mainfrom
athal7:feat/permission-mode
Draft

feat(agents): replace yolo mode with 3-way permission mode#1155
athal7 wants to merge 5 commits into
RunMaestro:mainfrom
athal7:feat/permission-mode

Conversation

@athal7

@athal7 athal7 commented Jul 1, 2026

Copy link
Copy Markdown

Replaces the binary yolo-mode/read-only toggle with permissionMode: 'full' | 'standard' | 'readonly'. full preserves current bypass behavior (renamed from yolo), standard is new and runs agents with no bypass flags so they use their own default permission model, readonly is the existing plan/exploration mode, unchanged.

Summary by CodeRabbit

  • New Features
    • Added a three-state per-tab permission model (Full Access, Standard, Read Only) and updated the toolbar to cycle modes with matching labels/tooltips.
  • Bug Fixes
    • Improved permission consistency across spawn paths (local, remote, queued, auto-run) by honoring an explicit permissionMode override.
    • Updated agent configurations so “Full Access” applies the correct full-permission args/env overrides while “Standard” avoids blanket elevated permissions.
  • Documentation
    • Refreshed onboarding/help text to reflect the new permission terminology and default behavior.
  • Tests
    • Expanded coverage for permission-mode precedence and full-access env override behavior.

Add permissionMode: 'full' | 'standard' | 'readonly' to replace the
binary yolo-mode/read-only toggle. 'full' preserves current bypass
behavior (renamed from yolo), 'standard' is new and runs agents with
no bypass flags so they use their default permission model, 'readonly'
is the existing plan/exploration mode, unchanged.

- Move each agent's bypass flags to fullAccessArgs (falls back to
  legacy yoloModeArgs); opencode's default env now denies the
  question tool without granting blanket permission, with the old
  full-allow config moved to fullAccessEnvOverrides
- agent-args builder resolves isFullAccess/isReadOnly from
  permissionMode with legacy yoloMode/readOnlyMode booleans as fallback
- Thread permissionMode through the IPC spawn config, preload bridge,
  and renderer spawn helpers
- Toolbar toggle button now cycles full -> standard -> readonly instead
  of a binary switch; label/tooltip/color driven by
  getPermissionModeLabel/getPermissionModeTooltip, which preserve the
  existing per-agent Plan-Mode vs Read-Only wording for readonly state
- Cue keeps permissionMode: 'full' (always full access, like Auto Run);
  context grooming keeps permissionMode: 'standard' (never needs
  bypass)
- Update wizard badge and welcome copy from YOLO to Full Access

Co-Authored-By: anthropic/claude-sonnet-4-6 <noreply@opencode.ai>
@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 641aa234-72a9-42ee-9d07-755bffe7d1ca

📥 Commits

Reviewing files that changed from the base of the PR and between ac3adcb and 7852d02.

📒 Files selected for processing (1)
  • src/__tests__/renderer/hooks/useInputProcessing.test.ts

📝 Walkthrough

Walkthrough

This PR adds permissionMode (full, standard, readonly) across agent config, spawn argument construction, process wiring, renderer state, and the toolbar UI. It also moves full-access args/env overrides into dedicated fields and updates tests and copy.

Changes

Permission Mode Feature

Layer / File(s) Summary
Types and metadata
src/shared/types.ts, src/main/agents/definitions.ts, src/main/preload/process.ts, src/renderer/global.d.ts, src/renderer/types/index.ts, src/shared/agentMetadata.ts, src/__tests__/shared/agentMetadata.test.ts
Adds fullAccessArgs, fullAccessEnvOverrides, and permissionMode fields to shared and renderer contracts, plus permission-mode label/tooltip helpers and tests.
Agent definitions and expectations
src/main/agents/definitions.ts, src/__tests__/main/agents/definitions.test.ts, src/__tests__/main/agents/detector.test.ts, src/__tests__/main/utils/context-groomer.test.ts
Moves permission-bypass behavior into fullAccessArgs/fullAccessEnvOverrides for several agents and updates the matching definition, detector, and context-groomer tests.
Argument resolution and spawn wiring
src/main/utils/agent-args.ts, src/main/cue/cue-spawn-builder.ts, src/main/utils/context-groomer.ts, src/main/ipc/handlers/process.ts, src/renderer/utils/sessionHelpers.ts, src/renderer/utils/agentArgs.ts, src/__tests__/main/utils/agent-args.test.ts, src/__tests__/main/cue/cue-spawn-builder.test.ts, src/__tests__/main/ipc/handlers/process.test.ts
Resolves effective permission mode in buildAgentArgs, passes permissionMode through spawn config paths, applies full-access env overrides, and updates the associated tests.
Renderer read-only and toggle flow
src/renderer/components/MainPanel/MainPanelContent.tsx, src/renderer/hooks/input/useInputProcessing.ts, src/renderer/hooks/remote/useRemoteHandlers.ts, src/renderer/stores/agentStore.ts, src/renderer/components/InputArea/InputArea.tsx, src/renderer/components/InputArea/components/ToolbarControls.tsx, src/renderer/components/WelcomeContent.tsx, src/renderer/components/Wizard/screens/DirectorySelectionScreen/components/DirectorySelectionHeader.tsx, src/__tests__/renderer/components/InputArea.test.tsx, src/__tests__/renderer/components/InputArea/components/ToolbarControls.test.tsx, src/__tests__/renderer/hooks/useInputProcessing.test.ts, src/__tests__/renderer/hooks/useRemoteHandlers.test.ts, src/__tests__/renderer/stores/agentStore.test.ts
Treats permissionMode: 'readonly' as read-only in renderer flows and replaces the toolbar’s boolean read-only toggle with a three-state permission-mode cycle backed by session updates.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: replacing yolo mode with a three-way permission mode.
Docstring Coverage ✅ Passed Docstring coverage is 90.91% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@athal7 athal7 marked this pull request as ready for review July 1, 2026 17:24
@greptile-apps

greptile-apps Bot commented Jul 1, 2026

Copy link
Copy Markdown

Greptile Summary

This PR replaces the binary yolo/read-only toggle with a 3-way permissionMode ('full' | 'standard' | 'readonly'), moves bypass flags into per-agent fullAccessArgs/fullAccessEnvOverrides, and adds a cycling toolbar button.

  • agent.args for claude-code, codex, copilot, and opencode no longer include bypass flags; they are now only injected by buildAgentArgs when permissionMode === 'full' or yoloMode === true.
  • The three primary renderer spawn paths (useInputProcessing, agentStore, useRemoteHandlers) do not forward permissionMode (or yoloMode) to the IPC call, so agents in "Full Access" mode — including all existing tabs where permissionMode is undefined — will spawn without the bypass flags they previously always received.
  • cue-spawn-builder.ts and context-groomer.ts were correctly updated to pass permissionMode explicitly.

Confidence Score: 3/5

Merging as-is would silently remove bypass flags from all agent spawns in the default Full Access mode — users would encounter unexpected permission prompts from their agents.

The agent definitions correctly move bypass flags to fullAccessArgs, and the IPC handler and buildAgentArgs are wired to inject them when permissionMode is set. However, the three renderer spawn paths that handle the vast majority of user interactions — interactive input, queued items, and remote commands — do not forward permissionMode or yoloMode. Because these paths also no longer receive bypass flags via agent.args, every spawn on a default (or newly set Full Access) tab will run without the permissions the UI promises.

src/renderer/hooks/input/useInputProcessing.ts, src/renderer/stores/agentStore.ts, src/renderer/hooks/remote/useRemoteHandlers.ts — all three spawn calls need permissionMode forwarded.

Important Files Changed

Filename Overview
src/renderer/hooks/input/useInputProcessing.ts Updates isReadOnly derivation to include permissionMode === 'readonly', but the spawn call does not forward permissionMode or yoloMode, so agents in Full Access mode spawn without any bypass flags — a regression from pre-PR behavior.
src/renderer/stores/agentStore.ts Same missing permissionMode forwarding; queued items spawned via the agent store queue also run without bypass flags in Full Access mode.
src/renderer/hooks/remote/useRemoteHandlers.ts Third spawn path that does not forward permissionMode; remote AI commands from external triggers also miss full-access flag injection.
src/main/ipc/handlers/process.ts Correctly wires permissionMode through buildAgentArgs and applies fullAccessEnvOverrides, but has an inconsistent isFullAccess guard for env-var overrides vs. the arg-injection path in agent-args.ts.
src/main/agents/definitions.ts Correctly moves --dangerously-skip-permissions and equivalent flags to fullAccessArgs; opencode defaultEnvVars and fullAccessEnvOverrides are well-separated.
src/main/utils/agent-args.ts Adds permissionMode branching to buildAgentArgs; correctly gives permissionMode precedence over legacy yoloMode/readOnlyMode booleans.
src/renderer/components/InputArea/components/ToolbarControls.tsx 3-way cycle logic and styling are correct; isReadOnlyMode prop is still declared in the interface but is unused after the refactor.
src/shared/agentMetadata.ts New getPermissionModeLabel/getPermissionModeTooltip helpers correctly delegate to existing readonly helpers for the readonly case, preserving agent-specific labels.
src/main/cue/cue-spawn-builder.ts Correctly adds permissionMode: 'full' alongside the legacy yoloMode: true; cue spawns will continue to receive bypass flags.
src/renderer/utils/agentArgs.ts Adds --allow-all (Copilot CLI) to KNOWN_YOLO_FLAGS so it is filtered in read-only mode, consistent with the existing set.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[User clicks toolbar button] --> B[ToolbarControls cycles permissionMode on activeTab]
    B --> C{tab.permissionMode}

    subgraph spawn["Spawn paths (missing permissionMode forwarding)"]
        D[useInputProcessing] -->|readOnlyMode only| IPC
        E[agentStore queue] -->|readOnlyMode only| IPC
        F[useRemoteHandlers] -->|readOnlyMode only| IPC
    end

    subgraph correct["Correctly updated paths"]
        G[cue-spawn-builder] -->|permissionMode: 'full'| IPC
        H[context-groomer] -->|permissionMode: 'standard'| IPC
    end

    C -->|'full' or undefined| D
    C -->|'standard'| D
    C -->|'readonly'| D

    IPC[IPC process handler] --> J[buildAgentArgs]
    J --> K{isFullAccess?}
    K -->|permissionMode=undefined, yoloMode=undefined → false| L[No fullAccessArgs added]
    K -->|permissionMode='full' → true| M[fullAccessArgs added]

    style L fill:#ffcccc
    style spawn fill:#fff3cc
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A[User clicks toolbar button] --> B[ToolbarControls cycles permissionMode on activeTab]
    B --> C{tab.permissionMode}

    subgraph spawn["Spawn paths (missing permissionMode forwarding)"]
        D[useInputProcessing] -->|readOnlyMode only| IPC
        E[agentStore queue] -->|readOnlyMode only| IPC
        F[useRemoteHandlers] -->|readOnlyMode only| IPC
    end

    subgraph correct["Correctly updated paths"]
        G[cue-spawn-builder] -->|permissionMode: 'full'| IPC
        H[context-groomer] -->|permissionMode: 'standard'| IPC
    end

    C -->|'full' or undefined| D
    C -->|'standard'| D
    C -->|'readonly'| D

    IPC[IPC process handler] --> J[buildAgentArgs]
    J --> K{isFullAccess?}
    K -->|permissionMode=undefined, yoloMode=undefined → false| L[No fullAccessArgs added]
    K -->|permissionMode='full' → true| M[fullAccessArgs added]

    style L fill:#ffcccc
    style spawn fill:#fff3cc
Loading

Comments Outside Diff (1)

  1. src/renderer/hooks/input/useInputProcessing.ts, line 1058-1166 (link)

    P1 permissionMode never forwarded to the spawn call — "Full Access" silently becomes "Standard"

    The PR moves --dangerously-skip-permissions (and the equivalent flags for every other agent) out of agent.args and into agent.fullAccessArgs, which buildAgentArgs adds only when isFullAccess is true. isFullAccess is true only when permissionMode === 'full' or yoloMode === true (legacy path). But the window.maestro.process.spawn call at the end of this block passes neither field — only readOnlyMode: isReadOnly. So config.permissionMode and config.yoloMode are both undefined inside the IPC handler, isFullAccess is never true, and agents that previously ran with bypass flags (claude-code: --dangerously-skip-permissions; codex: --dangerously-bypass-approvals-and-sandbox; etc.) no longer receive them. Every new or existing tab whose permissionMode is undefined shows "Full Access" in the toolbar but spawns without any permission bypass.

    The same omission is present in agentStore.ts (~line 423) and useRemoteHandlers.ts (~line 465). The fix is to forward permissionMode in all three spawn calls, e.g. permissionMode: freshActiveTab?.permissionMode ?? (freshActiveTab?.readOnlyMode ? 'readonly' : 'full').

Reviews (1): Last reviewed commit: "feat(agents): replace yolo mode with 3-w..." | Re-trigger Greptile

Comment thread src/main/ipc/handlers/process.ts Outdated
};
}
// In full-access mode, apply agent-specific env var overrides for full permissions
const isFullAccess = config.permissionMode === 'full' || config.yoloMode === true;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Inconsistent isFullAccess guard for env-var overrides vs. arg injection

buildAgentArgs only treats yoloMode: true as full-access when permissionMode is undefined — an explicit permissionMode: 'standard' suppresses it (see the test "permissionMode standard suppresses bypass args even when yoloMode: true is also passed"). But here config.yoloMode === true always wins regardless of permissionMode. Passing permissionMode: 'standard' + yoloMode: true therefore skips bypass flags (args path, correct) yet still applies fullAccessEnvOverrides (env-var path, wrong). The guard should be config.permissionMode === 'full' || (config.permissionMode === undefined && config.yoloMode === true) to stay consistent.

theme: Theme;
isTerminalMode: boolean;
isReadOnlyMode: boolean;
isReadOnlyMode?: boolean;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 isReadOnlyMode prop is declared but never consumed

The prop was removed from the destructure list but is still present in ToolbarControlsProps. Callers (e.g. MainPanelContent) still pass it, but the component now derives the display state from activeTab?.permissionMode directly. Leaving the dead prop in the interface creates confusion for future maintainers about where the control's source of truth lives.

Suggested change
isReadOnlyMode?: boolean;
// isReadOnlyMode removed — component now reads permissionMode directly from activeTab

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/main/ipc/handlers/process.ts (1)

461-477: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Match env override precedence to buildAgentArgs.

permissionMode is authoritative for args, but env overrides still read legacy booleans directly. A stale yoloMode: true can apply full-access env overrides under explicit standard/readonly, and explicit readonly can miss readOnlyEnvOverrides.

🐛 Proposed fix
 	// In read-only mode, apply agent-specific env var overrides to strip
 	// blanket permission grants (e.g., OpenCode's "*":"allow" YOLO config)
 	let effectiveCustomEnvVars = configResolution.effectiveCustomEnvVars;
-	if (config.readOnlyMode && agent?.readOnlyEnvOverrides) {
+	const hasExplicitPermissionMode = config.permissionMode !== undefined;
+	const isReadOnly =
+		config.permissionMode === 'readonly' ||
+		(!hasExplicitPermissionMode && config.readOnlyMode === true);
+	const isFullAccess =
+		config.permissionMode === 'full' ||
+		(!hasExplicitPermissionMode && config.yoloMode === true);
+
+	if (isReadOnly && agent?.readOnlyEnvOverrides) {
 		effectiveCustomEnvVars = {
 			...(effectiveCustomEnvVars || {}),
 			...agent.readOnlyEnvOverrides,
 		};
 	}
 	// In full-access mode, apply agent-specific env var overrides for full permissions
-	const isFullAccess = config.permissionMode === 'full' || config.yoloMode === true;
-	if (isFullAccess && (agent as any)?.fullAccessEnvOverrides) {
+	if (isFullAccess && agent?.fullAccessEnvOverrides) {
 		effectiveCustomEnvVars = {
 			...(effectiveCustomEnvVars || {}),
-			...(agent as any).fullAccessEnvOverrides,
+			...agent.fullAccessEnvOverrides,
 		};
 	}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/ipc/handlers/process.ts` around lines 461 - 477, Match the env
override precedence in process IPC handling to the same authority rules used by
buildAgentArgs. In the env merge logic around effectiveCustomEnvVars, stop using
legacy yoloMode/readOnlyMode booleans directly and instead derive behavior from
permissionMode first, so explicit standard/readonly/full-access settings win
consistently. Update the branches that apply agent.readOnlyEnvOverrides and
agent.fullAccessEnvOverrides to use the same permission-mode checks and fallback
ordering as buildAgentArgs, preventing stale flags from overriding the current
permission mode.
src/main/cue/cue-spawn-builder.ts (1)

99-104: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

permissionMode: 'full' is incomplete here.

This only upgrades the argv path. Cue still sanitizes configResolution.effectiveCustomEnvVars without merging agentDef.fullAccessEnvOverrides, so env-driven agents like OpenCode keep their standard permission config during Cue runs. process:spawn overlays those full-access env overrides, so this path now diverges from the advertised “same pipeline” behavior.

Suggested fix
 	const configResolution = applyAgentConfigOverrides(agentConfig, finalArgs, {
 		agentConfigValues: (agentConfigValues ?? {}) as Record<string, any>,
 		sessionCustomModel: customModel,
 		sessionCustomEffort: customEffort,
 		sessionCustomArgs: customArgs,
 		sessionCustomEnvVars: customEnvVars,
 	});
 	finalArgs = configResolution.args;
+	let envVarsForSpawn = configResolution.effectiveCustomEnvVars;
+	if (agentDef.fullAccessEnvOverrides) {
+		envVarsForSpawn = {
+			...(envVarsForSpawn || {}),
+			...agentDef.fullAccessEnvOverrides,
+		};
+	}
 	// Sanitize custom env vars BEFORE they reach the spawn environment. This
 	// drops blocklisted names (PATH, HOME, USER, SHELL, LD_PRELOAD,
 	// DYLD_INSERT_LIBRARIES, NODE_OPTIONS) and any name that does not match the
 	// POSIX identifier regex. Keeping this in the spawn-builder means SSH
 	// wrapping below inherits the sanitized map automatically via
 	// `sshWrapConfig.customEnvVars`.
 	const sanitizedResult = sanitizeCustomEnvVars(
-		configResolution.effectiveCustomEnvVars,
+		envVarsForSpawn,
 		config.onLog
 	);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/cue/cue-spawn-builder.ts` around lines 99 - 104, The Cue spawn path
in cue-spawn-builder.ts is only passing permissionMode: 'full' through
buildAgentArgs, but it still drops agentDef.fullAccessEnvOverrides when
preparing env vars. Update the Cue pipeline to merge those full-access env
overrides into configResolution.effectiveCustomEnvVars the same way
process:spawn does, so agents like OpenCode get the same permissions in Cue
runs; use the existing buildAgentArgs and agentDef.fullAccessEnvOverrides
symbols to locate the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/main/agents/definitions.ts`:
- Around line 376-378: Cue’s full-access spawn path is not applying the new
full-access environment overrides, so `permissionMode: 'full'` still uses the
standard env. Update the Cue builder in `cue-spawn-builder.ts` to merge
`fullAccessEnvOverrides` from the definitions into the spawned env when full
access is requested, rather than only sanitizing
`configResolution.effectiveCustomEnvVars`. Use the existing
`fullAccessEnvOverrides` symbol from `definitions.ts` and the Cue spawn builder
logic that sets `permissionMode: 'full'` to ensure the full-access env is
actually used.

In `@src/renderer/components/InputArea/components/ToolbarControls.tsx`:
- Around line 81-83: The derived pill state in ToolbarControls is missing the
legacy yoloMode fallback, so restored tabs with unset permissionMode can resolve
to the wrong mode. Update the currentPermissionMode calculation to account for
the legacy session state alongside activeTab.readOnlyMode, using the existing
activeTab/session values so the pill resolves to standard when yoloMode is false
and readOnlyMode is false. Keep the logic localized to ToolbarControls and
preserve the current fallback order for permissionMode first, then legacy state.

In `@src/renderer/hooks/input/useInputProcessing.ts`:
- Around line 1058-1061: The spawn path in useInputProcessing.ts is only passing
readOnlyMode into window.maestro.process.spawn(...), so permissionMode is not
preserved for batch sends. Update the spawn payload in the same flow that
computes isReadOnly to also include freshActiveTab?.permissionMode (or an
equivalent explicit flag) and wire it through the spawn call so Full Access tabs
can reach the new full-access arg/env branch instead of collapsing into the
standard path.

In `@src/renderer/hooks/remote/useRemoteHandlers.ts`:
- Around line 415-416: The remote spawn path in useRemoteHandlers is still
collapsing targetTab.permissionMode into isReadOnly and only forwarding
readOnlyMode, so full vs standard tabs lose their distinction. Update the
spawn/config assembly in this handler to include permissionMode explicitly
alongside readOnlyMode, and make sure the remote agent launch logic uses the
permissionMode value when dispatching web/mobile commands rather than deriving
everything from the boolean.

In `@src/renderer/stores/agentStore.ts`:
- Around line 372-375: Queued sends are still dropping the non-readonly
permission state because the enqueue/dequeue path only persists readOnlyMode.
Update the agentStore flow around isReadOnly and the subsequent spawn payload so
it carries targetTab.permissionMode as well, not just a boolean readonly flag.
Then, when replaying queued work, use the stored permissionMode to restore
full-access behavior for tabs that were originally full.

---

Outside diff comments:
In `@src/main/cue/cue-spawn-builder.ts`:
- Around line 99-104: The Cue spawn path in cue-spawn-builder.ts is only passing
permissionMode: 'full' through buildAgentArgs, but it still drops
agentDef.fullAccessEnvOverrides when preparing env vars. Update the Cue pipeline
to merge those full-access env overrides into
configResolution.effectiveCustomEnvVars the same way process:spawn does, so
agents like OpenCode get the same permissions in Cue runs; use the existing
buildAgentArgs and agentDef.fullAccessEnvOverrides symbols to locate the change.

In `@src/main/ipc/handlers/process.ts`:
- Around line 461-477: Match the env override precedence in process IPC handling
to the same authority rules used by buildAgentArgs. In the env merge logic
around effectiveCustomEnvVars, stop using legacy yoloMode/readOnlyMode booleans
directly and instead derive behavior from permissionMode first, so explicit
standard/readonly/full-access settings win consistently. Update the branches
that apply agent.readOnlyEnvOverrides and agent.fullAccessEnvOverrides to use
the same permission-mode checks and fallback ordering as buildAgentArgs,
preventing stale flags from overriding the current permission mode.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: e52ec763-bae3-4732-8cd3-7a2366fe61b0

📥 Commits

Reviewing files that changed from the base of the PR and between bee94d0 and eeec799.

📒 Files selected for processing (27)
  • src/__tests__/main/agents/definitions.test.ts
  • src/__tests__/main/agents/detector.test.ts
  • src/__tests__/main/cue/cue-spawn-builder.test.ts
  • src/__tests__/main/utils/agent-args.test.ts
  • src/__tests__/main/utils/context-groomer.test.ts
  • src/__tests__/renderer/components/InputArea.test.tsx
  • src/__tests__/renderer/components/InputArea/components/ToolbarControls.test.tsx
  • src/__tests__/shared/agentMetadata.test.ts
  • src/main/agents/definitions.ts
  • src/main/cue/cue-spawn-builder.ts
  • src/main/ipc/handlers/process.ts
  • src/main/preload/process.ts
  • src/main/utils/agent-args.ts
  • src/main/utils/context-groomer.ts
  • src/renderer/components/InputArea/components/ToolbarControls.tsx
  • src/renderer/components/MainPanel/MainPanelContent.tsx
  • src/renderer/components/WelcomeContent.tsx
  • src/renderer/components/Wizard/screens/DirectorySelectionScreen/components/DirectorySelectionHeader.tsx
  • src/renderer/global.d.ts
  • src/renderer/hooks/input/useInputProcessing.ts
  • src/renderer/hooks/remote/useRemoteHandlers.ts
  • src/renderer/stores/agentStore.ts
  • src/renderer/types/index.ts
  • src/renderer/utils/agentArgs.ts
  • src/renderer/utils/sessionHelpers.ts
  • src/shared/agentMetadata.ts
  • src/shared/types.ts

Comment thread src/main/agents/definitions.ts
Comment on lines +81 to +83
const activeTab = session.aiTabs?.find((t) => t.id === session.activeTabId);
const currentPermissionMode: 'full' | 'standard' | 'readonly' =
activeTab?.permissionMode ?? (activeTab?.readOnlyMode ? 'readonly' : 'full');

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Include the legacy yoloMode fallback in the derived pill state.

This only falls back to readOnlyMode. For restored tabs where permissionMode is still unset and legacy state is { yoloMode: false, readOnlyMode: false }, the toolbar will render Full Access even though the PR contract says that state should resolve to standard. That leaves the pill out of sync and makes the next click cycle from the wrong mode.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/renderer/components/InputArea/components/ToolbarControls.tsx` around
lines 81 - 83, The derived pill state in ToolbarControls is missing the legacy
yoloMode fallback, so restored tabs with unset permissionMode can resolve to the
wrong mode. Update the currentPermissionMode calculation to account for the
legacy session state alongside activeTab.readOnlyMode, using the existing
activeTab/session values so the pill resolves to standard when yoloMode is false
and readOnlyMode is false. Keep the logic localized to ToolbarControls and
preserve the current fallback order for permissionMode first, then legacy state.

Comment thread src/renderer/hooks/input/useInputProcessing.ts
Comment thread src/renderer/hooks/remote/useRemoteHandlers.ts
Comment thread src/renderer/stores/agentStore.ts

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: eeec799dac

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

'stream-json',
'--dangerously-skip-permissions',
],
args: ['--print', '--verbose', '--output-format', 'stream-json'],

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve full access for existing Claude spawn paths

This removes Claude's bypass flag from the default args, but several non-mode-aware spawn paths still do not pass permissionMode or yoloMode. For example Auto Run still sends only readOnlyMode: false in src/renderer/hooks/agent/useAgentExecution.ts:572, and the normal input path only forwards readOnlyMode at src/renderer/hooks/input/useInputProcessing.ts:1151, so buildAgentArgs() never appends fullAccessArgs. Default Full Access Claude runs now start without --dangerously-skip-permissions, which can stall or deny tool calls in noninteractive runs.

Useful? React with 👍 / 👎.

Comment on lines +128 to 129
if (!isReadOnly) {
finalArgs = [...finalArgs, ...agent.batchModeArgs];

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Do not add bypass batch args in Standard mode

When a caller explicitly selects permissionMode: 'standard', isReadOnly is false here, so the agent's batchModeArgs are still appended. Several definitions put the bypass itself in batchModeArgs (--dangerously-bypass-approvals-and-sandbox, --skip-permissions-unsafe, --allow-all), so Standard mode for Codex, Factory Droid, and Copilot-CLI still grants full permissions instead of using the provider's default model.

Useful? React with 👍 / 👎.

readOnlyMode,
modelId: undefined,
yoloMode: false,
permissionMode: 'standard' as const,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Respect readOnlyMode when grooming context

Passing an explicit permissionMode: 'standard' makes buildAgentArgs() ignore the readOnlyMode boolean above, because permissionMode takes precedence. Callers such as group chat and Director's Notes summaries pass readOnlyMode: true for read-only grooming, but after this change they no longer get readOnlyArgs like Claude plan mode or Codex read-only sandbox.

Useful? React with 👍 / 👎.

Comment on lines 103 to +104
yoloMode: true, // Cue runs always use YOLO mode like Auto Run
permissionMode: 'full' as const,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Apply full access env overrides for Cue runs

Cue marks its runs as full access here, but the builder only carries configResolution.effectiveCustomEnvVars into the spawn and never layers agentDef.fullAccessEnvOverrides. After OpenCode's default env was changed to the Standard config, Cue OpenCode runs no longer receive the full-access OPENCODE_CONFIG_CONTENT, so unattended Cue tasks can be denied or hang on permissions despite the explicit full mode.

Useful? React with 👍 / 👎.

Comment on lines +216 to +217
permissionMode: nextMode,
readOnlyMode: nextMode === 'readonly',

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep legacy read-only toggles in sync

Once the toolbar writes permissionMode, the other read-only entry points still only flip readOnlyMode (keyboard shortcut, Quick Actions, Prompt Composer, and tab store). If a user cycles the toolbar to Readonly and then uses one of those controls to turn it off, this field stays readonly, so later sends still run as read-only and the toolbar continues to show Readonly despite readOnlyMode being false.

Useful? React with 👍 / 👎.

Comment on lines +378 to 380
fullAccessEnvOverrides: {
OPENCODE_CONFIG_CONTENT:
'{"permission":{"*":"allow","external_directory":"allow","question":"deny"},"tools":{"question":false}}',

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Thread full access env through CLI sends

This new full-access override is only applied in the desktop process:spawn handler, while maestro-cli send still layers defaultEnvVars, batchModeEnvVars, user vars, and read-only overrides only. Since OpenCode's default env is now the Standard config, default write-mode CLI sends with OpenCode no longer get the permission:{"*":"allow","external_directory":"allow"} config and can be denied or hang in unattended runs.

Useful? React with 👍 / 👎.

readOnlyMode: config.readOnlyMode,
modelId: config.modelId,
yoloMode: config.yoloMode,
permissionMode: config.permissionMode,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Apply read-only env overrides for permissionMode

Forwarding permissionMode here only changes argument selection; the env override block below still checks the legacy config.readOnlyMode boolean. A caller using the new API with permissionMode: 'readonly' and no legacy flag gets read-only CLI args but misses readOnlyEnvOverrides, so OpenCode can keep the Standard OPENCODE_CONFIG_CONTENT instead of the no-prompt read-only config.

Useful? React with 👍 / 👎.

Comment thread src/main/ipc/handlers/process.ts Outdated
Comment on lines +473 to +475
effectiveCustomEnvVars = {
...(effectiveCustomEnvVars || {}),
...(agent as any).fullAccessEnvOverrides,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve custom env vars in full access mode

These full-access overrides are layered after effectiveCustomEnvVars, which already contains session and agent custom env vars. In Full Access OpenCode, a user-provided OPENCODE_CONFIG_CONTENT is overwritten by Maestro's blanket config, so users cannot customize or narrow the permission config even though custom env vars are supposed to override agent defaults.

Useful? React with 👍 / 👎.

@pedramamini

Copy link
Copy Markdown
Collaborator

Thanks for this, @athal7 - the 3-way permission model is a genuinely nice cleanup over the binary yolo/read-only toggle, and the buildAgentArgs precedence logic plus the added test coverage are solid.

Before we merge, there's one blocking regression that both Greptile and CodeRabbit flagged and that I've confirmed against the code:

permissionMode is never forwarded to process.spawn in the three main renderer spawn paths, so "Full Access" silently loses its bypass flags.

This PR moves the bypass flags (--dangerously-skip-permissions, --dangerously-bypass-approvals-and-sandbox, etc.) out of agent.args and into agent.fullAccessArgs, which buildAgentArgs only injects when isFullAccess is true (permissionMode === 'full', or legacy yoloMode === true). But these three spawn calls only pass readOnlyMode: isReadOnly and never forward permissionMode (or yoloMode):

  • src/renderer/hooks/input/useInputProcessing.ts (spawn ~L1140, payload ~L1151)
  • src/renderer/stores/agentStore.ts (spawn ~L423 and ~L521)
  • src/renderer/hooks/remote/useRemoteHandlers.ts (spawn ~L509)

So inside the IPC handler both config.permissionMode and config.yoloMode are undefined, isFullAccess is never true, and every tab in Full Access mode, including all existing tabs where permissionMode is still undefined (the toolbar renders that as "Full Access"), spawns without the bypass flags it received before this PR. Users would hit unexpected permission prompts in what the UI calls Full Access.

The fix is to forward permissionMode in all three spawn payloads, e.g.:

permissionMode: freshActiveTab?.permissionMode ?? (freshActiveTab?.readOnlyMode ? 'readonly' : 'full'),

A few smaller items worth addressing while you're in here (non-blocking, your call):

  • src/main/ipc/handlers/process.ts (~L461-477): the env-override branch derives full-access / read-only from the legacy yoloMode / readOnlyMode booleans directly rather than giving permissionMode precedence the way buildAgentArgs does, so a stale yoloMode: true could apply full-access env overrides under an explicit standard / readonly. Worth aligning the precedence.
  • src/main/cue/cue-spawn-builder.ts: the Cue path passes permissionMode: 'full' for args but does not merge agentDef.fullAccessEnvOverrides into the spawn env the way process:spawn does, so env-driven agents (e.g. OpenCode) keep their standard env during Cue runs.
  • src/renderer/components/InputArea/components/ToolbarControls.tsx: the isReadOnlyMode prop looks unused after the refactor and is safe to drop.

No merge conflicts on this branch, so once the spawn forwarding is in place this should be good to go. Thanks again for the contribution!

Align the full-access env-override guard in the process IPC handler
with the args-injection guard in agent-args.ts, so an explicit
permissionMode: 'standard' correctly suppresses fullAccessEnvOverrides
even when a legacy yoloMode: true is also passed. Also drop the now-
dead isReadOnlyMode/onToggleTabReadOnlyMode props from
ToolbarControlsProps and their call site now that the toggle reads
permissionMode directly from the active tab.

Co-Authored-By: anthropic/claude-sonnet-4-6 <noreply@opencode.ai>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3c469ad993

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines 373 to +374
defaultEnvVars: {
OPENCODE_CONFIG_CONTENT: '{"permission":{"question":"deny"},"tools":{"question":false}}',

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve desktop full access for OpenCode sends

For desktop sends where the user leaves the new toolbar at its default Full Access state, the renderer never sends permissionMode: 'full' or yoloMode to process:spawn (checked normal input at src/renderer/hooks/input/useInputProcessing.ts:1151, queued sends at src/renderer/stores/agentStore.ts:433, and remote sends at src/renderer/hooks/remote/useRemoteHandlers.ts:519). After this default was changed to the Standard OpenCode config, those spawns only receive {"permission":{"question":"deny"}}, so fullAccessEnvOverrides is not layered and OpenCode can deny or block write/external-directory actions despite the UI saying Full Access. Please either keep the full-access env as the default until callers pass the mode, or thread the tab permission mode through these spawn calls.

Useful? React with 👍 / 👎.

// The question tool waits for stdin input which hangs batch mode.
// Users can override by setting customEnvVars in agent config.
defaultEnvVars: {
OPENCODE_CONFIG_CONTENT: '{"permission":{"question":"deny"},"tools":{"question":false}}',

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Apply read-only env overrides to direct read-only spawns

After this line makes OpenCode's default env the Standard config, direct read-only spawns that bypass process:spawn no longer receive readOnlyEnvOverrides. For example, tab naming builds read-only args in src/main/ipc/handlers/tabNaming.ts:155-160 but then passes only configResolution.effectiveCustomEnvVars at src/main/ipc/handlers/tabNaming.ts:195-198, so OpenCode tab naming runs with --agent plan plus {"permission":{"question":"deny"}} instead of the blanket allow config that the read-only override comments say is needed to avoid permission prompts. This can make automatic naming fail or hang for OpenCode tabs.

Useful? React with 👍 / 👎.

Align env-override precedence in process.ts with the same
permissionMode-first, legacy-boolean-fallback derivation already used
by the arg builder, so a stale yoloMode/readOnlyMode can no longer win
over an explicit permissionMode. Merge agentDef.fullAccessEnvOverrides
into Cue's spawn env so env-driven full-access agents (e.g. OpenCode)
actually get full permissions during Cue runs, not just agents whose
bypass is argv-flag-based. Thread permissionMode through the four
remaining renderer spawn call sites (AutoRun/batch send, remote/web
command dispatch, and both agentStore spawn paths) that previously
only sent readOnlyMode, so full-access tabs no longer silently regress
to standard mode when dispatched through these paths.

Co-Authored-By: anthropic/claude-sonnet-4-6 <noreply@opencode.ai>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/renderer/hooks/input/useInputProcessing.ts (1)

1058-1061: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Forward the effective permission mode when read-only is forced.

Line 1058 correctly makes Auto Run/no-worktree and legacy read-only tabs force isReadOnly, but Line 1152 still sends the tab’s raw permissionMode. If that raw value is full or standard, the main process can treat the spawn as writable despite readOnlyMode: true. Derive the payload mode from isReadOnly.

🐛 Proposed fix
 const isReadOnly =
 	isAutoRunReadOnly ||
 	freshActiveTab?.readOnlyMode === true ||
 	freshActiveTab?.permissionMode === 'readonly';
+const effectivePermissionMode = isReadOnly ? 'readonly' : freshActiveTab?.permissionMode;
 readOnlyMode: isReadOnly,
-permissionMode: freshActiveTab?.permissionMode,
+permissionMode: effectivePermissionMode,

Also applies to: 1151-1152

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/renderer/hooks/input/useInputProcessing.ts` around lines 1058 - 1061, The
spawn payload in useInputProcessing should forward the effective permission
mode, not the tab’s raw permissionMode, because read-only can be forced by
isAutoRunReadOnly or readOnlyMode. Update the logic around the isReadOnly
calculation and the payload construction so the mode sent to the main process is
derived from isReadOnly (read-only when true, otherwise the existing tab mode).
Use the existing freshActiveTab, isReadOnly, and permissionMode handling in
useInputProcessing to locate the fix.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/renderer/hooks/input/useInputProcessing.ts`:
- Around line 1058-1061: The spawn payload in useInputProcessing should forward
the effective permission mode, not the tab’s raw permissionMode, because
read-only can be forced by isAutoRunReadOnly or readOnlyMode. Update the logic
around the isReadOnly calculation and the payload construction so the mode sent
to the main process is derived from isReadOnly (read-only when true, otherwise
the existing tab mode). Use the existing freshActiveTab, isReadOnly, and
permissionMode handling in useInputProcessing to locate the fix.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 4f33eb28-0a8f-49dc-8d0a-ede59696f698

📥 Commits

Reviewing files that changed from the base of the PR and between 3c469ad and 3c84acb.

📒 Files selected for processing (6)
  • src/__tests__/main/cue/cue-spawn-builder.test.ts
  • src/main/cue/cue-spawn-builder.ts
  • src/main/ipc/handlers/process.ts
  • src/renderer/hooks/input/useInputProcessing.ts
  • src/renderer/hooks/remote/useRemoteHandlers.ts
  • src/renderer/stores/agentStore.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/renderer/hooks/remote/useRemoteHandlers.ts
  • src/renderer/stores/agentStore.ts
  • src/main/ipc/handlers/process.ts

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3c84acb853

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/renderer/stores/agentStore.ts Outdated
appendSystemPrompt,
agentSessionId: tabAgentSessionId ?? undefined,
readOnlyMode: isReadOnly,
permissionMode: targetTab.permissionMode,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Snapshot permission mode for queued work

When processing queued messages, this reads targetTab.permissionMode at dispatch time, but QueuedItem only snapshots the legacy readOnlyMode when the item is enqueued. If a user queues a prompt while the tab is in Standard mode and then switches the tab back to Full Access before the current run exits, the queued prompt is spawned with full bypass instead of the Standard mode selected for that queued work. Please store permissionMode on queued items and pass that here, falling back to the tab only for legacy queue entries; the slash-command spawn path below has the same issue.

Useful? React with 👍 / 👎.

The renderer spawn call sites sent the tab's raw permissionMode
alongside readOnlyMode, but readOnlyMode can be forced to true by
conditions independent of the tab's own permissionMode field (Auto
Run without a worktree, a queued item's own readOnlyMode flag). That
produced an internally inconsistent spawn payload (readOnlyMode: true,
permissionMode: 'full') where the main process could honor the raw
permissionMode and treat the spawn as writable despite the forced
read-only intent.

Derive effectivePermissionMode as 'readonly' whenever the forced
isReadOnly is true, otherwise fall back to the tab's own
permissionMode, at all four renderer spawn call sites (AutoRun/batch
send, remote/web command dispatch, and both agentStore spawn paths).

Co-Authored-By: anthropic/claude-sonnet-4-6 <noreply@opencode.ai>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/__tests__/renderer/hooks/useInputProcessing.test.ts (1)

1412-1444: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider adding a complementary "full access preserved" test.

This test only covers the forced-readonly override path. Given the PR's core regression was permissionMode not being forwarded at all (losing Full Access bypass), a sibling test asserting spawnCall.permissionMode === 'full' when Auto Run is not forcing readonly would directly guard against regressing the original bug.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/__tests__/renderer/hooks/useInputProcessing.test.ts` around lines 1412 -
1444, Add a sibling test in useInputProcessing.test that covers the non-forced
path for useInputProcessing/processInput. The new test should create a
tab/session where Auto Run does not force readonly, then verify
window.maestro.process.spawn is called with permissionMode preserved as "full".
Reuse the existing helpers like createMockTab, createMockSession, createDeps,
and processInput so the test directly guards the forwarding behavior that
regressed.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/__tests__/renderer/hooks/useInputProcessing.test.ts`:
- Around line 1412-1444: Add a sibling test in useInputProcessing.test that
covers the non-forced path for useInputProcessing/processInput. The new test
should create a tab/session where Auto Run does not force readonly, then verify
window.maestro.process.spawn is called with permissionMode preserved as "full".
Reuse the existing helpers like createMockTab, createMockSession, createDeps,
and processInput so the test directly guards the forwarding behavior that
regressed.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b3e6c228-08c6-4c31-87e9-b6b74c21c378

📥 Commits

Reviewing files that changed from the base of the PR and between 3c84acb and ac3adcb.

📒 Files selected for processing (6)
  • src/__tests__/renderer/hooks/useInputProcessing.test.ts
  • src/__tests__/renderer/hooks/useRemoteHandlers.test.ts
  • src/__tests__/renderer/stores/agentStore.test.ts
  • src/renderer/hooks/input/useInputProcessing.ts
  • src/renderer/hooks/remote/useRemoteHandlers.ts
  • src/renderer/stores/agentStore.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/renderer/stores/agentStore.ts
  • src/renderer/hooks/remote/useRemoteHandlers.ts
  • src/renderer/hooks/input/useInputProcessing.ts

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ac3adcb28f

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

// env-only full-access agents silently run at standard permissions in Cue.
let envVarsForSpawn = configResolution.effectiveCustomEnvVars;
if (agentDef.fullAccessEnvOverrides) {
envVarsForSpawn = { ...(envVarsForSpawn || {}), ...agentDef.fullAccessEnvOverrides };

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve Cue custom env over full-access defaults

When a Cue run supplies customEnvVars with the same key as fullAccessEnvOverrides (for example an OpenCode OPENCODE_CONFIG_CONTENT that narrows or customizes permissions), configResolution.effectiveCustomEnvVars already contains the user value, but this spread overwrites it with Maestro's blanket full-access config before sanitizing and spawning. That makes Cue ignore the user's per-run env override; layer the full-access defaults before user/session env instead.

Useful? React with 👍 / 👎.

Add a sibling test to the forced-readonly effectivePermissionMode test:
asserts a tab with permissionMode 'full' sends permissionMode: 'full'
to the spawn config when Auto Run is not forcing read-only. Directly
guards against regressing the original bug this PR fixes (permissionMode
not forwarded at all, silently losing Full Access bypass).

Co-Authored-By: anthropic/claude-sonnet-4-6 <noreply@opencode.ai>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7852d02bb7

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

// The question tool waits for stdin input which hangs batch mode.
// Users can override by setting customEnvVars in agent config.
defaultEnvVars: {
OPENCODE_CONFIG_CONTENT: '{"permission":{"question":"deny"},"tools":{"question":false}}',

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Apply full access env to group chat participants

When an OpenCode group chat participant is run in write mode (readOnly is false), group-chat-router.ts builds args with only the legacy readOnlyMode flag and spawnGroupChatAgent.ts passes configResolution.effectiveCustomEnvVars directly, so fullAccessEnvOverrides is never layered. Since this default is now the Standard config rather than the allow-all config, OpenCode participants and recovery spawns run without the full read/write permissions promised by the group chat prompt and can deny or block file edits.

Useful? React with 👍 / 👎.

@jSydorowicz21

Copy link
Copy Markdown
Contributor

Hey @athal7 I'm going to have @pedramamini or @reachrazamair take a look at this one. If memory recalls correctly the reason why we use yolo mode is most clis don't expose a nice way to permission handle when spawning programatically instead of via TUI. That leaves us in a spot where if you hit something that's blocked and you want the agent to do it there's not a way to approve that. Please correct me if I'm wrong here guys

@athal7 athal7 marked this pull request as draft July 2, 2026 19:27
@athal7

athal7 commented Jul 2, 2026

Copy link
Copy Markdown
Author

this pr needs more work, putting back in draft while i work on it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants