⌂ Home
Gemini CLI: Terminal AI Agent Foundations
Gemini CLI Track
⏰ 30-40 min Module 2 of 18 📺 Windows-first
🔮
Gemini CLI Track — M01: Prompting & Commands Master the @-mention context system, slash commands, and memory — all demonstrated on the real TaskFlow codebase you set up in M00.

Prompting & Commands

Gemini CLI is only as useful as the context you give it. This module teaches you how to feed it the right information at the right time — using @-mentions, slash commands, and the memory system.

Why Context Matters

Analogy First

Imagine asking a new contractor to estimate the cost of renovating your bathroom — without showing them the bathroom. They'll give you generic numbers based on average bathrooms, not your bathroom with its unusually placed plumbing and non-standard tile. The estimate will be plausible but wrong in exactly the ways that matter. The pain is that generic advice applied to specific situations creates confident-sounding errors. Giving Gemini CLI your actual TaskFlow files is like walking the contractor through the real bathroom: now every number they give you is specific to the actual pipes, the actual layout, the actual constraints you're dealing with.

✗ Without Context

Prompt: "How does the auth flow work?"

  • Describes generic JWT flows
  • May mention libraries you don't use
  • Can't tell you which fields your User model has
  • Hallucinations increase for project-specific details
  • Advice requires you to translate to your codebase

✓ With @-mention Context

Prompt: "@auth.py @routers/users.py How does the auth flow work?"

  • Sees your exact get_current_user() function
  • Knows you use python-jose and HS256
  • Traces the real OAuth2PasswordBearer flow
  • Cites actual line numbers and field names
  • Advice applies directly to your code
Why It Matters — Real Numbers

A developer debugging an auth issue in TaskFlow without @-mentions might get advice about a get_current_user that takes different parameters than the actual one — causing them to chase a non-existent bug. With @auth.py, Gemini sees the actual function signature get_current_user(token: str = Depends(oauth2_scheme), db: Session = Depends(get_db)) and can immediately spot whether the issue is in token parsing, database lookup, or the HTTP exception. Context transforms "10 minutes of debugging wrong things" into "30 seconds of identifying the real issue".

@file Mentions

Technical Definition

An @-mention is a file reference that Gemini CLI resolves before sending your prompt to the model. When you type @models.py, Gemini CLI reads that file from disk, prepends its content to your prompt, and sends the combined text to the Gemini model. The model then sees both your question and the complete file content — as if you had copy-pasted the file into your prompt manually, but faster and without length constraints.

Paths are relative to your current working directory. @models.py and @routers/tasks.py both work as long as you're in the sample-project/taskflow/ directory.

Single File Examples

WHAT: Each of these commands loads a specific TaskFlow file and asks a question about it. Notice how the questions are specific to what that file actually contains. WHY: Specificity in both the file and the question gets you specific, useful answers.
powershell — single-file @-mentions on TaskFlow
# Understand the Task model's fields and relationships
gemini "@models.py Explain the Task model. What is the purpose of the task_tags table?"

# Understand schema validation rules
gemini "@schemas.py What fields are optional vs required in TaskCreate?"

# Understand the auth dependency
gemini "@auth.py What does get_current_user raise if the token is expired or invalid?"

# Understand database connection lifecycle
gemini "@database.py Why does get_db use yield instead of return?"
bash — single-file @-mentions on TaskFlow
gemini "@models.py Explain the Task model. What is the purpose of the task_tags table?"
gemini "@schemas.py What fields are optional vs required in TaskCreate?"
gemini "@auth.py What does get_current_user raise if the token is expired or invalid?"
gemini "@database.py Why does get_db use yield instead of return?"
PowerShell — sample-project/taskflow
PS>gemini "@models.py Explain the Task model. What is the purpose of the task_tags table?"
✦ Reading models.py...
The Task model has 10 fields:
id, title, description, completed (bool), priority (str: low/medium/high)
due_date (nullable datetime), created_at, updated_at, owner_id, tags (relationship)
 
task_tags is a SQLAlchemy association table for the many-to-many
relationship between Task and Tag. It has no ORM class of its own —
SQLAlchemy manages it transparently through task.tags and tag.tasks.
Press ▶ to see the response
What Just Happened?

