Skip to content

Gemini CLI

Google’s Gemini CLI works similarly to Claude Code in spirit – permissions are checked by the agent harness rather than the kernel – with an optional operating-system sandbox layer you can turn on if you want stricter isolation (macOS Seatbelt, or Docker/Podman elsewhere).

Add Portuni to ~/.gemini/settings.json:

{
"mcpServers": {
"portuni": {
"httpUrl": "http://localhost:4011/mcp",
"headers": {
"Authorization": "Bearer $PORTUNI_MCP_TOKEN"
},
"timeout": 5000
}
}
}

Gemini CLI resolves environment variables in settings.json strings, so reference the token as $PORTUNI_MCP_TOKEN rather than pasting it in. Export the variable in your shell (Settings → MCP Server → Copy token in the desktop app), or launch Gemini from a terminal the desktop app spawned, which has it injected. The bearer header matters: the desktop sidecar always requires it, and a standalone server requires it whenever PORTUNI_AUTH_TOKEN is set.

The example above shows a standalone server on the default port 4011. The desktop app’s install buttons cover Claude Code, Codex, and Vibe but not Gemini, so to reach a desktop workspace you register it by hand the same way – each enabled workspace’s sidecar listens on its own loopback port allocated from 47011 up, with its token in the PORTUNI_MCP_TOKEN_<WORKSPACE_ID> env var. Grab the URL and token from Settings → MCP Server.

Other useful keys on the same object: trust (skip per-tool approval prompts), timeout (in milliseconds).

For the full picture, see the Gemini MCP server docs.

Out of the box, Gemini CLI treats the directory you launched it from as its workspace and ignores everything else. Mirror folders living in a separate workspace root need to be included on purpose.

Three ways to do it:

At launch (recommended). Pass --include-directories – up to five, comma-separated:

Terminal window
gemini --include-directories /Users/me/Workspaces/portuni

Scope is the current session only. Bake it into a shell alias if you open Portuni mirrors often.

Mid-session. If you realise later that you need another folder:

/directory add ~/Workspaces/portuni/q2-rebrand
/directory show

Heads up: the slash command is disabled when running under a restrictive sandbox profile. In that case, use --include-directories at launch instead.

Persistent (use with care).

{
"context": {
"includeDirectories": ["/Users/me/Workspaces/portuni"],
"loadMemoryFromIncludeDirectories": true
}
}

Every Gemini session on the machine now sees the folder. Useful on a dedicated workstation; otherwise the launch flag stays cleaner.

Gemini CLI has a few different personalities when it comes to asking for confirmation:

Mode How to enable What it does
default no flag Asks before every tool call
auto_edit --approval-mode=auto_edit Auto-approves edits; still asks for the rest
plan --approval-mode=plan Read-only planning – no writes execute
yolo --yolo or Ctrl+Y Auto-approves everything

--yolo automatically turns the sandbox on, which is a sensible safety net when you’re letting the agent act freely.

If you’d like stronger isolation, Gemini can run the agent process inside a sandbox. Turn it on with --sandbox / -s, the GEMINI_SANDBOX=true env var, or tools.sandbox: true in settings.

  • macOS – uses sandbox-exec with the permissive-open profile: writes outside the project directory are restricted, most other operations are allowed.
  • Linux / cross-platform – uses a Docker or Podman image called gemini-cli-sandbox, which you can customise via .gemini/sandbox.Dockerfile.

Pair the sandbox with --include-directories so the sandbox image picks up your mirror folders at start-up. Runtime additions through /directory add are blocked under restrictive profiles.

With the desktop app, “more than one instance” is the normal state: every enabled workspace runs its own sidecar on its own port (from 47011 up) with its own token. Since there’s no Gemini install button, mirror the naming convention the app uses for the other clients – one entry per workspace, named portuni-<workspace-id>, token referenced via that workspace’s PORTUNI_MCP_TOKEN_<ID> variable. In app-spawned terminals all of those variables are already exported (plain PORTUNI_MCP_TOKEN aliases the active workspace).

For standalone CLI servers, register each instance as its own MCP server in ~/.gemini/settings.json the same way:

{
"mcpServers": {
"portuni": {
"httpUrl": "http://localhost:4011/mcp",
"headers": { "Authorization": "Bearer $PORTUNI_MCP_TOKEN" }
},
"portuni-alt": {
"httpUrl": "http://localhost:3002/mcp",
"headers": { "Authorization": "Bearer $PORTUNI_ALT_MCP_TOKEN" }
}
}
}

If you point Gemini’s MCP URL at the Portuni endpoint with the ?home_node_id=<id> query param (the same form portuni_mirror writes into other harness configs), the server auto-seeds the read scope on connect and you can call tools immediately. Without the query param, call portuni_session_init as your first move.