GEMINI.md & Configuration
In M01 you learned how to give Gemini context with @-mentions. That's great for one-off questions. But what about things that are always true about your project? GEMINI.md is how you encode that permanent context.
What GEMINI.md Does
Every new employee at a company gets an onboarding document: here's what we build, here's our tech stack, here's the coding style we use, here's what you should never do in production. Without it, they'd spend their first month asking basic questions and making avoidable mistakes. The pain is that this knowledge exists but isn't written down — so it only transfers in conversations. GEMINI.md is that onboarding document for Gemini CLI. Write it once, and every session starts with Gemini already knowing your project at the level of a developer who read the onboarding guide.
GEMINI.md is a Markdown file that Gemini CLI automatically reads at the start of every session when it exists in the current working directory (or any parent directory up to the home directory). It is not a config file with a fixed schema — it is free-form Markdown that you write in natural language. Gemini treats its contents as system-level context: facts about the project, rules for how to respond, and instructions that override default behavior.
Loading order: Gemini CLI finds the nearest GEMINI.md by walking up from the current directory. If you have ~/GEMINI.md and ~/projects/taskflow/GEMINI.md, and you're in the taskflow directory, Gemini loads both — the project file takes precedence where there are conflicts.
Gemini CLI found GEMINI.md in the current directory, read it, and was able to answer "what are the valid priority values?" without any @-mention — because that information was in the context file. This is the key insight: GEMINI.md is always-on context that you write once and never repeat.
Reading the TaskFlow GEMINI.md
TaskFlow already has a GEMINI.md at sample-project/taskflow/GEMINI.md. Let's walk through every section and understand why it's written the way it is.
# TaskFlow — Gemini CLI Context ## Project Overview TaskFlow is a REST API for managing personal tasks. Built with FastAPI + SQLite. Run it with: uvicorn main:app --reload Docs at: http://localhost:8000/docs
auth.py contains JWT helpers and database.py contains the session dependency — so it gives accurate cross-file advice without needing @-mentions.## Key Files - main.py — FastAPI app, middleware, router registration - models.py — SQLAlchemy models: User, Task, Tag (many-to-many via task_tags) - schemas.py — Pydantic v2 schemas for request/response validation - auth.py — JWT authentication: hash_password, verify_password, get_current_user - database.py — SQLAlchemy engine, SessionLocal, get_db() dependency - routers/users.py — POST /users/register, POST /users/login - routers/tasks.py — CRUD for /tasks/ (requires auth) - routers/tags.py — CRUD for /tags/ (requires auth)
## API Endpoints POST /users/register Create account {email, username, password} POST /users/login Get JWT token (form: username, password) GET /tasks/ List tasks (query: completed, priority, tag) POST /tasks/ Create task {title, description, priority, due_date, tag_ids} GET /tasks/{id} Get single task PATCH /tasks/{id} Update task fields DELETE /tasks/{id} Delete task GET /tags/ List all tags POST /tags/ Create tag {name, color} DELETE /tags/{id} Delete tag GET /health Health check
## Authentication All /tasks/ and /tags/ routes require: Authorization: Bearer <token> Get a token from POST /users/login with form-encoded username+password.
## Development Commands # Install dependencies pip install -r requirements.txt # Start server (auto-reload on file changes) uvicorn main:app --reload # Run tests pytest tests/ -v # Quick API test (after starting server) curl http://localhost:8000/health
You just read the five sections of TaskFlow's GEMINI.md and understood why each one is there. Notice the pattern: each section answers a different question Gemini might ask itself when reasoning about your project. Project Overview = "what is this?" Key Files = "where does what live?" Endpoints = "what does it expose?" Auth = "how are requests secured?" Commands = "how is it run?" Together they give Gemini a complete mental model of TaskFlow before you've typed a single prompt.
Model Selection
Gemini CLI can use different Gemini modelsDifferent versions of the Gemini language model with different capabilities, speeds, and costs. Flash is optimized for speed and cost efficiency. Pro is optimized for reasoning quality and complex tasks. You select the model in GEMINI.md or at runtime. depending on your task. You set the default model in GEMINI.md using the model: field, or override it per-session with the --model flag. The two main options are Gemini 2.5 Flash (fast, cheap, good for most tasks) and Gemini 2.5 Pro (smarter, better at complex reasoning, higher cost).
⚡ Gemini 2.5 Flash
✨ Gemini 2.5 Pro
# TaskFlow — Gemini CLI Context
## Configuration
model: gemini-2.5-flash # Default for routine tasks
# Uncomment for architecture reviews:
# model: gemini-2.5-pro
# Use Flash for routine tasks (faster)
gemini --model gemini-2.5-flash "@routers/tasks.py Add input validation to priority field"
# Use Pro for complex architecture questions
gemini --model gemini-2.5-pro "@models.py @schemas.py @routers/ Design a caching strategy for the task list endpoint"
gemini --model gemini-2.5-flash "@routers/tasks.py Add input validation to priority field"
gemini --model gemini-2.5-pro "@models.py @schemas.py @routers/ Design a caching strategy for the task list endpoint"
System Instructions
Every software team has unwritten rules: "we use type hints everywhere", "never commit directly to main", "tests are mandatory for new endpoints". New developers learn these rules the hard way — through code review comments and "that's not how we do it here" feedback. The pain is that these rules exist only in the heads of senior developers and come out as reactive corrections. System instructions in GEMINI.md are the proactive version: you write the rules once, and Gemini follows them from the first response — without waiting to be corrected.
System instructions in GEMINI.md are sections that tell Gemini how to behave, not just what the project is. Use a ## Instructions or ## Coding Standards section with bullet points or imperative sentences. Instructions override Gemini's default behavior for this project. Common uses: enforce style guides, specify what libraries to use or avoid, require certain patterns (like always adding type hints), and define "never do X" rules for safety.
## Coding Standards
### Always Do
- Use Python 3.12 type hints on all function parameters and return types
- Use Pydantic v2 style: model_config dict, model_dump() not .dict(), model_validate() not .from_orm()
- Use SQLAlchemy 2.0 ORM style: session.get() for single lookups, session.execute(select()) for queries
- Add try/except with specific exception types, never bare except
- Put new tests in tests/ directory following the conftest.py fixtures pattern
### Never Do
- Never use raw SQL strings — always use SQLAlchemy ORM or Core expressions
- Never commit SECRET_KEY, DATABASE_URL, or any credentials to the codebase
- Never add a new dependency without also adding it to requirements.txt
- Never change the response schema of an existing endpoint without a migration plan
Token Caching
Token caching (also called context cachingA Gemini API feature that stores a snapshot of a large context window. Subsequent requests that use the same cached context are cheaper and faster because the model doesn't re-process the same input tokens.) means that once Gemini has processed the content of your GEMINI.md and any @-mentioned files, it can reuse that processed representation for subsequent requests in the same session. The first request in a session pays the full token cost to process the context. Subsequent requests that use the same context prefix are cheaper and faster.
Practical implication for GEMINI.md: Content you put in GEMINI.md is cached once per session. Content you @-mention in individual prompts is processed fresh each time. This means GEMINI.md is the most cost-efficient place to put large, stable context that applies to all your questions.
What Belongs Where
Put in GEMINI.md (cached)
- Project overview and purpose
- Technology stack and versions
- File roles and key file list
- API endpoint table
- Auth pattern description
- Coding standards / "always/never" rules
- Development commands
Use @-mention (per-prompt)
- Specific file contents for targeted questions
- Files you're actively modifying
- Error messages or stack traces
- Test output that needs analysis
- Snippets from files that change often
- Large files only needed for one question
Global vs Project Config
Configuration Priority (highest to lowest)
gemini --model gemini-2.5-pro — overrides everything for that invocation
./GEMINI.md — project-specific context and instructions, loaded when in that directory
%USERPROFILE%\.gemini\config.yaml (same as ~\.gemini\config.yaml in PowerShell).# Create the .gemini directory if it doesn't exist
New-Item -ItemType Directory -Force -Path "$env:USERPROFILE\.gemini"
# Edit the global config
notepad "$env:USERPROFILE\.gemini\config.yaml"
# ~/.gemini/config.yaml — applies to all projects
model: gemini-2.5-flash # default model for all sessions
theme: dark # terminal color theme
auto_accept_edits: false # always confirm file changes
sandbox: false # set true to restrict shell tool
mkdir -p ~/.gemini
cat > ~/.gemini/config.yaml << 'EOF'
model: gemini-2.5-flash
theme: dark
auto_accept_edits: false
EOF
Three Starter Templates
Use these templates as starting points when creating GEMINI.md for new projects. Each is annotated to explain why each section is included.
# [Project Name] — Gemini CLI Context
## Project Overview
[One sentence: what this API does and who uses it]
Run: [exact start command]
API docs: [URL]
## Tech Stack
- Language/runtime: Python 3.12 / Node.js 20
- Framework: FastAPI 0.111 / Express 4
- Database: [name + ORM/driver]
- Auth: [JWT / OAuth2 / API key — describe the pattern]
- Tests: [pytest / jest — test directory]
## Key Files
- [filename] — [one-sentence role]
(list 5-10 most important files)
## API Endpoints
[table: METHOD /path — description — auth required: yes/no]
## Coding Standards
- [Language version rules: type hints, async/await patterns]
- [ORM style: what patterns to use/avoid]
- [Error handling: specific exception types, HTTP status codes]
- [Testing: required for new endpoints? where do tests go?]
## Development Commands
[copy-paste ready commands for: install, run, test, lint]
## Common Gemini CLI Tasks for This Project
- "[example prompt that's especially useful]"
(3-5 examples)
# [Monorepo Name] — Gemini CLI Context
## Repository Structure
[Brief description of what this monorepo contains]
## Packages / Services
- packages/[name] — [what it does, language, entry point]
- services/[name] — [what it does, how it's deployed]
(list all significant packages)
## Shared Infrastructure
- packages/shared/ — [shared types, utilities, constants]
- infra/ — [IaC: Terraform/Pulumi/CDK]
- [CI config location]
## Cross-Package Rules
- Shared types must be defined in packages/shared — never duplicated
- Breaking changes to shared types require updating all consumers
- Service-to-service calls use [gRPC / REST / message queue] — not direct imports
## Per-Package Standards
### packages/api (Node.js)
- TypeScript strict mode, zod for validation
### packages/worker (Python)
- Type hints required, mypy in CI
## Common Gemini CLI Tasks
- "@packages/api/src/ @packages/shared/ Check if this new type is consistent"
- "@services/auth/ Trace the complete login flow across services"
# [Pipeline Name] — Gemini CLI Context
## Pipeline Overview
[What data flows in, what comes out, what it's used for]
Orchestration: [Airflow / Prefect / cron]
Schedule: [how often it runs]
## Data Flow
[Source A] → [transform] → [Stage B] → [transform] → [Sink C]
## Key Datasets / Tables
- [table/dataset name] — [schema summary, row count, refresh cadence]
(list 5-10 key data assets)
## Data Quality Rules
- All pipelines must be idempotent (safe to re-run)
- Null handling: [your policy — drop, fill, error?]
- Schema changes: [process — migration required? backward compat?]
- Date/time: [all timestamps UTC? timezone handling?]
## Critical Never-Dos
- Never modify source tables directly — always write to staging first
- Never DELETE production data without a backup checkpoint
- Never commit database credentials — use [secret manager name]
## Development Commands
[commands for: install, run locally, test, validate data quality]
The TaskFlow GEMINI.md you've been reading all module is the REST API template filled in for a real project. In the lab below, you'll add a custom system instructions section to it and observe how Gemini's behavior changes. After the lab, you can use these templates for any future project — just swap the project-specific details and keep the structure.
Lab: Customize TaskFlow's GEMINI.md
You'll add four custom instructions to TaskFlow's GEMINI.md and observe how each one changes Gemini CLI's output on identical prompts. All commands run from inside sample-project/taskflow/.
Baseline: generate a new endpoint without custom instructions
First, run this command on the original TaskFlow GEMINI.md (before your changes). Note what style the code uses.
gemini "@routers/tasks.py Add an endpoint: GET /tasks/stats that returns total task count, completed count, and count by priority"
Add custom instructions to GEMINI.md
Open sample-project/taskflow/GEMINI.md and add this section at the end:
notepad GEMINI.md # or: code GEMINI.md (VS Code)
code GEMINI.md # or: nano GEMINI.md
Add this section to the bottom of GEMINI.md:
Re-run the same prompt and compare
# Exact same prompt as Step 1
gemini "@routers/tasks.py Add an endpoint: GET /tasks/stats that returns total task count, completed count, and count by priority"
class TaskStats(BaseModel) instead of a raw dict return, specific exception types if error handling was added, and no import of libraries not in requirements.txt.Test the "never return sensitive fields" rule
gemini "@routers/users.py Add a GET /users/me endpoint that returns the current user's profile"
schemas.User schema (which already excludes hashed_password) and NOT return the user object directly. If it adds a new schema, hashed_password should not appear in it. This demonstrates that your "never return sensitive fields" instruction is being followed.Knowledge Check
1. You run gemini inside sample-project/taskflow/. TaskFlow has a GEMINI.md file. What happens?
-p2. When should you use Gemini 2.5 Pro instead of Flash for a TaskFlow question?
3. You add "Never use raw SQL strings — always use SQLAlchemy ORM" to GEMINI.md's Coding Standards section. What effect does this have?
4. What is the highest-priority configuration source in Gemini CLI?
5. Which type of content is most cost-efficient to put in GEMINI.md vs using @-mentions per prompt?
Quiz Complete!
Ready for M03: Skill.md — Teaching Gemini Your Project's Patterns →