Gemini correctly identified all 10 Task fields, the priority values (low/medium/high — from the model's default string), and correctly explained the association table pattern. It could only do this because it read models.py directly — this is not general SQLAlchemy knowledge, it's specific to your TaskFlow file.

Multi-file: Cross-cutting Analysis

WHAT: Mention multiple files to ask questions that span files. WHY: Real bugs and architecture questions rarely live in a single file. @models.py @schemas.py lets you ask "are these in sync?" without manually comparing them.
powershell — multi-file analysis on TaskFlow
# Check model-schema alignment
gemini "@models.py @schemas.py Are all Task model fields represented in the Task response schema? List any that are missing."

# Trace auth dependencies across layers
gemini "@auth.py @routers/tasks.py Which task endpoints use get_current_user? How does it get injected?"

# Understand the full request cycle
gemini "@database.py @routers/tasks.py How does the database session get created and closed for a single POST /tasks/ request?"

# Find potential N+1 query issues
gemini "@models.py @routers/tasks.py When list_tasks returns results with tags, how many SQL queries are executed? Is there an N+1 risk?"
bash
gemini "@models.py @schemas.py Are all Task model fields represented in the Task response schema? List any that are missing."
gemini "@auth.py @routers/tasks.py Which task endpoints use get_current_user? How does it get injected?"
gemini "@database.py @routers/tasks.py How does the database session get created and closed for a single POST /tasks/ request?"
gemini "@models.py @routers/tasks.py When list_tasks returns results with tags, how many SQL queries are executed? Is there an N+1 risk?"

@folder Mentions

Technical Definition

An @folder mention loads all files in a directory recursively. @routers/ reads routers/users.py, routers/tasks.py, and routers/tags.py in one shot. Use folder mentions when your question spans many files in the same directory. Avoid loading massive folders — very large contexts can hit token limitsThe maximum number of tokens (roughly 4 characters per token) that can be sent in a single request. Gemini 2.5 Flash supports 1M tokens in context, but very large contexts are slower and more expensive. For TaskFlow, even loading all source files fits easily within limits. or slow down the response.

powershell — @folder mentions on TaskFlow
# Load all router files at once
gemini "@routers/ What authentication is required for each endpoint? Which ones are public?"

# Analyze all tests at once
gemini "@tests/ What test coverage exists? List any endpoints or functions that have no tests."

# Load entire project for architecture review
gemini "@routers/ @models.py @schemas.py @auth.py If I wanted to add a 'project' resource that tasks belong to, what changes would I need to make across all these files?"
bash
gemini "@routers/ What authentication is required for each endpoint? Which ones are public?"
gemini "@tests/ What test coverage exists? List any endpoints or functions that have no tests."
gemini "@routers/ @models.py @schemas.py @auth.py If I wanted to add a 'project' resource that tasks belong to, what changes would I need to make across all these files?"
Gotcha: Folder Loading on Windows

On Windows, use forward slashes in @-mentions even in PowerShell: @routers/ not @routers\. Gemini CLI normalizes paths internally, but the backslash can confuse the parser in some versions. When in doubt, use forward slashes consistently.

Built-in /slash Commands

Technical Definition

Slash commands are special directives typed inside the Gemini CLI interactive session. They control the session itself — clearing history, adding memories, getting help — rather than sending prompts to the model. They start with / and must be on their own line. You cannot use them in headless mode (-p); they only work in interactive sessions.

  • /help Lists all available slash commands and flags. Run this any time you forget a command name.
  • /clear Clears the conversation history from the current session. The model forgets everything said so far, but persistent memory (added via /memory add) is kept.
  • /quit Exits the Gemini CLI session. Equivalent to Ctrl+C or Ctrl+D.
  • /memory add Adds a string to the persistent memory store. This text is prepended to every future session automatically. Use it for facts about your project that should always be available.
  • /memory show Displays all entries currently in the persistent memory store. Useful for auditing what context is always being sent.
  • /tools Lists all tools available to the model in the current session: filesystem, shell execution, web search, and any configured MCP servers.
Gemini CLI — interactive session
PS>gemini
✦ Gemini 2.5 FlashType /help for commands, @file to add context
>/tools
Available tools: read_file, write_file, list_directory, run_shell_command, web_search
>/memory add This is the TaskFlow API project. JWT auth. SQLite. Python 3.12.
Memory saved. This will be included in all future sessions.
>/memory show
1. This is the TaskFlow API project. JWT auth. SQLite. Python 3.12.
>/clear
Conversation cleared. Memory entries preserved.
Press ▶ to see slash commands in action

Memory System

Analogy First

Imagine having to introduce yourself and explain your job to every person you meet — every day, every meeting, from scratch. "Hi, I'm a developer working on a FastAPI app that uses JWT auth with SQLite..." The pain of stateless AI tools is exactly this: every session starts fresh, and you spend the first several prompts re-establishing context. Gemini CLI's memory system is the permanent sticky note you leave yourself: it gets read at the start of every session, so Gemini already knows the essentials before you type a single word.

Memory entries are stored in ~/.gemini/memory (Linux/macOS) or %APPDATA%\gemini\memory (Windows) and are automatically prepended to every session. Think of them as your personal GEMINI.md that works across all projects.

WHAT: Add persistent context about TaskFlow so you don't have to repeat it each session. WHY: You'll run hundreds of Gemini CLI sessions during this course — memory means you never waste a prompt re-explaining what TaskFlow is. GOTCHA: Keep memory entries concise. Long entries consume tokens in every request.
gemini CLI — interactive session
# Start an interactive session (from inside sample-project/taskflow/)
gemini

# Add project-specific memory entries
/memory add TaskFlow is a FastAPI + SQLite task management API (the course reference project)
/memory add TaskFlow auth: JWT tokens from POST /users/login, Bearer header on all /tasks/ and /tags/ routes
/memory add TaskFlow models: User (id, email, username), Task (priority: low/medium/high), Tag (name, color)
/memory add TaskFlow stack: Python 3.12, FastAPI 0.111, SQLAlchemy 2.0, Pydantic v2, python-jose HS256

# Verify what's stored
/memory show

How Memory Persists Across Sessions

Session 1
You add memory about TaskFlow You run /memory add four times with TaskFlow context. Session ends.
Session 2 (next day)
Gemini already knows TaskFlow You type: "What's the priority field type?" — Gemini answers "string: low, medium, or high" without you having to @-mention any file.
Session 3 (new feature)
Context available immediately You type: "@routers/tasks.py Add a GET /tasks/overdue endpoint" — Gemini knows the auth pattern and model structure from memory, only reads tasks.py for implementation details.
What Just Happened?

Memory is the difference between Gemini being a stateless tool you retrain every session and a persistent assistant that knows your project. The four memory entries above encode the essentials: what the project is, how auth works, what the data model looks like, and what technology stack you're using. Every future prompt you write can assume this knowledge.

Multiline Input

Technical Definition

Multiline input lets you include code blocks, error messages, or structured text in your prompt. In an interactive session, wrap your code in triple backticks and press Enter. In headless mode (-p), use here-string syntaxA way to include multiline text in a shell command without escaping. In PowerShell: @' ... '@. In bash: $'...' or a heredoc. The text is treated literally, including newlines and special characters. in your shell to pass multi-line prompts.

WHAT: In PowerShell, use a here-string (@'...'@) to pass a multiline prompt. This is essential for pasting error messages or code snippets. GOTCHA: The closing '@ must be at column 0 — no leading whitespace.
powershell — multiline prompt with here-string
# Pass an error message with context using here-string
$prompt = @'
I got this error when calling POST /tasks/:

sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) NOT NULL constraint failed: tasks.owner_id

