gemcode 0.3.85__py3-none-any.whl → 0.3.86__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- gemcode/agent.py +27 -7
- gemcode/cli.py +13 -1
- gemcode/repl_slash.py +10 -10
- gemcode/session_runtime.py +40 -0
- gemcode/tools/__init__.py +8 -0
- gemcode/veomem_bridge.py +30 -1
- gemcode-0.3.86.dist-info/METADATA +416 -0
- {gemcode-0.3.85.dist-info → gemcode-0.3.86.dist-info}/RECORD +12 -12
- gemcode-0.3.85.dist-info/METADATA +0 -806
- {gemcode-0.3.85.dist-info → gemcode-0.3.86.dist-info}/WHEEL +0 -0
- {gemcode-0.3.85.dist-info → gemcode-0.3.86.dist-info}/entry_points.txt +0 -0
- {gemcode-0.3.85.dist-info → gemcode-0.3.86.dist-info}/licenses/LICENSE +0 -0
- {gemcode-0.3.85.dist-info → gemcode-0.3.86.dist-info}/top_level.txt +0 -0
gemcode/agent.py
CHANGED
|
@@ -103,14 +103,15 @@ def _chain_before_model_callbacks(*callbacks):
|
|
|
103
103
|
|
|
104
104
|
def _load_gemini_md(project_root: Path) -> str:
|
|
105
105
|
"""
|
|
106
|
-
Load
|
|
106
|
+
Load project instruction markdown / .gemcode/NOTES.md from a interactive CLI–style hierarchy.
|
|
107
107
|
|
|
108
108
|
Priority (later entries override earlier ones, all are concatenated):
|
|
109
109
|
1. ~/.gemcode/GEMINI.md — user-global instructions (all projects)
|
|
110
|
-
2. Walk UP from project_root: each directory's
|
|
110
|
+
2. Walk UP from project_root: each directory's `gemcode.md` / `GEMINI.md`
|
|
111
111
|
(org-level files at higher dirs, project-level at project_root)
|
|
112
|
-
3. project_root/
|
|
113
|
-
4. project_root
|
|
112
|
+
3. project_root/gemcode.md — the primary project instructions
|
|
113
|
+
4. project_root/GEMINI.md — backward-compatible legacy location
|
|
114
|
+
5. project_root/.gemcode/GEMINI.md — alternative location
|
|
114
115
|
5. project_root/.gemcode/notes.md — agent auto-generated notes (read-only context)
|
|
115
116
|
|
|
116
117
|
Max total: 80,000 chars. Each file is capped at 30,000 chars.
|
|
@@ -118,7 +119,14 @@ def _load_gemini_md(project_root: Path) -> str:
|
|
|
118
119
|
"""
|
|
119
120
|
import re
|
|
120
121
|
|
|
121
|
-
_NAMES = (
|
|
122
|
+
_NAMES = (
|
|
123
|
+
"gemcode.md",
|
|
124
|
+
"GEMCODE.md",
|
|
125
|
+
"GEMINI.md",
|
|
126
|
+
"gemini.md",
|
|
127
|
+
".gemcode/GEMINI.md",
|
|
128
|
+
".gemcode/gemini.md",
|
|
129
|
+
)
|
|
122
130
|
_FILE_CAP = 30_000
|
|
123
131
|
_TOTAL_CAP = 80_000
|
|
124
132
|
_COMMENT_RE = re.compile(r"<!--.*?-->", re.DOTALL)
|
|
@@ -162,8 +170,15 @@ def _load_gemini_md(project_root: Path) -> str:
|
|
|
162
170
|
for name in _NAMES:
|
|
163
171
|
_add(ancestor / name)
|
|
164
172
|
|
|
165
|
-
# 3+
|
|
166
|
-
for name in (
|
|
173
|
+
# 3+5. Project-root level instructions (primary location + compatibility)
|
|
174
|
+
for name in (
|
|
175
|
+
"gemcode.md",
|
|
176
|
+
"GEMCODE.md",
|
|
177
|
+
"GEMINI.md",
|
|
178
|
+
"gemini.md",
|
|
179
|
+
".gemcode/GEMINI.md",
|
|
180
|
+
".gemcode/gemini.md",
|
|
181
|
+
):
|
|
167
182
|
_add(project_root / name)
|
|
168
183
|
|
|
169
184
|
# 5. Agent-generated notes (informational context, not instructions)
|
|
@@ -312,6 +327,11 @@ def _build_runtime_facts(cfg: GemCodeConfig) -> str:
|
|
|
312
327
|
"\n\n## VeoMem recall (auto-captured, progressive)\n"
|
|
313
328
|
"This section is automatically generated from prior tool usage and summaries. "
|
|
314
329
|
"Treat it as helpful context; do not restate it verbatim to the user.\n"
|
|
330
|
+
"If you need deeper details about a specific prior observation, use the "
|
|
331
|
+
"3-step retrieval flow with tools:\n"
|
|
332
|
+
"- `veomem_search(query=...)` → get an index of relevant observation IDs\n"
|
|
333
|
+
"- `veomem_timeline(id=...)` → get compact neighbors around an anchor ID\n"
|
|
334
|
+
"- `veomem_get_observations(ids=...)` → fetch full text for selected IDs\n"
|
|
315
335
|
f"{t.strip()}\n"
|
|
316
336
|
)
|
|
317
337
|
except Exception:
|
gemcode/cli.py
CHANGED
|
@@ -130,18 +130,30 @@ def _initialize_gemcode_project(cfg: GemCodeConfig) -> None:
|
|
|
130
130
|
"""
|
|
131
131
|
root = cfg.project_root.resolve()
|
|
132
132
|
gem_dir = root / ".gemcode"
|
|
133
|
+
gemcode_md = root / "gemcode.md"
|
|
133
134
|
already_there = gem_dir.is_dir()
|
|
134
135
|
try:
|
|
135
136
|
gem_dir.mkdir(parents=True, exist_ok=True)
|
|
136
137
|
except OSError as e:
|
|
137
138
|
print(f"[gemcode] warning: could not create {gem_dir}: {e}", file=sys.stderr)
|
|
138
139
|
return
|
|
140
|
+
if not gemcode_md.exists():
|
|
141
|
+
try:
|
|
142
|
+
gemcode_md.write_text(
|
|
143
|
+
"# Project instructions\n\n"
|
|
144
|
+
"- Describe the project purpose here.\n"
|
|
145
|
+
"- Add build, test, and lint commands.\n"
|
|
146
|
+
"- Add architecture notes and conventions GemCode should follow.\n",
|
|
147
|
+
encoding="utf-8",
|
|
148
|
+
)
|
|
149
|
+
except OSError as e:
|
|
150
|
+
print(f"[gemcode] warning: could not create {gemcode_md}: {e}", file=sys.stderr)
|
|
139
151
|
if not already_there:
|
|
140
152
|
print(
|
|
141
153
|
"\n── GemCode · Project folder ready ──\n"
|
|
142
154
|
f" Workspace: {root}\n"
|
|
143
155
|
f" Config & session data: {gem_dir}/\n"
|
|
144
|
-
"
|
|
156
|
+
f" Project instructions: {gemcode_md.name}\n"
|
|
145
157
|
"── Ready. ──\n",
|
|
146
158
|
file=sys.stderr,
|
|
147
159
|
)
|
gemcode/repl_slash.py
CHANGED
|
@@ -1172,15 +1172,15 @@ async def process_repl_slash(
|
|
|
1172
1172
|
return ReplSlashResult(skip_model_turn=True)
|
|
1173
1173
|
|
|
1174
1174
|
if name == "init":
|
|
1175
|
-
|
|
1176
|
-
if
|
|
1177
|
-
out(f"
|
|
1175
|
+
gemcode_md = cfg.project_root / "gemcode.md"
|
|
1176
|
+
if gemcode_md.exists() and (sc.args or "").strip().lower() not in ("force", "overwrite", "-f"):
|
|
1177
|
+
out(f"gemcode.md already exists at {gemcode_md}.")
|
|
1178
1178
|
out("Use /init force to regenerate it, or edit it manually.")
|
|
1179
1179
|
out()
|
|
1180
1180
|
return ReplSlashResult(skip_model_turn=True)
|
|
1181
|
-
# Dispatch to the model to analyze the project and write
|
|
1181
|
+
# Dispatch to the model to analyze the project and write gemcode.md.
|
|
1182
1182
|
init_prompt = (
|
|
1183
|
-
"Analyze this codebase and generate a
|
|
1183
|
+
"Analyze this codebase and generate a gemcode.md file for me.\n\n"
|
|
1184
1184
|
"To do this:\n"
|
|
1185
1185
|
"1. Run `list_directory('.')` to understand the project structure\n"
|
|
1186
1186
|
"2. Read `package.json`, `pyproject.toml`, `go.mod`, `Cargo.toml`, `README.md` "
|
|
@@ -1188,9 +1188,9 @@ async def process_repl_slash(
|
|
|
1188
1188
|
"3. Look at the source directory structure (src/, lib/, app/, etc.)\n"
|
|
1189
1189
|
"4. Check for test directories and test runner config\n"
|
|
1190
1190
|
"5. Look for linting/formatting config files (.eslintrc, .prettierrc, ruff.toml, etc.)\n\n"
|
|
1191
|
-
"Write **only** to `
|
|
1191
|
+
"Write **only** to `gemcode.md` at the project root. Do **not** create "
|
|
1192
1192
|
"`CLAUDE.md`, `AGENTS.md`, `.cursorrules`, or similar.\n\n"
|
|
1193
|
-
"Then write a
|
|
1193
|
+
"Then write a gemcode.md file at the project root containing:\n"
|
|
1194
1194
|
"# Project Name\n"
|
|
1195
1195
|
"One-sentence description.\n\n"
|
|
1196
1196
|
"## Build & Test\n"
|
|
@@ -1208,10 +1208,10 @@ async def process_repl_slash(
|
|
|
1208
1208
|
"## Workflow\n"
|
|
1209
1209
|
"- Any git branching rules from README or CONTRIBUTING\n"
|
|
1210
1210
|
"- PR/commit conventions\n\n"
|
|
1211
|
-
"Keep it under 200 lines. Write the file to
|
|
1211
|
+
"Keep it under 200 lines. Write the file to gemcode.md now."
|
|
1212
1212
|
)
|
|
1213
|
-
out("Analyzing project to generate
|
|
1214
|
-
out("(GemCode will read the project structure and write a starting
|
|
1213
|
+
out("Analyzing project to generate gemcode.md…")
|
|
1214
|
+
out("(GemCode will read the project structure and write a starting gemcode.md)")
|
|
1215
1215
|
out()
|
|
1216
1216
|
return ReplSlashResult(model_prompt=init_prompt)
|
|
1217
1217
|
|
gemcode/session_runtime.py
CHANGED
|
@@ -404,6 +404,46 @@ def create_runner(cfg: GemCodeConfig, extra_tools: list | None = None) -> Runner
|
|
|
404
404
|
except Exception:
|
|
405
405
|
pass # OpenAPIToolset not in this ADK version — continue without
|
|
406
406
|
|
|
407
|
+
# ── AFC compatibility prompt (optional) ───────────────────────────────────
|
|
408
|
+
# Gemini Automatic Function Calling (AFC) only works when the tool list is
|
|
409
|
+
# composed of Python callables. Some ADK toolsets (MCP/OpenAPI/built-in
|
|
410
|
+
# declarations) may be non-callable and cause AFC to be disabled.
|
|
411
|
+
#
|
|
412
|
+
# If we're in an interactive terminal and the user opted into prompting,
|
|
413
|
+
# ask whether to keep "all tools" (AFC disabled) or restrict to callables
|
|
414
|
+
# (AFC enabled).
|
|
415
|
+
try:
|
|
416
|
+
import os
|
|
417
|
+
import sys
|
|
418
|
+
|
|
419
|
+
prompt_afc = os.environ.get("GEMCODE_AFC_PROMPT", "1").strip().lower() in ("1", "true", "yes", "on")
|
|
420
|
+
if prompt_afc and hasattr(sys.stdin, "isatty") and sys.stdin.isatty():
|
|
421
|
+
tools_list = list(merged_extra_tools or [])
|
|
422
|
+
noncallable = [t for t in tools_list if not callable(t)]
|
|
423
|
+
if noncallable and getattr(cfg, "_afc_choice", None) not in ("all", "callables"):
|
|
424
|
+
print(
|
|
425
|
+
"\n[gemcode] AFC compatibility\n"
|
|
426
|
+
"Gemini Automatic Function Calling (AFC) works best with Python callables only.\n"
|
|
427
|
+
"Some enabled toolsets appear non-callable, which can disable AFC.\n\n"
|
|
428
|
+
"Choose tool mode for this session:\n"
|
|
429
|
+
" [Enter] all tools (recommended; AFC may be disabled)\n"
|
|
430
|
+
" c callable-only tools (keeps AFC; disables MCP/OpenAPI/toolsets)\n",
|
|
431
|
+
file=sys.stderr,
|
|
432
|
+
)
|
|
433
|
+
try:
|
|
434
|
+
ans = input("afc> ").strip().lower()
|
|
435
|
+
except EOFError:
|
|
436
|
+
ans = ""
|
|
437
|
+
if ans.startswith("c"):
|
|
438
|
+
object.__setattr__(cfg, "_afc_choice", "callables")
|
|
439
|
+
else:
|
|
440
|
+
object.__setattr__(cfg, "_afc_choice", "all")
|
|
441
|
+
|
|
442
|
+
if getattr(cfg, "_afc_choice", None) == "callables":
|
|
443
|
+
merged_extra_tools = [t for t in tools_list if callable(t)] or None
|
|
444
|
+
except Exception:
|
|
445
|
+
pass
|
|
446
|
+
|
|
407
447
|
# Computer-use: ADK ComputerUseToolset backed by our Playwright BrowserComputer.
|
|
408
448
|
# Probe Playwright BEFORE building the agent so model routing (which runs
|
|
409
449
|
# inside build_root_agent → pick_effective_model) never switches to
|
gemcode/tools/__init__.py
CHANGED
|
@@ -20,6 +20,7 @@ from gemcode.checkpoints import list_checkpoints as _list_checkpoints, undo_chec
|
|
|
20
20
|
from gemcode.tools.curated_memory import make_curated_memory_tools
|
|
21
21
|
from gemcode.tools.compress_memory import make_compress_memory_tool
|
|
22
22
|
from gemcode.tools.skills import make_skill_tools
|
|
23
|
+
from gemcode.tools.veomem_tools import make_veomem_tools
|
|
23
24
|
|
|
24
25
|
|
|
25
26
|
def _get_load_memory_tool():
|
|
@@ -153,12 +154,19 @@ def build_function_tools(cfg: GemCodeConfig, *, include_subtask: bool = True) ->
|
|
|
153
154
|
read_curated_memory,
|
|
154
155
|
# Optional: compress memory files (markdown only; safe guards apply)
|
|
155
156
|
compress_memory_file,
|
|
157
|
+
# Optional: VeoMem recall tools (3-step search/timeline/fetch).
|
|
158
|
+
# Enabled via GEMCODE_VEOMEM=1.
|
|
156
159
|
# GemSkills (on-demand playbooks)
|
|
157
160
|
list_skills,
|
|
158
161
|
load_skill,
|
|
159
162
|
skills_manifest,
|
|
160
163
|
]
|
|
161
164
|
|
|
165
|
+
try:
|
|
166
|
+
tools.extend(make_veomem_tools(cfg))
|
|
167
|
+
except Exception:
|
|
168
|
+
pass
|
|
169
|
+
|
|
162
170
|
# ADK load_memory: explicit on-demand memory search (complements preload_memory).
|
|
163
171
|
# Only add when memory is enabled so the tool doesn't appear when there's no
|
|
164
172
|
# memory service to call into.
|
gemcode/veomem_bridge.py
CHANGED
|
@@ -24,6 +24,16 @@ def _summarize_tool_result(result: dict[str, Any]) -> str:
|
|
|
24
24
|
if result.get("error"):
|
|
25
25
|
e = str(result.get("error"))
|
|
26
26
|
return f"error: {e[:800]}"
|
|
27
|
+
|
|
28
|
+
def _clip_str(x: Any, n: int) -> str:
|
|
29
|
+
if x is None:
|
|
30
|
+
return ""
|
|
31
|
+
s = str(x)
|
|
32
|
+
s = s.strip()
|
|
33
|
+
if len(s) <= n:
|
|
34
|
+
return s
|
|
35
|
+
return s[:n].rstrip() + "…"
|
|
36
|
+
|
|
27
37
|
parts: list[str] = []
|
|
28
38
|
for k in ("exit_code", "path", "backup_path", "count", "chars_before", "chars_after"):
|
|
29
39
|
if k in result:
|
|
@@ -31,7 +41,26 @@ def _summarize_tool_result(result: dict[str, Any]) -> str:
|
|
|
31
41
|
for k in ("stdout", "stderr"):
|
|
32
42
|
v = result.get(k)
|
|
33
43
|
if isinstance(v, str) and v.strip():
|
|
34
|
-
parts.append(f"{k}={v
|
|
44
|
+
parts.append(f"{k}={_clip_str(v, 800)}")
|
|
45
|
+
|
|
46
|
+
# Web search results can be high-signal but are structured; make them searchable.
|
|
47
|
+
try:
|
|
48
|
+
results = result.get("results")
|
|
49
|
+
if isinstance(results, list) and results:
|
|
50
|
+
pieces: list[str] = []
|
|
51
|
+
for r in results[:5]:
|
|
52
|
+
if not isinstance(r, dict):
|
|
53
|
+
continue
|
|
54
|
+
title = _clip_str(r.get("title"), 120)
|
|
55
|
+
url = _clip_str(r.get("url"), 140)
|
|
56
|
+
snippet = _clip_str(r.get("snippet"), 180)
|
|
57
|
+
if title or url or snippet:
|
|
58
|
+
pieces.append(f"{title} ({url}) {snippet}".strip())
|
|
59
|
+
if pieces:
|
|
60
|
+
parts.append("results=[" + " | ".join(pieces) + "]")
|
|
61
|
+
except Exception:
|
|
62
|
+
pass
|
|
63
|
+
|
|
35
64
|
return " ".join(parts).strip()
|
|
36
65
|
|
|
37
66
|
|
|
@@ -0,0 +1,416 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: gemcode
|
|
3
|
+
Version: 0.3.86
|
|
4
|
+
Summary: Local-first coding agent on Google Gemini + ADK
|
|
5
|
+
Author: GemCode Contributors
|
|
6
|
+
License: Apache License
|
|
7
|
+
Version 2.0, January 2004
|
|
8
|
+
http://www.apache.org/licenses/
|
|
9
|
+
|
|
10
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
11
|
+
|
|
12
|
+
1. Definitions.
|
|
13
|
+
|
|
14
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
15
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
16
|
+
|
|
17
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
18
|
+
the copyright owner that is granting the License.
|
|
19
|
+
|
|
20
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
21
|
+
other entities that control, are controlled by, or are under common
|
|
22
|
+
control with that entity. For the purposes of this definition,
|
|
23
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
24
|
+
direction or management of such entity, whether by contract or
|
|
25
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
26
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
27
|
+
|
|
28
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
29
|
+
exercising permissions granted by this License.
|
|
30
|
+
|
|
31
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
32
|
+
including but not limited to software source code, documentation
|
|
33
|
+
source, and configuration files.
|
|
34
|
+
|
|
35
|
+
"Object" form shall mean any form resulting from mechanical
|
|
36
|
+
transformation or translation of a Source form, including but
|
|
37
|
+
not limited to compiled object code, generated documentation,
|
|
38
|
+
and conversions to other media types.
|
|
39
|
+
|
|
40
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
41
|
+
Object form, made available under the License, as indicated by a
|
|
42
|
+
copyright notice that is included in or attached to the work
|
|
43
|
+
(an example is provided in the Appendix below).
|
|
44
|
+
|
|
45
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
46
|
+
form, that is based on (or derived from) the Work and for which the
|
|
47
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
48
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
49
|
+
of this License, Derivative Works shall not include works that remain
|
|
50
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
51
|
+
the Work and Derivative Works thereof.
|
|
52
|
+
|
|
53
|
+
"Contribution" shall mean any work of authorship, including
|
|
54
|
+
the original version of the Work and any modifications or additions
|
|
55
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
56
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
57
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
58
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
59
|
+
means any form of electronic, verbal, or written communication sent
|
|
60
|
+
to the Licensor or its representatives, including but not limited to
|
|
61
|
+
communication on electronic mailing lists, source code control systems,
|
|
62
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
63
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
64
|
+
excluding communication that is conspicuously marked or otherwise
|
|
65
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
66
|
+
|
|
67
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
68
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
69
|
+
subsequently incorporated within the Work.
|
|
70
|
+
|
|
71
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
72
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
73
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
74
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
75
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
76
|
+
Work and such Derivative Works in Source or Object form.
|
|
77
|
+
|
|
78
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
79
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
80
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
81
|
+
(except as stated in this section) patent license to make, have made,
|
|
82
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
83
|
+
where such license applies only to those patent claims licensable
|
|
84
|
+
by such Contributor that are necessarily infringed by their
|
|
85
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
86
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
87
|
+
institute patent litigation against any entity (including a
|
|
88
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
89
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
90
|
+
or contributory patent infringement, then any patent licenses
|
|
91
|
+
granted to You under this License for that Work shall terminate
|
|
92
|
+
as of the date such litigation is filed.
|
|
93
|
+
|
|
94
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
95
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
96
|
+
modifications, and in Source or Object form, provided that You
|
|
97
|
+
meet the following conditions:
|
|
98
|
+
|
|
99
|
+
(a) You must give any other recipients of the Work or
|
|
100
|
+
Derivative Works a copy of this License; and
|
|
101
|
+
|
|
102
|
+
(b) You must cause any modified files to carry prominent notices
|
|
103
|
+
stating that You changed the files; and
|
|
104
|
+
|
|
105
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
106
|
+
that You distribute, all copyright, patent, trademark, and
|
|
107
|
+
attribution notices from the Source form of the Work,
|
|
108
|
+
excluding those notices that do not pertain to any part of
|
|
109
|
+
the Derivative Works; and
|
|
110
|
+
|
|
111
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
112
|
+
distribution, then any Derivative Works that You distribute must
|
|
113
|
+
include a readable copy of the attribution notices contained
|
|
114
|
+
within such NOTICE file, excluding those notices that do not
|
|
115
|
+
pertain to any part of the Derivative Works, in at least one
|
|
116
|
+
of the following places: within a NOTICE text file distributed
|
|
117
|
+
as part of the Derivative Works; within the Source form or
|
|
118
|
+
documentation, if provided along with the Derivative Works; or,
|
|
119
|
+
within a display generated by the Derivative Works, if and
|
|
120
|
+
wherever such third-party notices normally appear. The contents
|
|
121
|
+
of the NOTICE file are for informational purposes only and
|
|
122
|
+
do not modify the License. You may add Your own attribution
|
|
123
|
+
notices within Derivative Works that You distribute, alongside
|
|
124
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
125
|
+
that such additional attribution notices cannot be construed
|
|
126
|
+
as modifying the License.
|
|
127
|
+
|
|
128
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
129
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
130
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
131
|
+
this License, without any additional terms or conditions.
|
|
132
|
+
|
|
133
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
134
|
+
names, trademarks, service marks, or product names of the Licensor.
|
|
135
|
+
|
|
136
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
137
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
138
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
139
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
140
|
+
|
|
141
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
142
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
143
|
+
unless required by applicable law, shall any Contributor be liable
|
|
144
|
+
to You for damages, including any direct, indirect, special,
|
|
145
|
+
incidental, or consequential damages arising in any way out of the
|
|
146
|
+
use of the Work.
|
|
147
|
+
|
|
148
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
149
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
150
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
151
|
+
or other liability obligations and/or rights consistent with this
|
|
152
|
+
License. However, in accepting such obligations, You may act only
|
|
153
|
+
on Your own behalf and on Your sole responsibility.
|
|
154
|
+
|
|
155
|
+
END OF TERMS AND CONDITIONS
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
Project-URL: Homepage, https://github.com/spiderdev27/GemCode
|
|
159
|
+
Project-URL: Repository, https://github.com/spiderdev27/GemCode
|
|
160
|
+
Project-URL: Issues, https://github.com/spiderdev27/GemCode/issues
|
|
161
|
+
Keywords: ai,agent,coding,gemini,adk,cli,tui
|
|
162
|
+
Classifier: Development Status :: 3 - Alpha
|
|
163
|
+
Classifier: Environment :: Console
|
|
164
|
+
Classifier: Intended Audience :: Developers
|
|
165
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
166
|
+
Classifier: Operating System :: OS Independent
|
|
167
|
+
Classifier: Programming Language :: Python :: 3
|
|
168
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
169
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
170
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
171
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
172
|
+
Classifier: Topic :: Software Development
|
|
173
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
174
|
+
Classifier: Topic :: Terminals
|
|
175
|
+
Requires-Python: >=3.11
|
|
176
|
+
Description-Content-Type: text/markdown
|
|
177
|
+
License-File: LICENSE
|
|
178
|
+
Requires-Dist: google-adk>=1.0.0
|
|
179
|
+
Requires-Dist: google-genai>=1.0.0
|
|
180
|
+
Requires-Dist: python-dotenv>=1.0.0
|
|
181
|
+
Requires-Dist: rich>=13.0.0
|
|
182
|
+
Requires-Dist: prompt_toolkit>=3.0.0
|
|
183
|
+
Provides-Extra: dev
|
|
184
|
+
Requires-Dist: pytest>=8.0.0; extra == "dev"
|
|
185
|
+
Requires-Dist: pytest-asyncio>=0.24.0; extra == "dev"
|
|
186
|
+
Provides-Extra: mcp
|
|
187
|
+
Requires-Dist: mcp>=1.0.0; extra == "mcp"
|
|
188
|
+
Dynamic: license-file
|
|
189
|
+
|
|
190
|
+
# GemCode User Manual
|
|
191
|
+
|
|
192
|
+
This document is the primary user-facing manual for GemCode. It explains the product at a high level and points to the subsystem-specific documentation pages that provide production-grade depth.
|
|
193
|
+
|
|
194
|
+
## What GemCode is
|
|
195
|
+
GemCode is a local-first coding agent built around Google Gemini and the Google Agent Development Kit (ADK). It operates against a chosen project root and combines:
|
|
196
|
+
- a configuration model
|
|
197
|
+
- a runtime runner
|
|
198
|
+
- a root language-model agent
|
|
199
|
+
- a configurable tool inventory
|
|
200
|
+
- project-local state under `.gemcode/`
|
|
201
|
+
|
|
202
|
+
GemCode is designed for repository-native work rather than copy-paste chat workflows.
|
|
203
|
+
|
|
204
|
+
## Runtime modes
|
|
205
|
+
|
|
206
|
+
| Mode | Purpose |
|
|
207
|
+
|---|---|
|
|
208
|
+
| One-shot CLI | Single prompt/response runs |
|
|
209
|
+
| REPL | Stateful terminal interaction |
|
|
210
|
+
| TUI | Scrollback terminal UI over the REPL runtime |
|
|
211
|
+
| IDE stdio | Editor integration over JSONL stdin/stdout |
|
|
212
|
+
| Kaira | Priority-queue scheduler for background jobs |
|
|
213
|
+
| Live audio | Microphone-driven Gemini Live sessions |
|
|
214
|
+
|
|
215
|
+
## Recommended reading order
|
|
216
|
+
|
|
217
|
+
### 1. Setup and first use
|
|
218
|
+
- [`../docs/install.md`](../docs/install.md)
|
|
219
|
+
|
|
220
|
+
### 2. Interactive use
|
|
221
|
+
- [`../docs/cli-and-repl.md`](../docs/cli-and-repl.md)
|
|
222
|
+
|
|
223
|
+
### 3. Configuration and local assets
|
|
224
|
+
- [`../docs/configuration.md`](../docs/configuration.md)
|
|
225
|
+
|
|
226
|
+
### 4. Tooling and safety model
|
|
227
|
+
- [`../docs/tools-and-permissions.md`](../docs/tools-and-permissions.md)
|
|
228
|
+
|
|
229
|
+
### 5. Optional capability bundles
|
|
230
|
+
- [`../docs/capabilities.md`](../docs/capabilities.md)
|
|
231
|
+
|
|
232
|
+
### 6. Integrations
|
|
233
|
+
- [`../docs/integrations.md`](../docs/integrations.md)
|
|
234
|
+
- [`../docs/web-ui-contract.md`](../docs/web-ui-contract.md)
|
|
235
|
+
|
|
236
|
+
### 7. Operations and release
|
|
237
|
+
- [`../docs/operations.md`](../docs/operations.md)
|
|
238
|
+
|
|
239
|
+
### 8. `.gemcode/` state reference
|
|
240
|
+
- [`../docs/reference-gemcode-state.md`](../docs/reference-gemcode-state.md)
|
|
241
|
+
|
|
242
|
+
### 9. Architecture deep dive
|
|
243
|
+
- [`../docs/architecture.md`](../docs/architecture.md)
|
|
244
|
+
|
|
245
|
+
## Quickstart
|
|
246
|
+
|
|
247
|
+
### Install
|
|
248
|
+
```bash
|
|
249
|
+
cd gemcode
|
|
250
|
+
python3 -m venv .venv
|
|
251
|
+
source .venv/bin/activate
|
|
252
|
+
python3 -m pip install -e ".[dev]"
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
### Set your API key
|
|
256
|
+
```bash
|
|
257
|
+
export GOOGLE_API_KEY="your-key"
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### Start GemCode against a project
|
|
261
|
+
```bash
|
|
262
|
+
gemcode -C /path/to/project
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
### One-shot run
|
|
266
|
+
```bash
|
|
267
|
+
gemcode -C /path/to/project "Explain this repository"
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
### Mutating run
|
|
271
|
+
```bash
|
|
272
|
+
gemcode -C /path/to/project --yes "Fix the failing tests"
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
## Essential concepts
|
|
276
|
+
|
|
277
|
+
### Project root
|
|
278
|
+
Every GemCode run is anchored to a project root. This determines:
|
|
279
|
+
- what files are visible
|
|
280
|
+
- where `.gemcode/` state is stored
|
|
281
|
+
- what instruction files are loaded
|
|
282
|
+
- which repo-local assets are active
|
|
283
|
+
|
|
284
|
+
### `.gemcode/`
|
|
285
|
+
GemCode stores project-local state under `.gemcode/`, including:
|
|
286
|
+
- sessions
|
|
287
|
+
- logs
|
|
288
|
+
- artifacts
|
|
289
|
+
- memory
|
|
290
|
+
- skills
|
|
291
|
+
- rules
|
|
292
|
+
- output styles
|
|
293
|
+
- hooks
|
|
294
|
+
- integration config
|
|
295
|
+
|
|
296
|
+
Reference:
|
|
297
|
+
- [`../docs/reference-gemcode-state.md`](../docs/reference-gemcode-state.md)
|
|
298
|
+
|
|
299
|
+
### Project instruction files
|
|
300
|
+
GemCode supports project instruction files loaded by the agent layer. The live code treats `gemcode.md` as the primary project instruction file and supports `GEMINI.md` as a compatibility path.
|
|
301
|
+
|
|
302
|
+
Reference:
|
|
303
|
+
- [`../docs/configuration.md`](../docs/configuration.md)
|
|
304
|
+
|
|
305
|
+
### GemSkills
|
|
306
|
+
GemSkills are reusable prompt playbooks stored under:
|
|
307
|
+
- `.gemcode/skills/<name>/SKILL.md`
|
|
308
|
+
- `~/.gemcode/skills/<name>/SKILL.md`
|
|
309
|
+
|
|
310
|
+
They support:
|
|
311
|
+
- creation
|
|
312
|
+
- session loading
|
|
313
|
+
- one-shot invocation
|
|
314
|
+
- iterative editing
|
|
315
|
+
|
|
316
|
+
### Permissions
|
|
317
|
+
GemCode combines:
|
|
318
|
+
- workspace trust
|
|
319
|
+
- permission mode
|
|
320
|
+
- allow/deny settings
|
|
321
|
+
- blanket approval flags
|
|
322
|
+
- interactive approval prompts
|
|
323
|
+
|
|
324
|
+
Reference:
|
|
325
|
+
- [`../docs/tools-and-permissions.md`](../docs/tools-and-permissions.md)
|
|
326
|
+
|
|
327
|
+
## Common commands
|
|
328
|
+
|
|
329
|
+
### Inspect models
|
|
330
|
+
```bash
|
|
331
|
+
gemcode models
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
### Start the REPL
|
|
335
|
+
```bash
|
|
336
|
+
gemcode -C .
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
### Attach a file to a one-shot turn
|
|
340
|
+
```bash
|
|
341
|
+
gemcode -C . --attach ./report.pdf "Summarize this"
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
### Run the scheduler
|
|
345
|
+
```bash
|
|
346
|
+
gemcode kaira -C .
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
### Start the IDE bridge
|
|
350
|
+
```bash
|
|
351
|
+
gemcode ide --stdio
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
### Run live audio
|
|
355
|
+
```bash
|
|
356
|
+
gemcode live-audio -C .
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
## REPL command highlights
|
|
360
|
+
|
|
361
|
+
| Command | Purpose |
|
|
362
|
+
|---|---|
|
|
363
|
+
| `/help` | Command summary |
|
|
364
|
+
| `/status` | Model, capabilities, context, and runtime telemetry |
|
|
365
|
+
| `/context` | Context pressure and prompt budget telemetry |
|
|
366
|
+
| `/cost` | Token and cost estimate summary |
|
|
367
|
+
| `/attach` | Queue file attachments for the next turn |
|
|
368
|
+
| `/trust` | Manage workspace trust |
|
|
369
|
+
| `/init` | Generate project instructions |
|
|
370
|
+
| `/skills` | List skills |
|
|
371
|
+
| `/gemskill` | Load a skill into the session prompt |
|
|
372
|
+
| `/style` | Set session output style |
|
|
373
|
+
| `/rules` | Inspect active rules |
|
|
374
|
+
| `/diff` | Show current diff/checkpoint diff |
|
|
375
|
+
| `/rewind` | Restore checkpoints |
|
|
376
|
+
| `/review` | Run a review workflow |
|
|
377
|
+
| `/eval` | Run evaluation gates |
|
|
378
|
+
| `/kaira` | Show scheduler usage help |
|
|
379
|
+
|
|
380
|
+
Detailed behavior:
|
|
381
|
+
- [`../docs/cli-and-repl.md`](../docs/cli-and-repl.md)
|
|
382
|
+
|
|
383
|
+
## Capability overview
|
|
384
|
+
|
|
385
|
+
| Capability | What it adds |
|
|
386
|
+
|---|---|
|
|
387
|
+
| Deep research | research-focused tool routing and optional dedicated model path |
|
|
388
|
+
| Embeddings | semantic search and optional embedding-backed memory |
|
|
389
|
+
| Memory | retrieval-oriented persistent memory |
|
|
390
|
+
| Browser/computer use | Playwright-backed browser automation and inspection |
|
|
391
|
+
| Live audio | Gemini Live microphone sessions |
|
|
392
|
+
|
|
393
|
+
Detailed behavior:
|
|
394
|
+
- [`../docs/capabilities.md`](../docs/capabilities.md)
|
|
395
|
+
|
|
396
|
+
## Integrations overview
|
|
397
|
+
|
|
398
|
+
| Integration | Entry point |
|
|
399
|
+
|---|---|
|
|
400
|
+
| IDE bridge | `gemcode ide --stdio` |
|
|
401
|
+
| Web/SSE | documented in `docs/web-ui-contract.md` |
|
|
402
|
+
| MCP | `.gemcode/mcp.json` |
|
|
403
|
+
| OpenAPI | `.gemcode/openapi/` |
|
|
404
|
+
|
|
405
|
+
Detailed behavior:
|
|
406
|
+
- [`../docs/integrations.md`](../docs/integrations.md)
|
|
407
|
+
|
|
408
|
+
## Release and maintenance
|
|
409
|
+
Package version lives in:
|
|
410
|
+
- `gemcode/pyproject.toml`
|
|
411
|
+
|
|
412
|
+
Release operations, troubleshooting, and PyPI workflow are documented in:
|
|
413
|
+
- [`../docs/operations.md`](../docs/operations.md)
|
|
414
|
+
|
|
415
|
+
## Documentation policy
|
|
416
|
+
This manual is intentionally concise. The detailed production documentation lives under `docs/` and is organized by subsystem and operator concern so it can stay accurate as GemCode evolves.
|