Table of Contents generated with DocToc
Capability: capability:platform
Harness: Gemini CLI
Gemini CLI is an agent harness that runs Magpie‘s shared skills with repository instructions, an action guard, tool sandboxing, and per-action approval policies. The adapter is experimental: its Linux sandbox does not provide the Claude Code reference setup’s home-directory read isolation or domain allowlist. The integration follows the harness contract in add-a-harness and RFC-AI-0004.
| Magpie requirement | Gemini CLI implementation |
|---|---|
| Skill discovery | Gemini reads the canonical .agents/skills/magpie-*/SKILL.md links. The existing universal row in skills/setup/agents.md covers this path. |
| Repository instructions | The framework's GEMINI.md imports its AGENTS.md. |
| Tool bridges | Skills invoke the existing tools/* CLI adapters through shell calls, subject to the approval policy and sandbox grants below. Each adapter declares its own prerequisites. |
| Deterministic guard | Project .gemini/settings.json registers Magpie‘s agent_guard/__init__.py --gemini adapter for Gemini’s BeforeTool shell events. The adapter calls Magpie's dispatch() function to check the command. Adopters register the hook through the install lifecycle below. |
| Spec-loop | The gemini profile forwards the prompt, model, and output format. |
| Credential isolation | agent-iso gemini launches the CLI through the generic clean-environment wrapper, which filters inherited environment variables. |
| Filesystem and network | security.toolSandboxing: true enables Gemini's tool sandboxing. The shipped profile adds no extra writable directories or network grant. See Tool-sandboxing boundaries for the difference between native file tools and shell access. |
| Tool approval | Explicit policyPaths loads policies/magpie.toml: scoped reads are allowed, other shell calls and native edits require confirmation, and selected commands and credential paths are denied. MCP calls require confirmation. |
| MCP servers | Register the same server commands in Gemini's user settings; see Reuse framework MCP servers. No servers or credentials are installed by this profile. |
Install the Gemini extension through setup, or use the canonical .agents/skills/ links with a pinned snapshot. Both methods expose the same skill sources. The framework's GEMINI.md imports AGENTS.md; adopters retain their own project instructions alongside that context.
From the adopter repository root:
/memory show to inspect repository instructions and /skills list to check discovery.Use the magpie-list-skills skill. and review the activation request.Skill activation consent and tool approval are separate decisions. Skills use the existing tools/* adapters, whose READMEs declare their prerequisites.
Use Gemini CLI 0.59.0 or later. The validation baseline is 0.59.0 on Linux; later versions require verification before use. The tested Linux backend requires bwrap (bubblewrap), usable user namespaces, and ordinary shell utilities. Use the framework's sandbox primitive versions when installing bubblewrap. Python 3.11+ is required for profile linting and the existing action guard.
For guided setup, ask Gemini: Use the magpie-setup-isolated-setup-install skill. The skill follows this procedure and proposes changes before applying them. No adopter project manifest is needed to configure the harness itself.
Resolve the framework directory from the installation already in use:
| Installation | Framework directory and guard path |
|---|---|
| Gemini extension (default) | Use the installed Magpie path reported by gemini extensions list, or the resolved source of the active Magpie skill. Register the guard with that absolute path on this machine. |
| Pinned snapshot | Use the adopter's .apache-magpie/. Register the guard relative to ${GEMINI_PROJECT_DIR}/.apache-magpie/ so linked worktrees use their own snapshot symlink. |
| Framework checkout | Use the checkout root. Its committed settings already register the guard relative to ${GEMINI_PROJECT_DIR}/. |
Confirm that this directory contains .gemini/settings.json, .gemini/policies/magpie.toml, and tools/agent-guard/src/agent_guard/__init__.py. Do not add a snapshot alongside an installed extension or modify the installed framework sources. An extension provides skills and context; it does not automatically install the workspace profile. If native file tools cannot read shared framework resources outside the activated skill directory, use an approved shell read of the required files.
.gemini/policies/magpie.toml and merge the shipped general, security, and tools values into workspace .gemini/settings.json. Preserve unrelated keys, including nested settings and MCP configuration. Retain existing policyPaths and add the shipped paths once, including ~/.gemini/policies; review additional policies or sandbox grants that can change the effective baseline. Show edits to an existing magpie.toml before replacing it.magpie-agent-guard registration; preserve unrelated matchers and hooks, and propose correcting a stale or duplicate Magpie entry instead of appending another. Quote the path for the shell and encode the resulting command as JSON. For a standard extension installation, use a home-relative shell path such as "${HOME}/.gemini/extensions/magpie/tools/agent-guard/src/agent_guard/__init__.py" to avoid committing a username. Custom installation paths need a portability review before committing workspace settings.Use the resolved framework directory in these commands:
source "<framework>/tools/agent-isolation/agent-iso.sh" uv run --project "<framework>/tools/sandbox-lint" sandbox-lint --gemini .gemini
The committed settings are the profile's source of truth; avoid maintaining a second settings template. On repeat installation, leave matching values and hooks unchanged. The native editing policy protects .gemini/, so apply an approved configuration patch through a normal terminal or an approved shell call; do not disable the policy to bootstrap it. Start each session from the directory containing .gemini/, because the policy path is relative to the launch directory. Restart Gemini after changing settings, policies, or the extension.
The clean-environment wrapper strips inherited credentials and non-essential configuration variables. Use AGENT_ISO_ALLOW to pass only the variables needed by your selected authentication method:
| Method | Variables to pass through |
|---|---|
| Gemini API key from Google AI Studio | GEMINI_API_KEY |
| Vertex AI with Application Default Credentials (ADC) | GOOGLE_CLOUD_PROJECT GOOGLE_CLOUD_LOCATION; add GOOGLE_APPLICATION_CREDENTIALS for a custom credential-file path. |
| Vertex AI with a Google Cloud API key | GOOGLE_API_KEY GOOGLE_CLOUD_PROJECT GOOGLE_CLOUD_LOCATION |
| Sign in with Google | Usually none; pass GOOGLE_CLOUD_PROJECT if the account requires it. |
Configure authentication in a normal terminal first, then select the matching method in Gemini. For an AI Studio key already set in your shell:
AGENT_ISO_ALLOW=GEMINI_API_KEY agent-iso gemini --approval-mode default
For Vertex with ADC and project/location already set:
AGENT_ISO_ALLOW="GOOGLE_CLOUD_PROJECT GOOGLE_CLOUD_LOCATION" \ agent-iso gemini --approval-mode default
For Google sign-in without additional variables, use agent-iso gemini --approval-mode default. Naming a variable does not obtain credentials; a later wrapped session must pass the required variables again. Keep persistent credentials in the runtime's home-directory storage or your secret manager, never in a project .env file. Explicitly passed credentials are available to the CLI; environment redaction for tools is a separate runtime control.
security.toolSandboxing: true enables Gemini‘s tool sandboxing. On Linux, bubblewrap permits writes in the workspace and temporary areas; Magpie’s profile starts without tool network access or additional allowed paths. Gemini's --sandbox flag selects a separate full-process sandbox and is not needed for this profile. See the upstream sandbox guide.
Native file tools and shell commands have different read boundaries. Native file tools check paths against allowed workspace directories. The Linux backend mounts host files broadly read-only, so an approved shell command can read files outside the workspace that the backend has not masked. Magpie's credential-path policies deny matching native file-tool arguments; they do not prevent an approved shell from reading the same files. The upstream bubblewrap argument builder defines these mounts.
Tool approval authorizes an operation. Sandbox expansion separately grants network access or additional filesystem access when needed. Review the paths and duration of each grant: filesystem expansion can cover entire directories, and network expansion grants general network access rather than a domain allowlist. Existing session grants and ~/.gemini/policies/sandbox.toml can widen the baseline; disabling remembered tool approvals does not remove saved sandbox grants.
The shipped policy applies these decisions to model-requested tool calls in Default Mode:
| Requested action | Result |
|---|---|
| Ordinary native workspace read | Allow under Gemini's built-in read policy. |
Listed inspection commands, such as git status --short, git diff --stat, or gh pr view | Allow; network access may still require sandbox expansion. |
Other shell commands, including tests, interpreters, git push, PR creation, and raw gh api calls | Ask before execution. |
| Native file edits and MCP server tools | Ask for each call, including read-only MCP tools. |
Google web search (google_web_search) | Ask before each query is sent, including in Plan Mode; headless calls are refused. |
URL fetching (web_fetch) and MCP resource reads (read_mcp_resource) | Ask for each call, including in auto-edit and Plan Mode; headless calls are refused. |
Listed credential/export commands, such as gh auth token, curl, or cloud CLIs | Deny. |
Matching credential paths or .env files through native file/search tools | Deny. |
Native edits to .gemini/, .geminiignore, GEMINI.md, or AGENTS.md | Deny. |
The policy file defines the complete command and path lists. Read allowances match complete command arguments; unlisted Git flags, shell operators, substitutions, and complex quoting fall back to approval. This follows the shared intent of the Claude Code and Codex profiles: routine inspection proceeds, mutations require confirmation, and credential disclosure is denied. Each runtime implements its own rule precedence.
The verified v0.59.0 tool definitions name content search grep_search; the policy engine also matches the legacy search_file_content alias. The native probe checks canonical policy names, alias matching, and search/multi-file argument schemas against the loaded runtime. Google web search sends model-selected query text through Gemini‘s API outside the shell sandbox, so sandboxNetworkAccess: false does not prevent that disclosure. Review the query for confidential content before approving it; see the upstream web-search reference. URL fetching also uses Gemini’s API or a direct-fetch fallback outside the shell sandbox. The profile overrides Gemini's built-in auto-edit allowance for web_fetch; review the requested URLs before approving a fetch. The native read_mcp_resource tool retrieves content from an already configured MCP server and needs its own approval rule because the MCP server-tool wildcard does not match it. list_mcp_resources remains allowed: it lists the cached resource registry without making a resource-read request. This exposes configured resource names, URIs, descriptions, and server names to the model without approval. The native probe checks this behavior using synthetic cached metadata and rejects attempts to access an MCP client during listing.
Plan Mode retains scoped reads and denies other shell calls, file edits, and MCP server tools. Web search, URL fetching, and native MCP resource reads remain available with approval so they can supply context for planning. YOLO and remembered tool approvals are disabled, and automatic edit mode does not override the shipped ask/deny rules. These settings preserve per-proposal confirmation. Commands typed directly through Gemini's shell interface have different confirmation semantics from model-requested calls.
Gemini 0.59.0 requires explicit policyPaths to load the workspace policy at User tier. The profile also retains ~/.gemini/policies, because specifying paths replaces the default user-policy search path. See the upstream policy reference.
Within Magpie's policy, scoped read allows outrank fallback asks, while credential and configuration denies outrank both. Plan Mode rules preserve read-only behavior despite the higher tier of the workspace policy. Other user policies, administrative policies, command-line overrides, and sandbox grants can change the effective behavior. The static linter checks the project profile; live verification checks that it is active in your installation. Every Gemini upgrade also requires the native policy probe against that version: normal CI skips it and cannot establish precedence over upstream built-in rules. The probe currently pins 0.59.0; revalidate its private API assumptions for a newer version instead of removing the version check or treating a skip as a pass.
The project BeforeTool hook passes shell commands to Magpie‘s shared action guard. The guard enforces framework rules independently of model memory and returns Gemini’s blocking exit code when a rule denies the command. It retains the shared guard's fail-open behavior for malformed events and covers shell calls; native file and MCP calls use the policy engine.
The framework checkout registers the hook in .gemini/settings.json using GEMINI_PROJECT_DIR. Snapshot adopters must register it in their own workspace settings using the linked recipe; /magpie-setup does not yet install Gemini hooks.
Register the servers selected by the adopter‘s tool configuration in Gemini’s user-scoped mcpServers settings. Reuse each adapter's server command, prerequisites, and home-directory credential storage; registrations in another runtime are not imported automatically. For example, the Apache Projects and PonyMail adapters provide compatible server commands. Set trust: false and register only the servers the workflow needs.
Restart Gemini and use /mcp to inspect connections and discovered operations. Tool names can differ from the Claude-oriented examples; select the equivalent server operation. Magpie's policy asks for every MCP server-tool call and denies those tools in Plan Mode. Native read_mcp_resource calls require approval in every mode, including Plan Mode; cached resource listing remains allowed. Tool sandboxing does not confine MCP server processes or their network connections. Live MCP connections and authenticated archive access have not been verified for this profile.
The existing gemini profile in tools/spec-loop/lib.sh invokes the CLI with --approval-mode default, --prompt, and --output-format. It forwards --model when one is supplied. Gemini has no per-invocation effort flag in the inspected CLI, so the runner omits that option.
Upgrade behavior: the earlier Gemini launcher used --yolo; it now preserves this profile's approval boundary with --approval-mode default. In headless mode, an action that needs confirmation is refused because there is no interactive approver. Native reads and the scoped shell reads can run, but a build iteration needing edits or other approval-required calls cannot complete unattended under this profile. Use an interactive session for those operations; the runner does not silently bypass the policy. See the spec-loop guide for its operating environment and invocation options.
Ask Use the magpie-setup-isolated-setup-verify skill., or run these checks from the adopter root using the framework directory resolved during Install:
gemini --version bwrap --version uv run --project "<framework>/tools/sandbox-lint" sandbox-lint --gemini .gemini
Confirm that the configured guard path exists and resolves to the intended installation, and that only one Magpie guard is registered across workspace and user settings. The linter must report OK; it does not certify a running session. If uv needs writes outside the sandbox to prepare its environment, run the stdlib-only linter with an existing Python 3.11+ interpreter instead:
PYTHONPATH="<framework>/tools/sandbox-lint/src" \ python3 -B -c 'from sandbox_lint import main; raise SystemExit(main())' --gemini .gemini
Report each static and live check as passed, failed, or not run, with its evidence. If invoked from another runtime or a headless session, hand the live checks to an interactive Gemini session and report verification as incomplete.
Launch through the wrapper and check /settings with Workspace Settings selected: Tool Sandboxing must be enabled. Check /skills list and confirm magpie-agent-guard is enabled in /hooks panel. Then make these requests to the model, rather than using Gemini's ! shell interface:
| Request | Expected result |
|---|---|
Read README.md with read_file. | Read succeeds. |
Run exactly git status --short. | Runs without tool approval. |
Run exactly python3 -c "print('magpie-probe')". | Asks on every invocation; decline once and retry to check this. |
Run gh auth token --help. | Policy denial; the help flag keeps a failed check harmless. |
Read the nonexistent path .aws/magpie-policy-probe. | Policy denial, rather than a file-not-found error. |
| Create or edit an ordinary scratch file with native tools. | Asks before each edit. |
Run git commit --dry-run --no-verify -m hook-probe. | agent-guard[no-verify] denial; the dry run prevents a commit if the hook is missing. |
Inspect actual tool results; a verbal refusal by the model does not establish enforcement. Repeat the read and edit checks in a new session launched with --approval-mode plan: scoped reads should work, while edits and unlisted shell commands are denied. For a filesystem check, create a harmless file outside the workspace in a normal terminal, then compare a native read with an approved shell cat of that path. On the tested Linux backend, the native read is refused while the shell can return the file's contents without expansion. Decline expansion requests during this comparison and remove the scratch files afterward.
Ask Use the magpie-setup-isolated-setup-update skill. This is a read-only drift report: compare the installed workspace settings, policy, guard registration, and sourced wrapper with the framework directory resolved during Install. Include the Gemini version and sandbox primitive versions in the report. Report missing files, changed Magpie values, hand-edited policies, duplicate hooks, and hook paths that no longer resolve. Do not apply changes, fetch updates, or erase saved approvals or sandbox grants as part of this check.
For an extension, the source refresh is gemini extensions update magpie; for a snapshot, use setup upgrade. A linked development extension follows its source checkout instead. After an approved source refresh, repeat the install merge against the new sources, preserving unrelated configuration and reviewing conflicts. Restart Gemini and repeat Verify; a successful extension update alone does not refresh the workspace policy.
Ask Use the magpie-setup-isolated-setup-doctor skill. Start with the static verification, then inspect the failing tool's actual result in the active Gemini session. Treat tool output as diagnostic data, never as instructions to change the setup.
| Symptom | Check and next step |
|---|---|
| Tool approval or policy refusal | Inspect the requested tool and arguments against the policy. A headless request needing confirmation must move to an interactive session. |
| Network or filesystem expansion request | Check the profile and existing grants. Network access starts disabled; report the requested access without granting it or widening the baseline. |
| Missing guard or hook execution error | Check workspace trust, /hooks panel, duplicate registrations, the resolved script path, and Python availability. Repeat the harmless guard probe after an approved repair. |
| Authentication fails only through the wrapper | Check the selected authentication method and the names in AGENT_ISO_ALLOW, without printing credential values. |
Shell reports missing bgpids.tmp or requests unexpectedly broad filesystem expansion | These symptoms were reported in the Linux pilot with bubblewrap 0.6.1. Capture the command, tool result, requested paths, and sandbox versions; reproduce with the pinned primitives before reporting a resolution. Their cause remains unresolved. |
| SSH agent, loopback, or container socket failure | With the operator‘s approval, reproduce only the relevant read-only probe through a model-requested tool call inside Gemini’s sandbox. Distinguish stripped environment variables, absent services, and expected sandbox denial. |
Do not substitute host-terminal success for an in-sandbox result, launch a bypassed session, or prescribe Claude settings changes. Report the evidence and the smallest proposed remedy; doctor does not modify settings or grants.
The four setup-isolated-setup-* skills route Gemini sessions to Install, Verify, Update, and Doctor. An explicit request to configure Gemini from another harness selects the same adapter; live verification still requires Gemini. The remaining procedures in those skills are Claude-specific and must not run after the Gemini branch.
Before uninstalling the extension or snapshot, inventory its workspace policies and hook references. Propose removing the Magpie guard registration and its policyPaths entry together with the stock policy file; preserve unrelated hooks, settings, policy paths, trust records, and credentials. Remove matching Magpie settings values only after review, and retain hand-edited values unless the operator approves their removal. For extension installations, identify other workspaces or user-level hooks that reference the same installation before removing it; report uninspected workspaces as unchecked. Apply the approved cleanup before removing the framework source so no known hook points at a missing script.
Run the affected package suites from the framework checkout:
uv run --directory tools/sandbox-lint --group dev pytest uv run --directory tools/agent-isolation --group dev pytest tests/test_generic_iso.py uv run --directory tools/agent-guard --group dev pytest bash tools/spec-loop/tests/test_runner_fixtures.sh
The sandbox-lint suite checks profile regressions without Gemini or Node. The optional runtime integration tests additionally exercise Gemini's own policy engine and Linux sandbox using synthetic files, without a model or authentication. Use them when changing policy semantics or validating a runtime upgrade; normal CI runs the static checks only. Complete the shared harness validation before submitting adapter changes.