Here is the create_task endpoint: @routers/tasks.py

What is causing the error and how do I fix it?
'@
gemini -p $prompt --no-interactive
WHAT: In interactive mode, type a backtick fence and press Enter — Gemini waits for the closing fence before processing. WHY: This is more natural than PowerShell here-strings for short pastes.
gemini CLI interactive — paste a code block
# In the interactive session, type:
> Fix this function so it handles the case where tag_ids contains non-existent IDs:
```python
def create_task(task: schemas.TaskCreate, db: Session, current_user: models.User):
    tags = db.query(models.Tag).filter(models.Tag.id.in_(task.tag_ids)).all()
    db_task = models.Task(**task.dict(), owner_id=current_user.id, tags=tags)
    db.add(db_task)
    db.commit()
    return db_task
```
bash — multiline with heredoc
# Use a bash heredoc for multiline prompts
gemini -p "$(cat <<'EOF'
I got this error when calling POST /tasks/:
sqlalchemy.exc.IntegrityError: NOT NULL constraint failed: tasks.owner_id

Here is the create_task endpoint: @routers/tasks.py
What is causing the error and how do I fix it?
EOF
)" --no-interactive

Effective Prompting Patterns

These patterns consistently produce better results than unstructured questions. All examples use TaskFlow files.

Pattern 1

Role Prompting

Start with a role to activate specific expertise. Roles shift the model's response style and depth.

example
gemini "Act as a senior Python security engineer. Review @auth.py for vulnerabilities. Be specific about severity."
Pattern 2

Step-by-Step Request

Ask Gemini to enumerate steps rather than give a blob of text. Easier to follow, easier to verify.

example
gemini "@models.py Step by step, explain exactly what happens in the database when I delete a User who has Tasks."
Pattern 3

Ask for Alternatives

Get options instead of a single answer. Useful when you're not sure what approach fits best.

