Gemini CLI Notes
Background and Documentation
Configuration Layers
- User settings are in
~/.gemini/settings.json
. - Project-specific
myproject/.gemini/settings.json
files override~/.gemini/settings.json
. You only need to specify settings whose user-level values you want to change. - API keys and some other settings are controlled via environment variables. It is recommended to store them in
~/.gemini/.env
instead of adding them directly to~/.zshrc
or~/.bashrc
. - Project-specific
myproject/.gemini/.env
files shadow~/.gemini/.env
. You must specify all environment variables, even if you don’t want to change their user-level values. .env
takes precedence oversettings.json
, whereas command-line arguments trump both. See the Appendix at the end of the post for a deeper dive into how Gemini CLI processes configuration layers.- In particular, the current working directory will affect which
settings.json
,.env
andGEMINI.md
filesgemini
picks up.
Authentication, Request Limits and Privacy
- The
"selectedAuthType"
setting determines how you authenticate with Google’s AI services:"oauth-personal"
(personal Google account),"gemini-api-key
” (AI Studio) or"vertex-ai"
(Vertex AI). - You will be prompted to pick an auth type the first time you launch Gemini CLI, or more generally any time
"selectedAuthType"
isn’t found insettings.json
. You can also use the/auth
REPL command to switch to a different auth type later. - The auth type determines the model request limits as well as what data Google collects. See the Terms of Service and Privacy Notice for details. Keep in mind that if you authenticate using your personal Google account or use the free Google AI tier, your code, prompts and responses will be used to train Google models.
- If
"selectedAuthType"
is set to"oauth-personal"
, you will need to log into your Google account via the browser. This will create~/.gemini/google_accounts.json
and~/.gemini/oauth_creds.json
.- Currently (as of August 2025), you get the most free Gemini 2.5 Pro requests this way: 60 per minute and 1,000 per day.
- However, token caching is not available for this auth type. You can view your token usage for a given
gemini
session using the/stats
and/stats model
REPL commands.
- If
"selectedAuthType"
is set to"gemini-api-key
”, you will need toexport GEMINI_API_KEY="<Your Gemini API Key>"
in e.g.~/.gemini/.env
. You can obtain a Gemini API key here.- Currently (as of August 2025), the Free Tier rate limits for Gemini 2.5 Pro are 5 requests per minute and 100 requests per day. While this is considerably lower than what you get by authenticating using your personal Google account, token caching is available for this auth type.
- To get 1,000 requests per day using the Free Tier, you would need to switch to Gemini 2.5 Flash Lite (Flash Lite is a version of Lite optimized for low-latency use cases; Lite is not a “reasoning model”, unlike Pro). The lowest paid tier, Tier 1, gives you 150 requests per minute and 10,000 requests per day using Gemini 2.5 Pro.
- Anonymized usage stats, such what tools and models are used, are collected by default. Add
"usageStatisticsEnabled": false
to~/.gemini/settings.json
” to opt out.
Model Selection
- You can use the
--model
command-line argument to override the default model (currently Gemini 2.5 Pro) like so:gemini --model <model>
. - Supported
<model>
values includegemini-{2.5, 2.0}-{pro, flash, flash-lite}
. - You can also
export GEMINI_MODEL="<model>"
in~/.gemini/.env
or another.env
file.
Built-in Tools
- Gemini CLI comes with a number of built-in tools with the following execution flow. Their definitions live here.
- You can extend the list of built-in tools using MCP Servers. See this page for details.
- Use the
/tools
REPL command to list the tools available in a givengemini
session. For a longer description of each tool, run/tools desc
. - Use the
coreTools
setting insettings.json
to explicitly list what tools should be made available. For example,"coreTools" : []
means that no tools will be available whereas"coreTools": ["LSTool"]
means that onlyLSTool
will be available. - The name a tool appears under when you run
/tools
may not match the one you need to use incoreTools
. For example,LSTool
shows up as “ReadFolder”. This is becauseLSTool.Name
is set toReadFolder
inls.ts
, where its definition lives. - Most built-in tools follow the pattern of
FooBarTool
for thesettings.json name
, “FooBar” for the/tools
name andfoo-bar.ts
for the definition, but there are a handful of exceptions of whichLSTool
is one. -
Below are the
settings.json
names for the built-in tools, along with what/tools
calls them and where they are defined:settings.json name /tools name definition EditTool
“Edit” edit.ts GlobTool
“FindFiles” glob.ts WebSearchTool
“GoogleSearch” web-search.ts ReadFileTool
“ReadFile” read-file.ts LSTool
“ReadFolder” ls.ts ReadManyFilesTool
“ReadManyFiles” read-many-files.ts MemoryTool
“Save Memory” memoryTool.ts GrepTool
“SearchText” grep.ts ShellTool
“Shell” shell.ts WebFetchTool
“WebFetch” web-fetch.ts WriteFileTool
“WriteFile” write-file.ts - The default tools set correponds to having the following
coreTools
setting insettings.json
:"coreTools": ["EditTool", "GlobTool", "WebSearchTool", "ReadFileTool", "LSTool", "ReadManyFilesTool", "MemoryTool", "GrepTool", "ShellTool", "WebFetchTool", "WriteFileTool"]
- You can also use the
excludeTools
setting insettings.json
to remove specific tools from the default list. For example, adding"execludeTools": ["ShellTool"]
tosettings.json
will removeShell
from the list of available/tools
. - A tool listed in both
coreTools
andexcludeTools
is excluded. This means that you could list the default tool set incoreTools
and specify just the ones you want to disallow inexcludeTools
. - For example, if
settings.json
contains the following"coreTools": ["EditTool", "GlobTool", "WebSearchTool", "ReadFileTool", "LSTool", "ReadManyFilesTool", "MemoryTool", "GrepTool", "ShellTool", "WebFetchTool", "WriteFileTool"] "excludeTools": ["WebSearchTool", "ShellTool", "WebFetchTool"]
then
/tools
won’t showGoogleSearch
,Shell
andWebFetch
, whereas the rest of the default tools will remain available. - Keep in mind that
ShellTool
can execute arbitrary shell commands and thus poses a security risk. To help mitigate this,ShellTool
supports granular command restrictions. - For example, to enable only
git
to be executed, replace"coreTools": ["ShellTool"]
with"coreTools": ["run_shell_command(git)"]
insettings.json
. - Although you can also use
run_shell_command
inexcludeTools
, this is not recommended for security reasons. - Although restricting the commands
ShellTool
can execute viarun_shell_command
does provide a measure of security, it is nevertheless a good idea to enable sandboxing if you are going to makeShellTool
available (which it is by default, with no command restrictions).
Sandboxing
- Sandboxing is off by default. Add
"sandbox": true
to~/.gemini/settings.json
to turn it on. - When sandboxing is enabled, Gemini CLI will only be able to call tools supported by the sandbox environment, regardless of what tools are included via
coreTools
andexcludeTools
insettings.json
. - The default sandboxing methodology is platform-specific: Seatbelt on a Mac and Docker elsewhere.
- On a Mac,
export SEATBELT_PROFILE="<profile>"
in~/.gemini/.env
to select your Seatbelt profile. The built-in profiles are{permissive, restrictive}-{open, proxied, closed}
. The default ispermissive-open
, which restricts writes outside of the project directory but allows most other operations. export SEATBELT_PROFILE="custom"
in.gemini/.env
to use a custom Seatbelt profile stored in.gemini/sandbox-macos-custom.sb
. You can start by copying one of the built-in profiles, which live here and follow the naming schemasandbox-macos-<profile-name>.sb
(e.g.sandbox-macos-permissive-open.sb
forpermissive-open
andsandbox-macos-permissive-closed.sb
forpermissive-closed
).- See this page for some general pointers on creating custom Seatbelt profiles. They are written in a language called SBPL (“SandBox Profile Language”), which is a Scheme-based embedded DSL. The Apple Sandbox Guide has the details.
- Adding
"sandbox": true"
tosettings.json
is the equivalent of runninggemini --sandbox
(the--sandbox
command-line argument is a boolean flag). Alternatively, you can explicitly set"sandbox"
to one of the supported methodologies:"docker"
,"sandbox-exec"
(Mac only) or"podman"
. - In particular, you can use Docker-based sandboxing on the Mac by specifying
"sandbox: "docker"
insettings.json
. You will need Docker Desktop for the Mac to be installed and running for this to work properly. - Similar to having a custom Seatbelt profile, you can also create a custom Dockerfile in
myproject/.gemini/sandbox.Dockerfile
, as described here. - Per the docs, you should be able to add
export BUILD_SANDBOX=1
tomyproject/.gemini/.env
and havegemini
automatically build the custom Docker image. - When I tried this on a Mac, though (with Gemini CLI installed via
brew install gemini-cli
), I got the following error:ERROR: cannot build sandbox using installed gemini binary; run `npm link ./packages/cli` under gemini-cli repo to switch to linked binary.
This is apparently a known issue.
Instructional Context (“Memory”)
- Gemini CLI loads instructional context (aka “memory”) from files named
GEMINI.md
(the name can be changed via thecontextFileName
setting insettings.json
). - For an example, have a look at Gemini CLI’s own GEMINI.md.
- Context loaded from
GEMINI.md
files uses up context window tokens. This should not be material for Gemini 2.5 Pro, whose context window is large (1 million tokens). - Store user-level context in
~/.gemini/GEMINI.md
. You can add to it dynamically using the/memory add
REPL command. - Store
myproject
-specific context inmyproject/GEMINI.md
(rather thanmyproject/.gemini/GEMINI.md
). In other words, put it in the same sort of places where aREADME.md
would go. - Project-specific context will be merged with user-level context. Run the
/memory show
REPL command to see the overall, merged context. - Context can be controlled in hierarchical way using multiple
GEMINI.md
files, with the directory you launchgemini
from determining which ones are loaded. The details are here.
An Illustrative Example
Say that you are on a Mac and didn’t set any Gemini CLI-related environment variables in ~/.zshrc
or ~/.bashrc
. Assume that your user-level Gemini CLI configuration looks like this:
~/.gemini/settings.json
:
{
"theme": "Dracula",
"usageStatisticsEnabled": false,
"sandbox": true,
"selectedAuthType": "gemini-api-key"
}
~/.gemini/.env
:
export GEMINI_API_KEY="<Your Gemini API Key>" https://aistudio.google.com/apikey
export GEMINI_MODEL="gemini-2.5-flash-lite" # gemini-{2.5, 2.0}-{pro, flash, flash-lite}
~/.gemini/GEMINI.md
:
## User-level context
Now suppose that you have a project called myproject
, configured like this:
myproject/.gemini/settings.json
:
{
"selectedAuthType": "oauth-personal",
"excludeTools": ["ShellTool"]
}
myproject/.gemini/.env
:
export SEATBELT_PROFILE="custom" # {permissive, restrictive}-{open, proxied, closed}
myproject/.gemini/sandbox-macos-custom.sb
:
;; a suitably modified copy of sandbox-macos-permissive-open.sb, say
myproject/GEMINI.md
:
## Project-specific context
myproject/some_module/GEMINI.md
:
## Module-specific context
- If you run
gemini
outsidemyproject
:- You will authenticate using a Gemini API key, as per
~/.gemini/settings.json
- The API key will be read from
~/.gemini/.env
(commenting outGEMINI_API_KEY
will result in an error). - Sandboxing will be enabled, as per
~/.gemini/settings.json
. - Since no sandboxing methodology was specified explicitly,
sandbox-exec
will be used (the Mac default). - The Seatbelt profile used will be
permissive-open
(the default). - The model used will be Gemini 2.5 Flash Lite, as per
~/.gemini/.env
. - The default tool set will be availalbe. Run the
/tools
REPL command to confirm. - The instructional context should consist of the user-level context in
~/.gemini/GEMINI.md
alone, unless otherGEMINI.md
files happen to have been picked up based on your current working directory. Run the/memory show
REPL command to confirm.
- You will authenticate using a Gemini API key, as per
- On the other hand, if you
cd myproject; gemini
:- You will authenticate using your Google account, as per
myproject/.gemini/settings.json
. - Since there is no need for an API key, commenting out
GEMINI_API_KEY
in~/.gemini/.env
won’t have an effect. - The Seatbelt profile used will be
myproject/.gemini/sandbox-macos-custom.sb
, as dictated bymyproject/.gemini/.env
. - Irrespective of what
~/.gemini/.env
says, the model used will be Gemini 2.5 Pro (the default), even though you didn’t specifyGEMINI_MODEL
inmyproject/.gemini/.env
. Sincegemini
findsmyproject/.gemini/.env
first, the contents of~/.gemini/.env
are irrelevant. ShellTool
won’t be available, permyproject/.gemini/settings.json
. Run the/tools
REPL command to confirm.- The instructional context will be a combination of user-level context from
~/.gemini/GEMINI.md
, project-specific context frommyproject/GEMINI.md
and module-specific context frommyproject/some_module/GEMINI.md
. Run the/memory show
REPL command to confirm. - Since command-line argument take precedence over
settings.json
and.env
files, even after youcd myproject
you can still:- Turn off sandboxing via
gemini --sandbox false
- Explicitly select a different model via
gemini --model gemini-2.5-flash
.
- Turn off sandboxing via
- You will authenticate using your Google account, as per
Appendix: Configuration Layer Processing
We can use sandboxing to illustrate the order in which Gemini CLI processes “configuration layers”, since sandboxing is off by default and can alternatively be turned on via settings.json
files, .env
files and command-line arguments:
- Create an empty project directory:
mkdir -p ~/junk/myproject
. cd ~/junk/myproject
so thatmyproject
is your current project.- Run
gemini
. Sandboxing is off (the status bar at the bottom will say “no sandbox (see /docs)”). Exitgemini
. - Add
"sandbox": true
to the user-level settings in~/.gemini/settings.json
. You should also see additional settings there, such as"theme"
and"selectedAuthType"
. - Run
gemini
. Sandboxing is on (on a Mac, the status bar will say “macOS Seatbelt (permissive-open)” if you are using the default Seatbelt profile). Exitgemini
. - Create a project-specific
settings.json
file:mkdir .gemini; echo '{"sandbox": false}' > .gemini/settings.json
. - Run
gemini
. Sandboxing is off, because project-levelsettings.json
settings override user-levelsettings.json
settings. Note that you only need to specify the value ofsandbox
, the setting you want to override. Exitgemini
. - Set the
GEMINI_SANDBOX
environment variable via a user-level.env
file:echo 'export GEMINI_SANDBOX="true"' >> ~/.gemini/.env
. - Run
gemini
. Sandboxing in on, because environment variables take precedence oversettings.json
settings. Exitgemini
. - Create a project-specific
.env
file:echo 'export GEMINI_SANDBOX="false"' > .gemini/.env
.- This is sufficient if
"selectedAuthType"
is set to"oauth-personal"
in~/.gemini/settings.json
. - However, unlike with project-level
settings.json
overrides (where onlysandbox
needed to be specified), all relevant environment variables must be specified in.gemini/.env
and not justGEMINI_SANDBOX
. - For example, if
"selectedAuthType"
is set to"gemini-api-key"
in~/.gemini/settings.json
, you will need to addexport GEMINI_API_KEY="<Your Gemini API Key>"
tomyproject/.gemini/.env
in order to successfully authenticate yourself when runninggemini
frommyproject
.
- This is sufficient if
- Run
gemini
. Sandboxing in off, because the project-specific.gemini/.env
file shadows the user-level~/.gemini/.env
file. Exitgemini
. - Run
gemini --sandbox
. Sandboxing is on, because command-line arguments take precedence over environment variables.