Cookbook#
A collection of patterns for common gptme workflows. Each pattern shows a concrete problem, the idiomatic solution, and a runnable example.
Tool Use Basics#
Difficulty: Beginner | Category: Tool Use
Problem
New gptme users often treat it as a chatbot. The real power is that gptme can act — read and write files, run commands, and inspect output — all in one conversational session without leaving the terminal.
Solution
gptme ships with built-in tools that are always available:
Tool |
What it does |
|---|---|
|
Run any shell command and capture stdout/stderr |
|
Write or edit files |
|
Execute Python code in a persistent interpreter |
|
Read file contents into context |
|
Fetch a URL (if enabled) |
The agent orchestrates these tools automatically based on your request. You don’t need to invoke them explicitly.
Example
Start a session and ask a compound question that requires multiple tools:
gptme "Read README.md, list the project's dependencies from pyproject.toml, and tell me if any are pinned to an old major version"
gptme will read both files, reason about version ranges, and reply with its findings.
For interactive iteration, start a session and keep chatting:
gptme # opens an interactive session
# > Read the failing tests and fix them
# > Now run the test suite and show me the output
# > Write a summary of what you changed to CHANGES.md
Notes
Tools run in your local environment with your permissions. Keep sessions scoped to the project directory.
Use
gptme tools listto see which tools are available and which are enabled by default.Add
--no-confirmto skip per-tool confirmation prompts in trusted sessions.
Parallel Research Pipeline#
Difficulty: Intermediate | Category: Multi-Agent
Problem
Deep research takes time when done sequentially. If you need to compare five frameworks or investigate three bug hypotheses, doing them one-by-one wastes wall-clock time and burns context on already-answered sub-questions.
Solution
gptme supports spawning subagents via the subagent tool. Each subagent gets
a clean context and runs its task independently. The coordinator waits for all
subagents to finish, then synthesizes the results.
This pattern works well for:
Comparing N alternatives simultaneously
Running independent research branches
Executing the same task against multiple inputs
Example
Create a coordinator prompt file and run it:
cat > research-prompt.md << 'EOF'
Research the following three Python HTTP client libraries in parallel:
1. httpx
2. aiohttp
3. requests
For each, find: latest version, async support, connection pooling behavior, and
known issues with timeouts. Then write a comparison table to comparison.md and
recommend one for a high-concurrency microservice.
EOF
gptme --tools +subagent "$(cat research-prompt.md)"
Or invoke multi-agent mode directly in an interactive session:
gptme
# > Spawn three subagents: one researches httpx, one aiohttp, one requests.
# > Each should write its findings to a temp file named after the library.
# > When all are done, synthesize the findings into comparison.md.
The coordinator agent will spawn three subagents with separate contexts, each researching one library. Results are written to shared files; the coordinator reads them and writes the synthesis.
Notes
Subagents share your filesystem but not context. Use files as the communication channel between coordinator and workers.
For independent tasks, the total wall-clock time is roughly
max(subtask times)rather thansum(subtask times).Keep each subagent’s prompt self-contained — it won’t see the coordinator’s conversation history.
Persistent Context with Skills#
Difficulty: Intermediate | Category: Context Management
Problem
Every new gptme session starts blank. If your project has conventions (a specific naming scheme, a non-obvious architecture decision, a required workflow before running tests), you end up pasting the same explanation repeatedly or getting wrong first drafts because the agent lacked context.
Solution
A skill is a plain markdown document (SKILL.md) that gptme injects into
the session context automatically when its name is requested. Skills are placed
in named subdirectories under skills/ (or ~/.config/gptme/skills/ for
user-global skills).
This means you write the explanation once, commit it, and gptme makes it available on demand — no copy-pasting, no per-session setup.
Example
Create a skill for your project’s database migration convention:
mkdir -p skills/db-migration
cat > skills/db-migration/SKILL.md << 'EOF'
---
name: db-migration
description: Django migration conventions and pre-migration checklist
---
# Migration Workflow
## Before creating a migration
1. Run `make lint` — schema changes that fail lint cause corrupt migrations.
2. Squash pending migrations if there are more than 10.
3. Never create a migration on an unmerged feature branch.
## Creating a migration
```bash
python manage.py makemigrations --name describe_the_change
```
## Reverting a migration
```bash
python manage.py migrate myapp 0042 # the migration before yours
```
EOF
gptme automatically discovers skills in the skills/ directory at your
project root (no configuration needed). Alternatively, place skills in
~/.config/gptme/skills/ for user-global availability across all projects.
Skills are loaded by name — request one explicitly in a session:
gptme "Using the db-migration skill, help me add a nullable email field to the User model"
Notes
Skills are plain markdown files — commit them to your project repo so all contributors benefit from them.
Skills work across runtimes (gptme terminal, Claude Code with the hook adapter). Write them once, use them everywhere.
See Skills for the full skills reference.
Compose Skills into Workflows#
Difficulty: Advanced | Category: Skill Composition
Problem
Real-world workflows are multi-step: run tests, update a changelog, bump a version, create a tag, post a release. Writing a single monolithic prompt for this is brittle — it’s hard to update one step without breaking others, and you can’t reuse the individual steps elsewhere.
Solution
gptme skills compose explicitly. A workflow skill is a sequenced list of steps, while focused sub-skills hold the detailed conventions for each step. Name the workflow and every sub-skill you want loaded in the prompt; mentioning the workflow alone does not recursively load skills that it references.
This gives you a library of reusable primitives that snap together into larger workflows without duplicating their detailed instructions.
Example
Three focused sub-skills, each in its own SKILL.md:
# skills/release-check-tests/SKILL.md
---
name: release-check-tests
description: Verify the test suite passes before any release action
---
# Check Tests Before Release
Always run the full test suite before any release action:
make test
If any test fails, STOP and fix it before proceeding.
# skills/release-update-changelog/SKILL.md
---
name: release-update-changelog
description: Changelog update convention for releases
---
# Changelog Update Convention
Format: `## [X.Y.Z] - YYYY-MM-DD` with sections Added / Changed / Fixed / Removed.
Always add the new version block at the TOP of CHANGELOG.md, above previous versions.
Never delete old entries.
# skills/release-tag-and-push/SKILL.md
---
name: release-tag-and-push
description: Git tagging and push convention for releases
---
# Tag and Push Convention
Create an annotated tag:
git tag -a v$VERSION -m "Release v$VERSION" && git push origin master --tags
Do not push without a passing CI run on master.
A workflow skill that chains all three into a single step:
# skills/release-workflow/SKILL.md
---
name: release-workflow
description: Full release pipeline — test, changelog, tag, push
---
# Release Workflow
Steps in order:
1. Run `make test` (stop on failure)
2. Update CHANGELOG.md with the new version
3. Commit the changelog: `git commit CHANGELOG.md -m "chore: update changelog for vX.Y.Z"`
4. Create the annotated tag and push: `git tag -a v$VERSION -m "Release v$VERSION" && git push origin master --tags`
Trigger the full workflow and load its three focused conventions with one prompt:
gptme "Using the release-workflow, release-check-tests, release-update-changelog, and release-tag-and-push skills, do a release for v1.4.2"
Notes
Keep sub-skills under ~50 lines each. Long skills dilute focus; split them.
Skills are versioned in git — use
git log skills/to audit how your workflows have evolved over time.See Skills for the full skill format reference.
Write a Custom Tool Plugin#
Difficulty: Advanced | Category: Custom Tools
Problem
gptme’s built-in tools cover general-purpose tasks, but domain-specific operations — querying a proprietary API, reading a custom binary format, calling an internal service — require a custom tool. Without one, you’re pasting raw output into the prompt by hand, which is slow and error-prone.
Solution
gptme has a plugin API. A plugin is a Python package that exposes a
GptmePlugin instance via the gptme.plugins entry-point group. Each tool
in the plugin is a ToolSpec with a name, description (shown to the LLM), and
a functions list of Python callables the LLM can invoke directly. Write typed
functions with docstrings and gptme surfaces them as structured tool calls.
Example
A plugin that lets gptme query a local SQLite database:
# my_gptme_plugin/__init__.py
import sqlite3
from gptme.tools.base import ToolSpec
from gptme.plugins.plugin import GptmePlugin
def query_db(db_path: str, sql: str) -> str:
"""Execute a read-only SQL query against a local SQLite database.
Args:
db_path: Path to the SQLite database file.
sql: SELECT statement to run.
Returns:
Query results as a Markdown table, or "(no results)" when no rows match.
"""
con = sqlite3.connect(f"file:{db_path}?mode=ro", uri=True)
cur = con.execute(sql)
rows = cur.fetchall()
cols = [d[0] for d in cur.description] if cur.description else []
if not cols:
return "(no results)"
header = " | ".join(cols)
sep = " | ".join("---" for _ in cols)
body = "\n".join(" | ".join(str(c) for c in row) for row in rows)
return f"{header}\n{sep}\n{body}"
plugin = GptmePlugin(
name="sqlite",
tools=[
ToolSpec(
name="query_db",
desc="Run a read-only SQL query against a local SQLite database and return results as a Markdown table.",
functions=[query_db],
)
],
)
# pyproject.toml (in the plugin package)
[project]
name = "my-gptme-plugin"
version = "0.1.0"
[project.entry-points."gptme.plugins"]
sqlite = "my_gptme_plugin:plugin"
Install and use:
pip install -e ./my_gptme_plugin
# Verify it loaded
gptme tools list
# Use it in a session
gptme "Query the users table in /var/app/prod.db and find accounts created in the last 7 days"
gptme will call query_db with the right arguments and show you the results
inline, without you needing to copy-paste any SQL output.
Notes
Use
mode=roin the SQLite URI (as shown) to prevent accidental writes from a buggy SQL statement the LLM generates.Keep tool descriptions concise but precise — the LLM reads the
descfield to decide when and how to call the tool.gptme derives the tool’s parameter schema from the function’s type annotations and docstring
Args:section; keep both accurate.See Plugin System for the full
GptmePluginandToolSpecAPI reference.