example
gemini "@routers/tasks.py Give me 3 different ways to add pagination to list_tasks, ranked by implementation complexity."
Pattern 4

Constraint Prompting

Tell Gemini what NOT to do. Constraints produce more focused output than open-ended requests.

example
gemini "@schemas.py Add input validation to TaskCreate. Do NOT change the existing field names. Do NOT add any imports that aren't already in the file."
Bridge: From Prompting to Configuration

You've seen how @-mentions and prompting patterns shape what Gemini knows per-prompt. In M02, you'll learn how to encode the most important context permanently into a GEMINI.md file — so Gemini already knows your project's stack, patterns, and constraints every session without you having to repeat them. Think of good prompting patterns as temporary context; GEMINI.md as permanent context.

Lab: Explore TaskFlow Using Only Gemini CLI

Complete all five tasks. By the end you will understand every layer of TaskFlow — without reading a single line of code directly.

Map the entire API surface

powershell
gemini "@routers/ For every endpoint, list: HTTP method, path, whether auth is required, and the Pydantic schema used for the response."
bash
gemini "@routers/ For every endpoint, list: HTTP method, path, whether auth is required, and the Pydantic schema used for the response."
Expected: 11 entries. All /tasks/ and /tags/ routes should show "auth required". /users/register, /users/login, and /health should show "no auth". Response schemas should mention schemas.Task, schemas.User, schemas.Token.

Understand the many-to-many relationship

powershell
gemini "@models.py @schemas.py @routers/tasks.py Walk me through what happens — from database to HTTP response — when I call GET /tasks/ and a task has two tags. How does SQLAlchemy load the tags?"
Expected: Gemini traces the ORM lazy-loading or eager-loading of the tags relationship, explains the task_tags join table, and shows how the Tag objects become Tag schema instances in the JSON response.

Find what's missing in the test suite

powershell
gemini "@tests/ @routers/ Compare the existing tests to all available endpoints. Which endpoints have no test coverage?"
Expected: Gemini identifies gaps in test coverage — likely the tags router and some edge cases in tasks (invalid priority, missing fields, etc.) have no tests. This is a real gap in TaskFlow you'll fill in M08.

Use memory to skip re-explaining

gemini CLI interactive
# In an interactive session, first add memory:
/memory add TaskFlow uses Pydantic v2 (model_config not class Config, model_dump not .dict())

# Then in a new session, test it:
gemini "@schemas.py Am I using Pydantic v1 or v2 syntax here?"
Expected: Gemini correctly identifies Pydantic v2 syntax and may note the model_config = {"from_attributes": True} pattern (v2 replacement for class Config: orm_mode = True).

Use role prompting on a real problem

powershell
gemini "Act as a security engineer. Review @auth.py for the following issues: 1) Is the SECRET_KEY handling safe? 2) Are tokens invalidated on logout? 3) Is there a token expiry check? Be specific about what you find in this file."
Expected: Gemini identifies that the default SECRET_KEY is "dev-secret-key-do-not-use-in-production" (a real issue in auth.py line 13), that there's no logout/token revocation mechanism, and that expiry is handled by the JWT library's decode. These are real findings from the actual file.

Knowledge Check

1. You run gemini "@routers/ List all endpoints". What does the @routers/ mention do?

It only reads routers/__init__.py
It reads all files in the routers/ directory recursively
It lists the directory structure without reading file contents
It runs all Python files in the directory

2. What is the key difference between /clear and /memory show in a Gemini CLI session?

/clear deletes memory; /memory show saves conversation history
/clear erases the current conversation; /memory show displays persistent stored entries
Both affect the same in-session conversation history
/clear resets memory; /memory show displays the current conversation

3. You add a memory entry with /memory add TaskFlow uses JWT auth. When does this context get applied?

Only in the current session, until you type /clear
Only when you explicitly @mention the memory file
Automatically at the start of every future Gemini CLI session
Only when working in the same directory

4. Which prompting pattern would you use to get 3 different implementation options for adding pagination to TaskFlow's list_tasks endpoint?

Role prompting: "Act as a pagination expert..."
Constraint prompting: "Add pagination, don't change anything else"
Ask for alternatives: "Give me 3 ways to add pagination, ranked by complexity"
Step-by-step: "Step by step, add pagination"

5. You want to check whether TaskFlow's models.py and schemas.py are in sync. Which command is most appropriate?

gemini "@models.py List all Task fields" then manually compare
gemini "@schemas.py Are you in sync with models?"
gemini "@models.py @schemas.py Are the Task model and Task schema in sync? List any mismatches."
gemini "@routers/tasks.py Check model-schema alignment"

Quiz Complete!

Ready for M02: GEMINI.md & Configuration →