lcode-cli 0.14.0__tar.gz → 0.16.0__tar.gz
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.
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/CHANGELOG.md +37 -1
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/PKG-INFO +6 -3
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/README.md +5 -2
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/docs/bench.md +6 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/docs/configuration.md +10 -1
- lcode_cli-0.16.0/docs/hooks.md +134 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/docs/how-it-works.md +1 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/docs/installation.md +5 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/docs/quickstart.md +1 -1
- lcode_cli-0.16.0/docs/servers.md +136 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/docs/usage.md +2 -1
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/mkdocs.yml +2 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/pyproject.toml +1 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/src/lcode/__init__.py +1 -1
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/src/lcode/agent.py +13 -1
- lcode_cli-0.16.0/src/lcode/backends.py +430 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/src/lcode/bench.py +10 -5
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/src/lcode/cli.py +104 -19
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/src/lcode/codesearch.py +6 -1
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/src/lcode/config.py +23 -1
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/src/lcode/extensions.py +18 -3
- lcode_cli-0.16.0/src/lcode/hooks.py +241 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/src/lcode/ollama.py +6 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/src/lcode/permissions.py +19 -1
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/src/lcode/repl.py +30 -3
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/src/lcode/subagents.py +15 -4
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/src/lcode/tools.py +46 -6
- lcode_cli-0.16.0/tests/test_backends.py +335 -0
- lcode_cli-0.16.0/tests/test_hooks.py +203 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/.editorconfig +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/.github/CODEOWNERS +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/.github/ISSUE_TEMPLATE/model_request.yml +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/.github/dependabot.yml +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/.github/workflows/ci.yml +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/.github/workflows/docs.yml +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/.github/workflows/release.yml +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/.gitignore +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/.pre-commit-config.yaml +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/AGENTS.md +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/CODE_OF_CONDUCT.md +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/CONTRIBUTING.md +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/LICENSE +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/SECURITY.md +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/docs/agents.md +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/docs/assets/demo.svg +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/docs/assets/extra.css +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/docs/assets/logo.svg +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/docs/assets/social-preview.png +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/docs/changelog.md +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/docs/commands.md +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/docs/contributing.md +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/docs/index.md +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/docs/lsp.md +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/docs/mcp.md +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/docs/memory.md +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/docs/models.md +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/docs/sandbox.md +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/docs/search.md +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/docs/troubleshooting.md +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/examples/README.md +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/examples/commands/review.md +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/examples/skills/commit-message/SKILL.md +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/examples/skills/commit-message/scripts/staged.sh +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/install.sh +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/overrides/main.html +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/scripts/record_demo.py +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/scripts/social-preview.html +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/src/lcode/__main__.py +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/src/lcode/bench_backend.py +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/src/lcode/catalog.py +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/src/lcode/checkpoints.py +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/src/lcode/context.py +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/src/lcode/frontmatter.py +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/src/lcode/hardware.py +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/src/lcode/limits.py +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/src/lcode/lsp.py +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/src/lcode/mcp/__init__.py +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/src/lcode/mcp/auth.py +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/src/lcode/mcp/catalog.py +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/src/lcode/mcp/catalog.toml +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/src/lcode/mcp/client.py +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/src/lcode/mcp/commands.py +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/src/lcode/mcp/config.py +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/src/lcode/mcp/http.py +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/src/lcode/mcp/manager.py +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/src/lcode/mcp/protocol.py +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/src/lcode/mcp/server.py +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/src/lcode/mcp/stdio.py +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/src/lcode/memory.py +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/src/lcode/models.toml +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/src/lcode/planning.py +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/src/lcode/render.py +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/src/lcode/repomap.py +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/src/lcode/sandbox.py +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/src/lcode/servers/__init__.py +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/src/lcode/servers/encord.py +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/src/lcode/servers/valohai.py +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/src/lcode/sessions.py +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/src/lcode/vision.py +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/src/lcode/web.py +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/tests/conftest.py +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/tests/fake_lsp_server.py +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/tests/fake_mcp_server.py +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/tests/test_agent.py +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/tests/test_bench.py +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/tests/test_catalog.py +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/tests/test_checkpoints.py +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/tests/test_cli.py +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/tests/test_codesearch.py +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/tests/test_config.py +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/tests/test_context.py +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/tests/test_context_picker.py +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/tests/test_extensions.py +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/tests/test_lsp.py +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/tests/test_mcp.py +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/tests/test_memory.py +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/tests/test_permissions.py +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/tests/test_plan_mode.py +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/tests/test_repomap.py +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/tests/test_sandbox.py +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/tests/test_servers.py +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/tests/test_sessions.py +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/tests/test_subagents.py +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/tests/test_tools.py +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/tests/test_vision.py +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/tests/test_web.py +0 -0
- {lcode_cli-0.14.0 → lcode_cli-0.16.0}/uv.lock +0 -0
|
@@ -6,6 +6,40 @@ All notable changes to lcode are documented here. The format follows
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.16.0] - 2026-10-05
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- Other model servers: LM Studio, llama.cpp's llama-server, vLLM, MLX's server, or any other
|
|
14
|
+
server with an OpenAI-compatible API, instead of Ollama. `lcode config set backend lmstudio` (or
|
|
15
|
+
`llama.cpp`, `vllm`, `mlx`, `openai` with `base_url`); a key can come from `LCODE_API_KEY`. Tool
|
|
16
|
+
calls, streaming, reasoning (on and off), images and structured answers work as with Ollama.
|
|
17
|
+
lcode reads the context window from the server, matches the model setting to the models it
|
|
18
|
+
serves, and moves thinking that a server sends as part of the answer out of it. `lcode doctor`,
|
|
19
|
+
`lcode models`, `lcode bench` and `lcode index` work with every backend. See
|
|
20
|
+
[Other model servers](https://nasser1941.github.io/lcode/servers/), with setup for each.
|
|
21
|
+
|
|
22
|
+
## [0.15.0] - 2026-10-05
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
|
|
26
|
+
- Hooks: shell commands that run on lcode's events (`before_tool`, `after_tool`, `after_request`,
|
|
27
|
+
`session_start`, `notification`), filtered by tool and file, with the event as JSON on stdin. A
|
|
28
|
+
`before_tool` hook that exits with code 2 blocks the call and tells the model why; an
|
|
29
|
+
`after_tool` hook's output reaches the model when it fails (a linter) or with `feedback = true`.
|
|
30
|
+
Notification hooks run when lcode waits for you and when a long request is done.
|
|
31
|
+
- Permission rules: `[permissions]` allow and deny lists for shell commands, file edits, web
|
|
32
|
+
domains and MCP tools, checked before lcode asks. Deny always wins, even in `yolo` mode and for
|
|
33
|
+
read-only commands, and is enforced for subagents too.
|
|
34
|
+
- Both go in `config.toml` or a repository's `.lcode/settings.toml`, which is used only once
|
|
35
|
+
approved (and approved again after any change). `lcode doctor` lists them. See
|
|
36
|
+
[Hooks and permission rules](https://nasser1941.github.io/lcode/hooks/), with recipes for ruff,
|
|
37
|
+
prettier, blocking force-pushes, running tests and desktop notifications.
|
|
38
|
+
|
|
39
|
+
### Fixed
|
|
40
|
+
|
|
41
|
+
- `lcode config set` no longer drops tables you added to `config.toml` by hand.
|
|
42
|
+
|
|
9
43
|
## [0.14.0] - 2026-10-05
|
|
10
44
|
|
|
11
45
|
### Added
|
|
@@ -364,7 +398,9 @@ First public release.
|
|
|
364
398
|
- `AGENTS.md` project instructions and `/init` to generate them.
|
|
365
399
|
- One-line installer for Linux and macOS.
|
|
366
400
|
|
|
367
|
-
[Unreleased]: https://github.com/nasser1941/lcode/compare/v0.
|
|
401
|
+
[Unreleased]: https://github.com/nasser1941/lcode/compare/v0.16.0...HEAD
|
|
402
|
+
[0.16.0]: https://github.com/nasser1941/lcode/compare/v0.15.0...v0.16.0
|
|
403
|
+
[0.15.0]: https://github.com/nasser1941/lcode/compare/v0.14.0...v0.15.0
|
|
368
404
|
[0.14.0]: https://github.com/nasser1941/lcode/compare/v0.13.0...v0.14.0
|
|
369
405
|
[0.13.0]: https://github.com/nasser1941/lcode/compare/v0.12.0...v0.13.0
|
|
370
406
|
[0.12.0]: https://github.com/nasser1941/lcode/compare/v0.11.1...v0.12.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: lcode-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.16.0
|
|
4
4
|
Summary: A local-first terminal coding agent powered by open-weight models on your own GPU or Mac, via Ollama.
|
|
5
5
|
Project-URL: Homepage, https://nasser1941.github.io/lcode/
|
|
6
6
|
Project-URL: Documentation, https://nasser1941.github.io/lcode/
|
|
@@ -89,6 +89,8 @@ through [Ollama](https://ollama.com), and when it needs current information it c
|
|
|
89
89
|
and sees the errors an edit introduced right away.
|
|
90
90
|
- **Commands and skills.** Your own `/commands` as prompt templates, and skills in the
|
|
91
91
|
[Agent Skills](https://agentskills.io) format that the model loads only when a task needs them.
|
|
92
|
+
- **Hooks and rules.** Format every edited file, block force-pushes, run the tests after each
|
|
93
|
+
request: shell hooks on lcode's events, and allow and deny lists that hold even in `yolo` mode.
|
|
92
94
|
- **Plan mode.** `/plan <request>` or Shift+Tab: the model explores read-only and presents a plan;
|
|
93
95
|
you approve, edit or send it back before anything changes.
|
|
94
96
|
- **Undo.** lcode saves a checkpoint before the model changes files; `/undo` takes back the last
|
|
@@ -100,7 +102,7 @@ through [Ollama](https://ollama.com), and when it needs current information it c
|
|
|
100
102
|
session as short notes, saved by the model, by you (`/remember`) or by a quick check at the end
|
|
101
103
|
of a session. Not whole conversations, and never secrets.
|
|
102
104
|
- **Bring your own model.** Eight curated open-weight models, all tested end to end, or any Ollama model
|
|
103
|
-
with tool calling.
|
|
105
|
+
with tool calling. Or use LM Studio, llama.cpp, vLLM or MLX instead of Ollama.
|
|
104
106
|
- **MCP servers, ready to go.** Connect Jira and Confluence, GitHub, AWS, Google Drive, Grafana,
|
|
105
107
|
Google Cloud, Sentry, Linear, Notion, Postgres, Kubernetes, Metabase, Encord, Valohai and more with one command
|
|
106
108
|
(`lcode mcp add atlassian`), image generation with ComfyUI, or any other MCP server. Browser sign-in (OAuth) is built in.
|
|
@@ -206,7 +208,8 @@ fills up. Details: [How it works](https://nasser1941.github.io/lcode/how-it-work
|
|
|
206
208
|
|
|
207
209
|
See the pinned [Roadmap issue](https://github.com/nasser1941/lcode/issues/10). Next up:
|
|
208
210
|
|
|
209
|
-
- [
|
|
211
|
+
- [Git workflow: /commit, /review, /pr and parallel worktrees](https://github.com/nasser1941/lcode/issues/50)
|
|
212
|
+
- [Automation: JSON output, a Python API and a GitHub Action for self-hosted runners](https://github.com/nasser1941/lcode/issues/48)
|
|
210
213
|
- More models in the catalog, and test reports from your hardware ([report one](https://github.com/nasser1941/lcode/issues/new?template=model_request.yml))
|
|
211
214
|
|
|
212
215
|
## Contributing
|
|
@@ -53,6 +53,8 @@ through [Ollama](https://ollama.com), and when it needs current information it c
|
|
|
53
53
|
and sees the errors an edit introduced right away.
|
|
54
54
|
- **Commands and skills.** Your own `/commands` as prompt templates, and skills in the
|
|
55
55
|
[Agent Skills](https://agentskills.io) format that the model loads only when a task needs them.
|
|
56
|
+
- **Hooks and rules.** Format every edited file, block force-pushes, run the tests after each
|
|
57
|
+
request: shell hooks on lcode's events, and allow and deny lists that hold even in `yolo` mode.
|
|
56
58
|
- **Plan mode.** `/plan <request>` or Shift+Tab: the model explores read-only and presents a plan;
|
|
57
59
|
you approve, edit or send it back before anything changes.
|
|
58
60
|
- **Undo.** lcode saves a checkpoint before the model changes files; `/undo` takes back the last
|
|
@@ -64,7 +66,7 @@ through [Ollama](https://ollama.com), and when it needs current information it c
|
|
|
64
66
|
session as short notes, saved by the model, by you (`/remember`) or by a quick check at the end
|
|
65
67
|
of a session. Not whole conversations, and never secrets.
|
|
66
68
|
- **Bring your own model.** Eight curated open-weight models, all tested end to end, or any Ollama model
|
|
67
|
-
with tool calling.
|
|
69
|
+
with tool calling. Or use LM Studio, llama.cpp, vLLM or MLX instead of Ollama.
|
|
68
70
|
- **MCP servers, ready to go.** Connect Jira and Confluence, GitHub, AWS, Google Drive, Grafana,
|
|
69
71
|
Google Cloud, Sentry, Linear, Notion, Postgres, Kubernetes, Metabase, Encord, Valohai and more with one command
|
|
70
72
|
(`lcode mcp add atlassian`), image generation with ComfyUI, or any other MCP server. Browser sign-in (OAuth) is built in.
|
|
@@ -170,7 +172,8 @@ fills up. Details: [How it works](https://nasser1941.github.io/lcode/how-it-work
|
|
|
170
172
|
|
|
171
173
|
See the pinned [Roadmap issue](https://github.com/nasser1941/lcode/issues/10). Next up:
|
|
172
174
|
|
|
173
|
-
- [
|
|
175
|
+
- [Git workflow: /commit, /review, /pr and parallel worktrees](https://github.com/nasser1941/lcode/issues/50)
|
|
176
|
+
- [Automation: JSON output, a Python API and a GitHub Action for self-hosted runners](https://github.com/nasser1941/lcode/issues/48)
|
|
174
177
|
- More models in the catalog, and test reports from your hardware ([report one](https://github.com/nasser1941/lcode/issues/new?template=model_request.yml))
|
|
175
178
|
|
|
176
179
|
## Contributing
|
|
@@ -12,6 +12,10 @@ lcode bench --json results.json # also save machine-readable results
|
|
|
12
12
|
lcode bench --markdown # also print a table to paste into a test report
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
+
`lcode bench` also runs against [other model servers](servers.md), such as llama-server or LM
|
|
16
|
+
Studio: `LCODE_BACKEND=llama.cpp lcode bench`. The server keeps the model loaded and doesn't report
|
|
17
|
+
its memory use, so those columns stay empty.
|
|
18
|
+
|
|
15
19
|
```text
|
|
16
20
|
lcode bench · NVIDIA GeForce RTX 4080 Laptop GPU (12 GB VRAM), 31 GB RAM · Ollama 0.32.15
|
|
17
21
|
|
|
@@ -158,6 +162,7 @@ existing fields keep their meaning until `schema` changes.
|
|
|
158
162
|
"schema": 1,
|
|
159
163
|
"lcode": "0.3.1",
|
|
160
164
|
"ollama": "0.32.15",
|
|
165
|
+
"server": "Ollama 0.32.15",
|
|
161
166
|
"date": "2026-09-30T19:09:09+02:00",
|
|
162
167
|
"hardware": {
|
|
163
168
|
"os": "linux", "cpu": "13th Gen Intel(R) Core(TM) i9-13980HX", "ram_gib": 30.96,
|
|
@@ -197,6 +202,7 @@ existing fields keep their meaning until `schema` changes.
|
|
|
197
202
|
|
|
198
203
|
| Field | Meaning |
|
|
199
204
|
|---|---|
|
|
205
|
+
| `ollama`, `server` | The Ollama version, or `null` with [another model server](servers.md); `server` names the server either way |
|
|
200
206
|
| `runs[].model` | The name you gave (catalog key or Ollama tag); `ollama_model` is the model that ran |
|
|
201
207
|
| `runs[].context`, `num_batch`, `think` | The settings used. lcode lowers the batch size or context if the GPU runs out of memory, and reports what it ended up using |
|
|
202
208
|
| `runs[].memory_gb`, `gpu_percent` | From Ollama's `/api/ps`; `null` if unavailable |
|
|
@@ -15,11 +15,13 @@ lcode config path # print the file location
|
|
|
15
15
|
|
|
16
16
|
| Setting | Default | Meaning |
|
|
17
17
|
|---|---|---|
|
|
18
|
-
| `model` | `qwen3.6-35b` | Catalog key (see `lcode models`) or any installed Ollama model tag |
|
|
18
|
+
| `model` | `qwen3.6-35b` | Catalog key (see `lcode models`) or any installed Ollama model tag; with another [backend](servers.md), a model the server serves |
|
|
19
19
|
| `context` | largest that fits | Context window in tokens; accepts `128k`, `1m` |
|
|
20
20
|
| `num_batch` | 512 | Prompt batch size. Larger reads prompts faster but needs more GPU memory |
|
|
21
21
|
| `keep_alive` | `30m` | How long Ollama keeps the model in memory after the last request |
|
|
22
22
|
| `ollama_host` | `http://localhost:11434` | Ollama server URL |
|
|
23
|
+
| `backend` | `ollama` | The model server: `ollama`, `lmstudio`, `llama.cpp`, `vllm`, `mlx` or `openai` (any OpenAI-compatible API); see [Other model servers](servers.md) |
|
|
24
|
+
| `base_url` | the backend's | The server's OpenAI-compatible address, e.g. `http://localhost:1234/v1` |
|
|
23
25
|
| `permission_mode` | `ask` | `ask`, `plan`, `auto-edit` or `yolo` |
|
|
24
26
|
| `think` | `true` | Let the model reason before answering |
|
|
25
27
|
| `web` | `on` | Web search and page fetching: `on`, `ask` (before each search/website) or `off` |
|
|
@@ -40,6 +42,10 @@ lcode config path # print the file location
|
|
|
40
42
|
| `max_parallel_agents` | `1` | Subagents that run at the same time; more needs `OLLAMA_NUM_PARALLEL` on the Ollama server ([details](agents.md#several-at-once)) |
|
|
41
43
|
| `checkpoints` | `true` | Save a checkpoint before the model changes files, so [`/undo`](usage.md#undo-and-checkpoints) can restore them |
|
|
42
44
|
|
|
45
|
+
Besides these settings, `config.toml` can hold [hooks](hooks.md) (`[[hooks]]`) and
|
|
46
|
+
[permission rules](hooks.md#permission-rules) (`[permissions]`); a repository can have its own in
|
|
47
|
+
`.lcode/settings.toml`. `lcode config set` keeps them when it rewrites the file.
|
|
48
|
+
|
|
43
49
|
Example file:
|
|
44
50
|
|
|
45
51
|
```toml
|
|
@@ -61,6 +67,9 @@ Environment variables override the file, which is useful for one-off runs and CI
|
|
|
61
67
|
| `LCODE_NUM_BATCH` | `num_batch` |
|
|
62
68
|
| `LCODE_KEEP_ALIVE` | `keep_alive` |
|
|
63
69
|
| `OLLAMA_HOST` | `ollama_host` (same variable the Ollama CLI uses) |
|
|
70
|
+
| `LCODE_BACKEND` | `backend` |
|
|
71
|
+
| `LCODE_BASE_URL` | `base_url` |
|
|
72
|
+
| `LCODE_API_KEY` or `OPENAI_API_KEY` | API key for an [OpenAI-compatible server](servers.md) that needs one (never stored in the config file) |
|
|
64
73
|
| `LCODE_WEB` | `web` |
|
|
65
74
|
| `LCODE_SANDBOX` | `sandbox` |
|
|
66
75
|
| `LCODE_MEMORY` | `memory` |
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# Hooks and permission rules
|
|
2
|
+
|
|
3
|
+
Some things should happen whatever the model does: format every edited file, never force-push,
|
|
4
|
+
run the tests when a request is done. Hooks and permission rules do that without relying on the
|
|
5
|
+
model to follow instructions.
|
|
6
|
+
|
|
7
|
+
They go in `~/.config/lcode/config.toml` (yours, for every repository) or in a repository's
|
|
8
|
+
`.lcode/settings.toml` (shared with everyone who works on it). A repository's settings are used only
|
|
9
|
+
after you [approve them](commands.md#approving-a-repositorys-commands-skills-and-agents), because
|
|
10
|
+
hooks run commands; lcode asks again whenever the file changes.
|
|
11
|
+
|
|
12
|
+
## Permission rules
|
|
13
|
+
|
|
14
|
+
Rules are checked before lcode asks for permission. An **allow** rule lets an action through
|
|
15
|
+
without asking; a **deny** rule blocks it, even in `yolo` mode and even for commands that are
|
|
16
|
+
otherwise read-only. Deny always wins.
|
|
17
|
+
|
|
18
|
+
```toml
|
|
19
|
+
[permissions]
|
|
20
|
+
allow = ["bash:pytest *", "bash:npm test", "bash:ruff *", "edit:src/**", "web:docs.python.org"]
|
|
21
|
+
deny = ["bash:git push --force*", "bash:git push -f*", "bash:rm -rf /*", "edit:.env", "edit:**/*.pem"]
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
| Rule | Matches |
|
|
25
|
+
|---|---|
|
|
26
|
+
| `bash:<pattern>` | Shell commands, with `*` and `?` wildcards. A leading `cd <folder> &&` is ignored. A deny rule matches any part of a chained command (`git add . && git push --force`); an allow rule needs the whole command, or every part of it, to be allowed |
|
|
27
|
+
| `edit:<pattern>` | Files the model writes or edits, relative to the repository's root. A pattern without a `/` matches the file name anywhere (`.env`, `*.pem`); `src/**` matches everything under `src` |
|
|
28
|
+
| `web:<domain>` | Pages fetched from a domain; `web:search` for searches (only asked about with `web = "ask"`) |
|
|
29
|
+
| `mcp:<server>:<tool>` | An [MCP](mcp.md) server's tools, e.g. `mcp:github:list_*` |
|
|
30
|
+
|
|
31
|
+
When a rule blocks something, the model is told which rule, and not to work around it.
|
|
32
|
+
|
|
33
|
+
## Hooks
|
|
34
|
+
|
|
35
|
+
```toml
|
|
36
|
+
[[hooks]]
|
|
37
|
+
event = "after_tool"
|
|
38
|
+
tools = ["edit_file", "write_file"]
|
|
39
|
+
paths = ["*.py"]
|
|
40
|
+
command = "ruff format {path} && ruff check --fix {path}"
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
| Event | Runs | What it can do |
|
|
44
|
+
|---|---|---|
|
|
45
|
+
| `before_tool` | Before a tool call | Exit with code **2** to block the call; what the hook printed tells the model why |
|
|
46
|
+
| `after_tool` | After a tool call | Its output goes to the model when it exits with an error, or always with `feedback = true` |
|
|
47
|
+
| `after_request` | When a request is done | Its output is shown to you |
|
|
48
|
+
| `session_start` | When a session starts | Its output is shown, and with `feedback = true` given to the model |
|
|
49
|
+
| `notification` | When lcode waits for your answer, and when a request that took over 30 seconds is done | Show a desktop notification, ring a bell |
|
|
50
|
+
|
|
51
|
+
| Key | |
|
|
52
|
+
|---|---|
|
|
53
|
+
| `event` | One of the events above (required) |
|
|
54
|
+
| `command` | Run with `bash -c` in the working directory (required). `{path}` and `{tool}` are replaced, quoted |
|
|
55
|
+
| `tools` | Only for these tools (wildcards allowed), e.g. `["edit_file", "write_file"]` or `["mcp__*"]` |
|
|
56
|
+
| `paths` | Only for these files, like the `edit:` rules: `["*.py"]`, `["src/**"]` |
|
|
57
|
+
| `timeout` | Seconds before the hook is stopped (default 60) |
|
|
58
|
+
| `feedback` | `true` to give the hook's output to the model even when it succeeds |
|
|
59
|
+
|
|
60
|
+
Each hook gets the event as JSON on its standard input (the tool, its arguments, the file's full
|
|
61
|
+
path, the result for `after_tool`, the working directory), and in the environment variables
|
|
62
|
+
`LCODE_EVENT`, `LCODE_TOOL` and `LCODE_PATH`. Hooks run on your machine, also with the
|
|
63
|
+
[sandbox](sandbox.md) on.
|
|
64
|
+
|
|
65
|
+
## Recipes
|
|
66
|
+
|
|
67
|
+
**Format and lint Python files after every edit** (lint problems go back to the model):
|
|
68
|
+
|
|
69
|
+
```toml
|
|
70
|
+
[[hooks]]
|
|
71
|
+
event = "after_tool"
|
|
72
|
+
tools = ["edit_file", "write_file"]
|
|
73
|
+
paths = ["*.py"]
|
|
74
|
+
command = "ruff format --quiet {path} && ruff check --fix --quiet {path}"
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
**Prettier for JavaScript and TypeScript:**
|
|
78
|
+
|
|
79
|
+
```toml
|
|
80
|
+
[[hooks]]
|
|
81
|
+
event = "after_tool"
|
|
82
|
+
tools = ["edit_file", "write_file"]
|
|
83
|
+
paths = ["*.ts", "*.tsx", "*.js", "*.jsx", "*.css", "*.json"]
|
|
84
|
+
command = "npx --no-install prettier --write {path} > /dev/null"
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
**Never force-push.** A rule is enough:
|
|
88
|
+
|
|
89
|
+
```toml
|
|
90
|
+
[permissions]
|
|
91
|
+
deny = ["bash:git push --force*", "bash:git push -f*", "bash:git push * --force*"]
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
or, with a hook that explains the house rule to the model:
|
|
95
|
+
|
|
96
|
+
```toml
|
|
97
|
+
[[hooks]]
|
|
98
|
+
event = "before_tool"
|
|
99
|
+
tools = ["bash"]
|
|
100
|
+
command = '''
|
|
101
|
+
if jq -r .arguments.command | grep -Eq 'git push.*(--force|-f)'; then
|
|
102
|
+
echo "Force-pushing isn't allowed here: push to a new branch and open a pull request instead."
|
|
103
|
+
exit 2
|
|
104
|
+
fi
|
|
105
|
+
'''
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
**Run the tests when a request is done:**
|
|
109
|
+
|
|
110
|
+
```toml
|
|
111
|
+
[[hooks]]
|
|
112
|
+
event = "after_request"
|
|
113
|
+
command = "pytest -q -x 2>&1 | tail -3"
|
|
114
|
+
timeout = 300
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
**A desktop notification** when lcode needs you or finishes a long request:
|
|
118
|
+
|
|
119
|
+
```toml
|
|
120
|
+
[[hooks]]
|
|
121
|
+
event = "notification"
|
|
122
|
+
command = "notify-send lcode \"$(jq -r .message)\"" # macOS: osascript -e "display notification \"…\""
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
**Tell the model what branch it's on** at the start of every session:
|
|
126
|
+
|
|
127
|
+
```toml
|
|
128
|
+
[[hooks]]
|
|
129
|
+
event = "session_start"
|
|
130
|
+
command = "git status --short --branch | head -20"
|
|
131
|
+
feedback = true
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
`lcode doctor` lists the hooks and rules it found, and any it couldn't read.
|
|
@@ -106,6 +106,7 @@ the Ollama server you configure, it only contacts the web when the model searche
|
|
|
106
106
|
| `bench.py` | `lcode bench`: the benchmark tasks, their checks and the reports |
|
|
107
107
|
| `vision.py` | Looking at images with a model that can see |
|
|
108
108
|
| `subagents.py` | Subagents: agent types, running them (also in parallel), worktrees for workers |
|
|
109
|
+
| `hooks.py` | Hooks on lcode's events, and allow and deny rules for permissions |
|
|
109
110
|
| `repomap.py`, `codesearch.py` | The repository map, and semantic code search with an embedding model |
|
|
110
111
|
| `lsp.py` | Language servers: the `lsp` tool and errors after edits |
|
|
111
112
|
| `extensions.py` | Custom commands and skills, and approving a repository's own |
|
|
@@ -151,6 +151,11 @@ lcode config set ollama_host http://gpu-server:11434
|
|
|
151
151
|
Your prompts and the code the model reads are then sent to that server. Ollama has no
|
|
152
152
|
authentication; only expose it on a network you trust (or through an SSH tunnel).
|
|
153
153
|
|
|
154
|
+
### LM Studio, llama.cpp, vLLM or MLX instead of Ollama
|
|
155
|
+
|
|
156
|
+
lcode also works with any server that has an OpenAI-compatible API: `lcode config set backend
|
|
157
|
+
lmstudio` (or `llama.cpp`, `vllm`, `mlx`). See [Other model servers](servers.md).
|
|
158
|
+
|
|
154
159
|
### Windows
|
|
155
160
|
|
|
156
161
|
Use [WSL2](https://learn.microsoft.com/windows/wsl/install) with Ubuntu and follow the Ubuntu
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# Other model servers
|
|
2
|
+
|
|
3
|
+
lcode is built around [Ollama](https://ollama.com), but it also works with any server that has an
|
|
4
|
+
OpenAI-compatible API: [LM Studio](https://lmstudio.ai),
|
|
5
|
+
[llama.cpp](https://github.com/ggml-org/llama.cpp)'s `llama-server`, [vLLM](https://docs.vllm.ai)
|
|
6
|
+
and the [MLX](https://github.com/ml-explore/mlx-lm) server. Tool calls, streaming answers, reasoning
|
|
7
|
+
and all of lcode's tools work the same.
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
lcode config set backend lmstudio # or llama.cpp, vllm, mlx
|
|
11
|
+
lcode doctor # checks the server, the model and its context window
|
|
12
|
+
lcode
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
| `backend` | Server | Default address |
|
|
16
|
+
|---|---|---|
|
|
17
|
+
| `ollama` (default) | Ollama | `ollama_host`, `http://localhost:11434` |
|
|
18
|
+
| `lmstudio` | LM Studio | `http://localhost:1234/v1` |
|
|
19
|
+
| `llama.cpp` | llama-server | `http://localhost:8080/v1` |
|
|
20
|
+
| `vllm` | vLLM | `http://localhost:8000/v1` |
|
|
21
|
+
| `mlx` | `mlx_lm.server` | `http://localhost:8080/v1` |
|
|
22
|
+
| `openai` | Any other OpenAI-compatible API | Set `base_url` |
|
|
23
|
+
|
|
24
|
+
- **Another address:** `lcode config set base_url http://gpu-box:8000/v1`.
|
|
25
|
+
- **A server that needs a key:** put it in `LCODE_API_KEY` (or `OPENAI_API_KEY`). lcode sends it as a
|
|
26
|
+
bearer token and never writes it to the config file.
|
|
27
|
+
- **For one run:** `LCODE_BACKEND=llama.cpp lcode`.
|
|
28
|
+
|
|
29
|
+
Your prompts and the code the model reads go to that server, so use one you run yourself or trust.
|
|
30
|
+
|
|
31
|
+
## Choosing the model
|
|
32
|
+
|
|
33
|
+
The `model` setting names a model the server serves. `lcode models` lists them:
|
|
34
|
+
|
|
35
|
+
```text
|
|
36
|
+
$ lcode models
|
|
37
|
+
Models served by LM Studio at http://localhost:1234/v1
|
|
38
|
+
google/gemma-4-12b
|
|
39
|
+
qwen/qwen3.6-35b-a3b current
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Part of the name is enough when only one model matches (`lcode -m gemma`). A server with a single
|
|
43
|
+
model, like llama-server, uses it whatever the setting says. `lcode setup` only installs models
|
|
44
|
+
into Ollama: download models in the server itself.
|
|
45
|
+
|
|
46
|
+
## The context window
|
|
47
|
+
|
|
48
|
+
With Ollama, lcode chooses the context window and loads the model with it. Other servers load the
|
|
49
|
+
model themselves, with their own window, so lcode reads its size from the server:
|
|
50
|
+
|
|
51
|
+
- llama-server: the `-c` option;
|
|
52
|
+
- vLLM: `--max-model-len`;
|
|
53
|
+
- LM Studio: the context length the model was loaded with.
|
|
54
|
+
|
|
55
|
+
lcode then summarizes the conversation before it outgrows that window. The MLX server and Ollama's
|
|
56
|
+
own OpenAI endpoint don't report a size, so lcode assumes 32K; set the real size with
|
|
57
|
+
`lcode config set context 64k`. A smaller value than the server's is fine (`/ctx 16k`): lcode just
|
|
58
|
+
summarizes sooner.
|
|
59
|
+
|
|
60
|
+
lcode's instructions and tool definitions take about 6K tokens, so give the model at least 32K.
|
|
61
|
+
|
|
62
|
+
## Setting up each server
|
|
63
|
+
|
|
64
|
+
### LM Studio
|
|
65
|
+
|
|
66
|
+
1. Download a model that supports tool use, such as Qwen3.6 35B A3B or Gemma 4.
|
|
67
|
+
2. Load it with a context length of 32K or more. LM Studio's default of 4K is too small for a
|
|
68
|
+
coding agent.
|
|
69
|
+
3. Start the server: in the Developer tab, or with `lms server start`.
|
|
70
|
+
4. Point lcode at it:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
lcode config set backend lmstudio
|
|
74
|
+
lcode models # the ids LM Studio serves
|
|
75
|
+
lcode config set model qwen/qwen3.6-35b-a3b
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
On a Mac, LM Studio's MLX models are the fastest route. Load the model before you start lcode: a
|
|
79
|
+
model that LM Studio loads on request gets LM Studio's default context length.
|
|
80
|
+
|
|
81
|
+
### llama.cpp (llama-server)
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
llama-server -m Qwen3.6-35B-A3B-Q4_K_M.gguf --alias qwen3.6-35b --jinja -c 65536 -ngl 99 --n-cpu-moe 20
|
|
85
|
+
lcode config set backend llama.cpp
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
- `--jinja` is required for tool calls.
|
|
89
|
+
- `-c` sets the context window, which lcode reads.
|
|
90
|
+
- `--alias` gives the model a short name; otherwise its name is the file's path.
|
|
91
|
+
- On a GPU too small for the whole model, `--n-cpu-moe N` (or `--cpu-moe`) keeps a mixture-of-experts
|
|
92
|
+
model's expert layers in RAM.
|
|
93
|
+
|
|
94
|
+
With Docker and an NVIDIA GPU:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
docker run -d --gpus all -p 127.0.0.1:8080:8080 -v ~/models:/models ghcr.io/ggml-org/llama.cpp:server-cuda \
|
|
98
|
+
-m /models/Qwen3.6-35B-A3B-Q4_K_M.gguf --alias qwen3.6-35b --jinja -c 65536 -ngl 99 --n-cpu-moe 20 \
|
|
99
|
+
--host 0.0.0.0
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### vLLM
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
vllm serve Qwen/Qwen3-32B --max-model-len 32768 \
|
|
106
|
+
--enable-auto-tool-choice --tool-call-parser hermes --reasoning-parser qwen3
|
|
107
|
+
lcode config set backend vllm
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
vLLM needs `--enable-auto-tool-choice` and the tool-call parser for the model's family (see vLLM's
|
|
111
|
+
[tool calling](https://docs.vllm.ai/en/latest/features/tool_calling.html) page). A reasoning parser
|
|
112
|
+
keeps the model's thinking out of its answers.
|
|
113
|
+
|
|
114
|
+
### MLX (Apple silicon)
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
pip install mlx-lm
|
|
118
|
+
mlx_lm.server --model mlx-community/Qwen3-30B-A3B-4bit
|
|
119
|
+
lcode config set backend mlx
|
|
120
|
+
lcode config set context 32k
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## What's different from Ollama
|
|
124
|
+
|
|
125
|
+
| | Ollama | Other servers |
|
|
126
|
+
|---|---|---|
|
|
127
|
+
| Context window | lcode chooses it, and falls back to a smaller one when the GPU runs out of memory | The server's; lcode reads it |
|
|
128
|
+
| Reasoning on and off (`/think`, `--no-think`) | Yes | Yes, for models whose chat template has a switch (Qwen and others) on llama-server and vLLM |
|
|
129
|
+
| Thinking shown separately | Yes | Yes. When a server sends the thinking as part of the answer, lcode moves it out |
|
|
130
|
+
| Images | The model's own vision, or `vision_model` | Set `vision_model` to a model the server serves that can see images |
|
|
131
|
+
| [Code search](search.md#semantic-code-search) | Any installed embedding model | Needs the server to serve an embedding model too, as LM Studio can |
|
|
132
|
+
| Freeing the GPU for MCP tools that need it | Yes | No: the server decides what stays loaded |
|
|
133
|
+
| `lcode bench` memory columns | Measured | Empty: the server doesn't report them |
|
|
134
|
+
|
|
135
|
+
`lcode bench` works the same way with any backend, so you can compare the same model on two
|
|
136
|
+
servers: `LCODE_BACKEND=llama.cpp lcode bench`.
|
|
@@ -147,7 +147,8 @@ Read-only commands run without asking: `ls`, `cat`, `head`, `tail`, `grep`, `rg`
|
|
|
147
147
|
output, chain commands or run subshells. A `cd <folder> &&` in front is fine.
|
|
148
148
|
|
|
149
149
|
When asked, answer ++y++ (once), ++a++ (always, for this command or for all edits, until you quit)
|
|
150
|
-
or ++n++.
|
|
150
|
+
or ++n++. For lasting answers, write [permission rules](hooks.md#permission-rules): allow lists and
|
|
151
|
+
deny lists, per user or per repository; deny always wins, even in `yolo`. Text after ++n++ goes to the model as instructions: `n run the tests with -x first`.
|
|
151
152
|
|
|
152
153
|
!!! warning "yolo mode"
|
|
153
154
|
|
|
@@ -98,9 +98,11 @@ nav:
|
|
|
98
98
|
- Code intelligence: lsp.md
|
|
99
99
|
- Repository map and code search: search.md
|
|
100
100
|
- Models & context windows: models.md
|
|
101
|
+
- Other model servers: servers.md
|
|
101
102
|
- Benchmarking models: bench.md
|
|
102
103
|
- MCP servers: mcp.md
|
|
103
104
|
- Sandbox: sandbox.md
|
|
105
|
+
- Hooks and permission rules: hooks.md
|
|
104
106
|
- Configuration: configuration.md
|
|
105
107
|
- Reference:
|
|
106
108
|
- How it works: how-it-works.md
|
|
@@ -216,6 +216,9 @@ class Agent:
|
|
|
216
216
|
self.checkpoints = Checkpoints(self.console, settings.checkpoints)
|
|
217
217
|
self.mcp: McpManager | None = None # set by the CLI when MCP servers are configured
|
|
218
218
|
self.lsp = None # an lcode.lsp.Manager, set by the CLI when language servers are installed
|
|
219
|
+
from lcode.hooks import HookSet
|
|
220
|
+
|
|
221
|
+
self.hooks = HookSet() # set by the CLI from the settings (lcode.hooks)
|
|
219
222
|
self._repo_map: tuple[Path, repomap.RepoMap, str] | None = None
|
|
220
223
|
self._code_index: tuple[Path, codesearch.Index | None] | None = None
|
|
221
224
|
self.sandbox = (
|
|
@@ -567,7 +570,8 @@ class Agent:
|
|
|
567
570
|
self.console.print(f"[dim]{self.settings.model} does not support reasoning; continuing without.[/]")
|
|
568
571
|
yield from self.chat(messages, tools, False)
|
|
569
572
|
return
|
|
570
|
-
|
|
573
|
+
# Only Ollama loads the model with lcode's settings; other servers manage their own memory.
|
|
574
|
+
if getattr(self.ollama, "kind", "ollama") == "ollama" and any(m in error for m in GPU_MEMORY_ERRORS):
|
|
571
575
|
batch = self.settings.num_batch
|
|
572
576
|
if not started and batch and batch > SAFE_NUM_BATCH:
|
|
573
577
|
# Larger batches read prompts faster but need extra VRAM that isn't always free.
|
|
@@ -722,6 +726,14 @@ class Agent:
|
|
|
722
726
|
self._run_turn(user_text)
|
|
723
727
|
finally:
|
|
724
728
|
self.checkpoints.end_turn()
|
|
729
|
+
if self.hooks.hooks and self.allowed_tools is None:
|
|
730
|
+
payload = {"request": user_text[:2000], "cwd": str(self.cwd), "session": self.session_id}
|
|
731
|
+
for outcome in self.hooks.run("after_request", payload, self.cwd):
|
|
732
|
+
style = "dim" if outcome.code == 0 else "yellow"
|
|
733
|
+
if outcome.output or outcome.code:
|
|
734
|
+
self.console.print(
|
|
735
|
+
Text(f" ⎿ after_request hook ({outcome.code}): {outcome.output[:500]}", style=style)
|
|
736
|
+
)
|
|
725
737
|
|
|
726
738
|
def sandbox_root(self) -> Path | None:
|
|
727
739
|
"""The folder the model is limited to while the sandbox is on (None when it's off)."""
|