@google/gemini-cli (v0.40.1+).
Install
Auth
Crewship’s
apiKeyEnvVarsForAdapter("GEMINI_CLI") accepts either; both are mirrored to the container env so any version of gemini-cli finds its key.
Google account login
A Google AI Pro / Ultra subscription is a file, not a variable: Gemini CLI reads its “Login with Google” session only from~/.gemini/oauth_creds.json
(the google-auth-library credentials object — access_token,
refresh_token, scope, token_type, id_token, expiry_date in
milliseconds). Sign in with gemini on your own machine, then store the
whole file as a credential:
assign is the binding’s identity, not something Gemini
reads. A bare token is refused at submit time: the file needs access_token,
refresh_token and expiry_date, and only the file the CLI wrote has all
three.
At every run start Crewship renders the login into the agent’s
~/.gemini/oauth_creds.json (/crew/agents/<slug>/.gemini/oauth_creds.json,
mode 0600) with the real access and id tokens and refresh_token replaced
by 1//crewship-managed-no-refresh, sets GOOGLE_GENAI_USE_GCA=true — the
variable a headless gemini run selects the Google-login path with — and
carries no GEMINI_API_KEY / GOOGLE_API_KEY, because a key in the
environment wins over the login file. The run is billed flat_rate with
CREWSHIP_SUBSCRIPTION_PLAN set to “Google AI Pro” / “Google AI Ultra” when
the stored file names its tier in a plan field, and “Google AI” otherwise
(Google’s tokens carry no plan claim). Revoking the credential removes the file
from running containers; unassigning it removes the file at the next run
start.
Models
gemini-2.0-flash and gemini-1.5-pro are not available in the current Gemini API catalog — removed from picker. Note the dash-separated ID format (gemini-3-1-pro, not gemini-3.1-pro); Google’s models.list endpoint returns this canonical form.
Command shape
-p— non-interactive prompt mode--output-format stream-json— JSONL events (PR #10883)-m— model selector--approval-mode plan— appended only for theMINIMALprofile (Gemini’s read-only mode; its named-tool allowlist--allowed-toolsis deprecated in favour of the Policy Engine).CODING/FULLkeep the default flow.- System prompt folded into prompt body since headless mode has no
--system-instructionflag
MCP
Configured at/output/<slug>/.gemini/settings.json:
httpUrl (HTTP streaming, current) over url (SSE, legacy) — url is only emitted when the source explicitly declares sse transport. Env-var syntax ${VAR} or $VAR (POSIX); both expanded by gemini-cli at MCP spawn.
Crewship also auto-injects two sidecar-hosted servers into
.gemini/settings.json (injectMemoryMCP + injectRoutinesMCP): crewship-memory (http://127.0.0.1:9119/mcp/memory/<slug>) and crewship-routines (.../mcp/routines), both emitted as httpUrl entries. A user-declared server of the same name wins.Memory
Canonical memory set includingGEMINI.md (Gemini’s auto-discovery path) at /output/<slug>/.
Output stream
JSONL per geminicli.com/docs/cli/headless:Troubleshooting
gemini: not found — npm install failed.
Auth precedence trap — if both GEMINI_API_KEY (AI Studio) and GOOGLE_API_KEY (Cloud) are in the env, GOOGLE wins silently. Use one or the other.
Exit code 52 with no JSON — auth failure (issue #20183). Orchestrator detects exit-without-result and surfaces as run error.