Local-first coding agent on Google Gemini + ADK
Project description
GemCode
Local-first coding agent: Gemini + Google ADK, with repo tools, permissions, session persistence, and optional MCP. Implemented in clean-room fashion (reference only to third-party Claude Code trees).
Requirements
- Python 3.11+
- A Google AI Studio API key (
GOOGLE_API_KEY)
Install
cd gemcode
python3 -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -e ".[dev]"
Copy .env.example to .env and set GOOGLE_API_KEY.
Usage
From a git repository root (or pass -C /path/to/repo):
gemcode "Explain the structure of src/"
gemcode --yes "Add a module docstring to src/foo.py"
gemcode --session mysess --yes "Continue: run tests and fix failures"
--yes: allow mutating tools (write_file,search_replace). Shell execution is still restricted by the.env.exampleallowlist.--session: Conversation history is stored under.gemcode/sessions.sqlite(ADKSqliteSessionService). Reuse the same--sessionid to continue.--max-llm-calls: cap model↔tool iterations for this message (maps to ADKRunConfig.max_llm_calls). You can also setGEMCODE_MAX_LLM_CALLS.--model-mode: choose model routing mode (auto|fast|balanced|quality, defaultfast). Inauto, GemCode heuristically picks a model for the prompt.- Gemini family routing: set
GEMCODE_MODEL_FAMILY_MODE=auto|primary|alt.primaryuses theGEMCODE_MODEL*ids (Gemini 3.x defaults)altuses theGEMCODE_MODEL_ALT*ids (Gemini 2.5 family defaults)autouses a cheap prompt heuristic to prefer Gemini 3.x for complex tasks and Gemini 2.5 for simpler ones.
- Deep research: set
--deep-research(orGEMCODE_ENABLE_DEEP_RESEARCH=1) to enable research tools and route toGEMCODE_MODEL_DEEP_RESEARCH(default:travel_explore). - Gemini 3.x tool context circulation (built-in tools + custom/function tools)
- Enabled by default for
--deep-researchruns, so Search/URL/Maps results can be combined with your custom tools in the same workflow. - Controlled by
GEMCODE_TOOL_COMBINATION_MODE/--tool-combination-mode(deep_research|always|never|auto, default:deep_research).
- Enabled by default for
- Embeddings: set
--embeddings(orGEMCODE_ENABLE_EMBEDDINGS=1) to enable embeddings-based semantic retrieval (and embedding-backed memory whenGEMCODE_ENABLE_MEMORY=1). - Capability routing: set
--capability-mode(orGEMCODE_CAPABILITY_MODE) toauto|research|embeddings|computer|audio|allto enable the right toolsets (deep research / embeddings / computer-use) and route to role-appropriate models when applicable. - Tool inventory / validation:
gemcode tools listprints the exact tool inventory and whether each tool can build a Gemini tool declarationgemcode tools smokefails non-zero if any tool’s declaration compilation fails- Optional inspection flags:
--deep-research,--maps-grounding,--embeddings,--memory
- Optional compaction: set
GEMCODE_ENABLE_COMPACT=1to trim oldContententries before each model call (MVP sliding window; can break complex tool chains if too aggressive—tuneGEMCODE_MAX_CONTENT_ITEMS). - Session token ceiling: set
GEMCODE_MAX_SESSION_TOKENSto stop the next LLM call when cumulativeusage_metadata.total_token_countexceeds the limit. - Token budget tracking: set
GEMCODE_TOKEN_BUDGETto enforce continuation/stop decisions per user turn (token-budget audit in.gemcode/audit.log). - Stop-the-loop hooks: set
GEMCODE_POST_TURN_HOOK=/path/to/hook.sh(or place an executable at.gemcode/hooks/post_turn) to run after each user message. - Circuit breaker: set
GEMCODE_MAX_CONSECUTIVE_TOOL_FAILURESto block further tools after N consecutive tool errors. - Recovery-loop: ADK
ReflectAndRetryToolPlugin-based retries on tool failures.- Set
GEMCODE_ENABLE_TOOL_RECOVERY_RETRY=0to disable. - Set
GEMCODE_TOOL_REFLECT_MAX_RETRIES=1to control retries per tool.
- Set
- Gemini thinking controls (Claude-like):
- By default GemCode lets Gemini use its dynamic/adaptive thinking behavior.
- Set
GEMCODE_DISABLE_THINKING=1to force a best-effort “low thinking” mode:- Gemini 3.x: uses
thinkingLevel=minimal(can't fully disable) - Gemini 2.5: uses
thinkingBudget=0(disables thinking where supported)
- Gemini 3.x: uses
- Enable thought summaries for debugging with
GEMCODE_INCLUDE_THOUGHT_SUMMARIES=1(increases tokens/cost). - Fine-tune explicitly:
GEMCODE_THINKING_LEVEL=minimal|low|medium|high(Gemini 3.x only)GEMCODE_THINKING_BUDGET=0|-1|1024(Gemini 2.5 only)
- Additionally, when
model_modeis set tofast|balanced|qualityand you haven't provided explicitGEMCODE_THINKING_*overrides:- Gemini 3.x auto-maps
fast|balanced|qualitytothinkingLevel - Gemini 2.5 auto-maps
fast|balanced|qualitytothinkingBudget
- Gemini 3.x auto-maps
- If
model_mode=auto, GemCode leaves thinking unmodified.
- Persistent memory (optional): set
GEMCODE_ENABLE_MEMORY=1to ingest conversation snippets and retrieve relevant memories on future turns. - Project context: optional
GEMINI.mdin the project root is injected into the system instruction.
Permissions
GEMCODE_PERMISSION_MODE=strict: writes andrun_commandare blocked unless the command name is inGEMCODE_ALLOW_COMMANDS.default: reads always allowed; writes require--yes; shell runs only allowlisted commands (see.env.example).- In-run HITL permission ask (optional):
- Enable with
--interactive-askorGEMCODE_INTERACTIVE_PERMISSION_ASK=1. - When enabled and you did NOT pass
--yes, GemCode prompts you in the terminal to approve mutating tools (write_file,search_replace) and computer-use actions (browser automation). - If you don’t approve, the tool call is blocked (no silent re-execution).
- Enable with
When tools are blocked by policy, the consecutive-tool circuit breaker does not count those policy rejections as “tool failures”.
Optional debugging: set GEMCODE_EMIT_TOOL_USE_SUMMARIES=1 to write a lightweight tool_result record per tool into .gemcode/audit.log.
Optional MCP
Install with pip install -e ".[mcp]" and create .gemcode/mcp.json (see gemcode/mcp_loader.py). Run with --mcp to attach configured servers.
Vertex AI / Interactions API
See src/gemcode/vertex.py and src/gemcode/interactions.py for environment variables and future wiring.
Tools and “Powers”
GemCode wires tools into Gemini via ADK in a Claude Code–style outer/inner loop:
- Outer loop (your CLI / session) sets model + tools + safety gates and then streams the resulting Events.
- Inner loop (inside ADK) repeatedly calls the model and executes tools until completion or stop conditions.
Core function tools (custom, always available)
GemCode always exposes a set of function tools you can use to read and edit the user’s project.
- Read-only tools (typically allowed without
--yes):read_filelist_directoryglob_filesgrep_content
- Mutating tools (require
--yesunless your policy blocks them):write_filesearch_replace
- Shell execution:
run_command(guarded byGEMCODE_ALLOW_COMMANDSfrom.env.exampleandGEMCODE_PERMISSION_MODE).
Tool execution is still controlled by permission gates and then governed by GemCode’s circuit breaker + recovery behavior.
In-run interactive permission ask (HITL)
GemCode can switch from “fail closed unless you re-run with --yes” to an
in-run approval workflow:
- If enabled (
--interactive-ask/GEMCODE_INTERACTIVE_PERMISSION_ASK=1) and you did not pass--yes, any mutating tool call or computer-use action will trigger a terminal prompt. - Approving continues the same run; rejecting blocks the tool call.
This applies to both the standard CLI (gemcode "...") and the Kairos daemon (gemcode kairos).
Kairos proactive scheduler (daemon)
gemcode kairos runs a long-lived scheduler that turns prompts into queued
jobs:
- You type one prompt per line into stdin; each line becomes a job.
- Jobs are run with a priority queue; the daemon also exposes Kairos tools so
the model itself can
kairos_enqueue_prompt()additional work.
Kairos tools available to the model (per job):
kairos_sleep_ms(duration_ms: int): pauses just that job forduration_mswithout blocking other queued jobs.kairos_enqueue_prompt(prompt: str, priority: int = 0, session_id: str | None = None): enqueues a new job. Ifsession_idis omitted, it defaults to the current job’s session.
Priority defaults for stdin-enqueued jobs are controlled by --default-priority.
Deep research (built-in Gemini tools + optional tool combination)
When deep research is enabled (CLI --deep-research or GEMCODE_ENABLE_DEEP_RESEARCH=1),
GemCode injects Gemini built-in tools:
google_searchurl_contextgoogle_maps_grounding(optional; only injected when explicitly enabled via--maps-groundingorGEMCODE_ENABLE_MAPS_GROUNDING=1)
On Gemini 3.x models, GemCode can additionally enable Gemini’s built-in tool context circulation so built-in results (Search/URL/Maps) can be combined with your custom tools in the same workflow:
- Controlled by
GEMCODE_TOOL_COMBINATION_MODE/--tool-combination-mode(deep_research|always|never|auto, default:deep_research).
Embeddings (semantic retrieval + embedding-backed memory)
When embeddings are enabled (--embeddings or GEMCODE_ENABLE_EMBEDDINGS=1),
GemCode injects a semantic retrieval tool:
semantic_search_files(embeds query + candidate file chunks, ranks via cosine similarity).
If you also enable persistent memory ingestion (GEMCODE_ENABLE_MEMORY=1),
GemCode uses embedding-backed memory storage:
EmbeddingFileMemoryServicestores both text and vectors in.gemcode/memories.jsonl.- Retrieval uses cosine similarity and falls back to keyword search when needed.
Computer Use (optional, gated browser automation)
When computer use is enabled (GEMCODE_ENABLE_COMPUTER_USE=1 or --capability-mode computer),
GemCode adds an ADK ComputerUseToolset backed by Playwright (BrowserComputer).
Notes:
- Requires optional deps:
playwright(and you should runplaywright install). - Browser automation actions are still permission-gated:
- In
defaultpermission mode, computer-use tool calls require--yes. - In
strictmode, computer use is denied.
- In
- Headless mode is controlled by
GEMCODE_COMPUTER_HEADLESS.
Live audio (Gemini Live API via ADK)
GemCode also supports real-time audio sessions via gemcode live-audio.
It streams microphone audio to Gemini using ADK’s Runner.run_live() and
prints model text parts.
This MVP requires optional deps:
sounddevicenumpy
You can configure:
- record duration (
--seconds) - PCM sample rate (
--rate) - optional language (
--language) - optional model override (
--model, must support AUDIO streaming)
Memory ingestion + prompt suggestions
After each run, GemCodeTerminalHooksPlugin:
- writes a structured terminal reason to
.gemcode/audit.log - optionally ingests the session into memory (via ADK memory integration)
- optionally generates “next-step” prompt suggestions:
- uses
gemcode/prompt_suggestions.pyheuristics - if
GEMCODE_PROMPT_SUGGESTIONS_USE_INTERACTIONS=1, it can also call Gemini using the Interactions API to produce a better suggestion
- uses
- runs your stopHooks-like post-turn script from
GEMCODE_POST_TURN_HOOK(or.gemcode/hooks/post_turn)
Safety, circuit breaker, and recovery
GemCode enforces:
- Permission gates via ADK callbacks:
GEMCODE_PERMISSION_MODE=strictblocks writes and shell (unless allowlisted)- mutating + computer-use tool calls require
--yesin default mode
- Consecutive tool failure circuit breaker:
- capped by
GEMCODE_MAX_CONSECUTIVE_TOOL_FAILURES - policy rejections don’t increment the streak
- capped by
- Recovery-loop:
- ADK
ReflectAndRetryToolPlugin-based retries on retryable tool errors - recovery skips policy denials and circuit breaker blocks
- ADK
Development
pip install -e ".[dev]"
pytest
References (local only)
Do not commit proprietary leaked trees into this package. Keep claude-code-leaked/ and similar folders outside version control or in a private mirror.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file gemcode-0.3.70.tar.gz.
File metadata
- Download URL: gemcode-0.3.70.tar.gz
- Upload date:
- Size: 204.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d2ba7be5ceac01e420037ab0317679fd043ba637a710d934e1165a73f5c19093
|
|
| MD5 |
3d7496463ede067028d4d562b98a75e7
|
|
| BLAKE2b-256 |
e2b1928bad0f9bdb2d2cf10f91a4c66c25db55a88bbf60bea6b2391922500bd8
|
Provenance
The following attestation bundles were made for gemcode-0.3.70.tar.gz:
Publisher:
publish-pypi.yml on spiderdev27/GemCode
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
gemcode-0.3.70.tar.gz -
Subject digest:
d2ba7be5ceac01e420037ab0317679fd043ba637a710d934e1165a73f5c19093 - Sigstore transparency entry: 1247038086
- Sigstore integration time:
-
Permalink:
spiderdev27/GemCode@5aab417f33260d4d1c6170060a6824ace4bc4b22 -
Branch / Tag:
refs/tags/v0.3.70 - Owner: https://github.com/spiderdev27
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@5aab417f33260d4d1c6170060a6824ace4bc4b22 -
Trigger Event:
push
-
Statement type:
File details
Details for the file gemcode-0.3.70-py3-none-any.whl.
File metadata
- Download URL: gemcode-0.3.70-py3-none-any.whl
- Upload date:
- Size: 224.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dd6c209b9b25178c83b2bf3e7abbd15eb3bdc24f8134064bdf9e0325c491c46f
|
|
| MD5 |
fc2ce1be7902678bc0cf2a06d45fb330
|
|
| BLAKE2b-256 |
efcbcaf2dcec3791322204ed09300ecb723203ea689302e953b27a69f623676f
|
Provenance
The following attestation bundles were made for gemcode-0.3.70-py3-none-any.whl:
Publisher:
publish-pypi.yml on spiderdev27/GemCode
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
gemcode-0.3.70-py3-none-any.whl -
Subject digest:
dd6c209b9b25178c83b2bf3e7abbd15eb3bdc24f8134064bdf9e0325c491c46f - Sigstore transparency entry: 1247038087
- Sigstore integration time:
-
Permalink:
spiderdev27/GemCode@5aab417f33260d4d1c6170060a6824ace4bc4b22 -
Branch / Tag:
refs/tags/v0.3.70 - Owner: https://github.com/spiderdev27
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@5aab417f33260d4d1c6170060a6824ace4bc4b22 -
Trigger Event:
push
-
Statement type: