Skip to content

feat: github.com/flanksource/sandbox-runtime with --sandbox flag - #41

Merged
moshloop merged 3 commits into
mainfrom
feat/sandbox-runtime
Jul 31, 2026
Merged

feat: github.com/flanksource/sandbox-runtime with --sandbox flag#41
moshloop merged 3 commits into
mainfrom
feat/sandbox-runtime

Conversation

@adityathebe

@adityathebe adityathebe commented Jul 31, 2026

Copy link
Copy Markdown
Member

Summary by CodeRabbit

  • New Features

    • Added optional sandboxing for local Claude, Codex, and Gemini CLI processes, with restricted network, filesystem, environment, and state access.
    • Added the --sandbox option and automatic CLI-mode enforcement.
    • Added runtime mode selection and validation across primary and fallback models.
  • Bug Fixes

    • Preserved explicitly selected runtime modes during model expansion and fallback resolution.
    • Improved validation and error reporting for incompatible modes and backends.
  • Chores

    • Updated installation to use Go’s standard install workflow with embedded version information.

Sandbox previously rewrote already-resolved models to CLI backends with a dedicated helper, duplicating registry behavior and making it appear that model identity changed.\n\nPass CLI mode into the existing resolver instead, apply it consistently to fallbacks and prompt overlays, and reject explicit API runtime contradictions.
Route --sandbox through the existing ModelFlags mode path while preserving mode during compact selector expansion and retaining WithMode as the shared model helper.

Consolidate repetitive resolver cases and replace weak wrapper assertions with exact policy, provider wiring, and lifecycle cleanup coverage.
@coderabbitai

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

Changes

The pull request adds sandboxed execution for Claude, Codex, and Gemini CLI providers. It adds runtime-mode resolution, CLI-mode validation, sandbox configuration propagation, cleanup handling, and tests. The install task now uses metadata-aware go install.

Sandboxed CLI runtime

Layer / File(s) Summary
Runtime mode resolution
pkg/api/registry/model.go, pkg/api/registry/model_compact.go, pkg/api/registry/parse.go, pkg/aiflags/flags.go, pkg/cli/provider_defaults.go
Model expansion preserves explicit modes. Model.WithMode applies and validates modes for primary and fallback models.
CLI sandbox configuration
pkg/cli/ai.go, pkg/cli/ai_prompt_file.go, pkg/cli/prompt_source.go, pkg/cli/*_test.go
CLI options and prompt overlays parse runtime modes, enforce CLI mode for sandboxing, propagate sandbox state, and decode persisted flags.
Provider selection validation
pkg/api/runtime_config.go, pkg/api/runtime_registry.go, pkg/api/runtime_provider_ginkgo_test.go
Runtime configuration exposes sandbox state. Provider creation rejects sandbox requests for non-CLI backends.
Sandboxed CLI execution
pkg/ai/provider/*.go
CLI startup wraps supported commands with sandbox-runtime restrictions and closes sandbox resources after completion or startup failure. Tests cover provider propagation, restrictions, and cleanup.

Installation task

Layer / File(s) Summary
Direct Go installation
Taskfile.yaml
The install task removes INSTALL_DIR, embeds version metadata with linker flags, and runs go install directly.

Sequence Diagram(s)

sequenceDiagram
  participant AIProviderOptions
  participant RuntimeRegistry
  participant startCLIStream
  participant sandbox-runtime
  participant CLIProcess
  AIProviderOptions->>RuntimeRegistry: resolve sandbox configuration as CLI mode
  RuntimeRegistry->>startCLIStream: create CLI stream with sandbox enabled
  startCLIStream->>sandbox-runtime: configure and wrap provider command
  sandbox-runtime->>CLIProcess: start restricted Claude, Codex, or Gemini process
  CLIProcess-->>startCLIStream: stream process output
  startCLIStream-->>AIProviderOptions: return stream and sandbox cleanup
  AIProviderOptions->>sandbox-runtime: close sandbox after stream completion or startup failure
Loading

Suggested reviewers: moshloop

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 41.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the main change: adding sandbox-runtime support through the --sandbox flag.
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 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/sandbox-runtime
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch feat/sandbox-runtime

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.

@adityathebe
adityathebe marked this pull request as ready for review July 31, 2026 09:40

@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: 2

🧹 Nitpick comments (1)
pkg/ai/provider/claude_cli.go (1)

17-28: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Make NewClaudeCLI set sandbox at construction, like NewCodexCLI.

NewClaudeCLI(model string) does not accept ai.Config, so sandbox stays at its zero value unless a caller sets provider.sandbox = cfg.Sandbox afterward. pkg/ai/provider/init.go currently does this correctly for both BackendClaudeCLI and BackendGeminiCLI, but the pattern relies on every future caller remembering the follow-up assignment. NewCodexCLI(cfg ai.Config) avoids this by accepting the full config and setting sandbox: cfg.Sandbox directly.

Since Config.Sandbox is documented so "the flag cannot be silently ignored," align NewClaudeCLI (and NewGeminiCLI) with NewCodexCLI's single-step pattern to remove the two-step construction risk.

♻️ Proposed refactor for NewClaudeCLI
-func NewClaudeCLI(model string) *ClaudeCLI {
-	if strings.TrimSpace(model) == "" {
-		model = "opus"
-	}
-	model = ai.NormalizeModelForBackend(ai.BackendClaudeCLI, model)
-	return &ClaudeCLI{model: model}
-}
+func NewClaudeCLI(cfg ai.Config) *ClaudeCLI {
+	model := cfg.Model.Name
+	if strings.TrimSpace(model) == "" {
+		model = "opus"
+	}
+	model = ai.NormalizeModelForBackend(ai.BackendClaudeCLI, model)
+	return &ClaudeCLI{model: model, sandbox: cfg.Sandbox}
+}

This requires updating NewClaudeCLI call sites (pkg/ai/provider/init.go, pkg/ai/provider/cli_test.go) to pass ai.Config instead of a bare model string.

🤖 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 `@pkg/ai/provider/claude_cli.go` around lines 17 - 28, Update NewClaudeCLI to
accept ai.Config, derive and normalize the model from cfg, and initialize
sandbox from cfg.Sandbox like NewCodexCLI. Update its call sites in init.go and
cli_test.go to pass the full configuration, and apply the same constructor
pattern to NewGeminiCLI so sandbox is set during construction.
🤖 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 `@pkg/cli/ai_prompt_file.go`:
- Around line 106-111: Derive one effective sandbox value from both the request
option and saved configuration, then use it consistently in the mode-enforcement
block around requestedMode and when setting cfg.Sandbox. This must force
registry.ModeCLI whenever either sandbox source is enabled, while preserving the
existing validation for an explicitly incompatible --mode.

In `@pkg/cli/prompt_source.go`:
- Line 125: Update actionFlagsToOptions to assign the persisted f["mode"] flag
to o.Mode, alongside the existing Sandbox mapping, so prompt actions specifying
mode: cli reach overlayCLI unchanged.

---

Nitpick comments:
In `@pkg/ai/provider/claude_cli.go`:
- Around line 17-28: Update NewClaudeCLI to accept ai.Config, derive and
normalize the model from cfg, and initialize sandbox from cfg.Sandbox like
NewCodexCLI. Update its call sites in init.go and cli_test.go to pass the full
configuration, and apply the same constructor pattern to NewGeminiCLI so sandbox
is set during construction.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 9ff846c8-e4be-4231-9a1c-4ed15b95801a

📥 Commits

Reviewing files that changed from the base of the PR and between 23d2935 and 78f99f2.

📒 Files selected for processing (21)
  • Taskfile.yaml
  • pkg/ai/provider/claude_cli.go
  • pkg/ai/provider/cli.go
  • pkg/ai/provider/cli_test.go
  • pkg/ai/provider/codex_cli.go
  • pkg/ai/provider/gemini_cli.go
  • pkg/ai/provider/init.go
  • pkg/aiflags/flags.go
  • pkg/api/registry/model.go
  • pkg/api/registry/model_compact.go
  • pkg/api/registry/parse.go
  • pkg/api/runtime_config.go
  • pkg/api/runtime_provider_ginkgo_test.go
  • pkg/api/runtime_registry.go
  • pkg/cli/ai.go
  • pkg/cli/ai_prompt_file.go
  • pkg/cli/ai_prompt_file_test.go
  • pkg/cli/ai_test.go
  • pkg/cli/prompt_source.go
  • pkg/cli/prompt_source_test.go
  • pkg/cli/provider_defaults.go

Comment thread pkg/cli/ai_prompt_file.go
Comment on lines +106 to +111
if o.Sandbox {
if requestedMode != "" && requestedMode != registry.ModeCLI {
return base, baseCfg, fmt.Errorf("--sandbox requires CLI mode, but --mode is %q", requestedMode)
}
requestedMode = registry.ModeCLI
}

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

Apply CLI mode when any sandbox source is enabled.

baseCfg.Sandbox enables cfg.Sandbox at Line 190, but it does not enter the CLI-mode enforcement block. A saved sandbox configuration can therefore resolve an API or agent backend. The provider validation layer will reject that configuration.

Use one effective sandbox value for both mode enforcement and cfg.Sandbox.

Proposed fix
-	if o.Sandbox {
+	sandbox := o.Sandbox || baseCfg.Sandbox
+	if sandbox {
 		if requestedMode != "" && requestedMode != registry.ModeCLI {
 			return base, baseCfg, fmt.Errorf("--sandbox requires CLI mode, but --mode is %q", requestedMode)
 		}
 		requestedMode = registry.ModeCLI
 	}
@@
-	cfg.Sandbox = o.Sandbox || baseCfg.Sandbox
+	cfg.Sandbox = sandbox

Also applies to: 190-190

🤖 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 `@pkg/cli/ai_prompt_file.go` around lines 106 - 111, Derive one effective
sandbox value from both the request option and saved configuration, then use it
consistently in the mode-enforcement block around requestedMode and when setting
cfg.Sandbox. This must force registry.ModeCLI whenever either sandbox source is
enabled, while preserving the existing validation for an explicitly incompatible
--mode.

Comment thread pkg/cli/prompt_source.go
o.APIURL = f["api-url"]
o.NoCache = flagBool(f["no-cache"])
o.Budget = f["budget"]
o.Sandbox = flagBool(f["sandbox"])

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

Map the persisted mode action flag.

actionFlagsToOptions does not assign f["mode"] to o.Mode. As a result, a prompt action with mode: cli does not reach overlayCLI.

Proposed fix
 	o.Backend = f["backend"]
+	o.Mode = f["mode"]
 	o.APIKey = f["api-key"]
🤖 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 `@pkg/cli/prompt_source.go` at line 125, Update actionFlagsToOptions to assign
the persisted f["mode"] flag to o.Mode, alongside the existing Sandbox mapping,
so prompt actions specifying mode: cli reach overlayCLI unchanged.

@moshloop
moshloop merged commit 5e5fb10 into main Jul 31, 2026
12 checks passed
@moshloop
moshloop deleted the feat/sandbox-runtime branch July 31, 2026 10:25
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.

2 participants