lcode-cli 0.8.0__tar.gz → 0.10.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.8.0 → lcode_cli-0.10.0}/CHANGELOG.md +44 -1
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/PKG-INFO +5 -2
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/README.md +4 -1
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/docs/agents.md +3 -1
- lcode_cli-0.10.0/docs/commands.md +131 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/docs/configuration.md +4 -1
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/docs/how-it-works.md +3 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/docs/quickstart.md +1 -1
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/docs/usage.md +51 -3
- lcode_cli-0.10.0/examples/README.md +17 -0
- lcode_cli-0.10.0/examples/commands/review.md +15 -0
- lcode_cli-0.10.0/examples/skills/commit-message/SKILL.md +17 -0
- lcode_cli-0.10.0/examples/skills/commit-message/scripts/staged.sh +8 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/mkdocs.yml +1 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/pyproject.toml +2 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/src/lcode/__init__.py +1 -1
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/src/lcode/agent.py +36 -4
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/src/lcode/cli.py +23 -1
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/src/lcode/config.py +8 -2
- lcode_cli-0.10.0/src/lcode/extensions.py +405 -0
- lcode_cli-0.10.0/src/lcode/frontmatter.py +62 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/src/lcode/mcp/commands.py +2 -2
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/src/lcode/memory.py +2 -14
- lcode_cli-0.10.0/src/lcode/planning.py +138 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/src/lcode/repl.py +80 -4
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/src/lcode/subagents.py +7 -7
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/src/lcode/tools.py +50 -6
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/tests/conftest.py +8 -1
- lcode_cli-0.10.0/tests/test_extensions.py +253 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/tests/test_mcp.py +15 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/tests/test_memory.py +1 -0
- lcode_cli-0.10.0/tests/test_plan_mode.py +161 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/.editorconfig +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/.github/CODEOWNERS +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/.github/ISSUE_TEMPLATE/model_request.yml +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/.github/dependabot.yml +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/.github/workflows/ci.yml +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/.github/workflows/docs.yml +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/.github/workflows/release.yml +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/.gitignore +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/.pre-commit-config.yaml +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/AGENTS.md +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/CODE_OF_CONDUCT.md +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/CONTRIBUTING.md +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/LICENSE +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/SECURITY.md +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/docs/assets/demo.svg +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/docs/assets/extra.css +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/docs/assets/logo.svg +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/docs/assets/social-preview.png +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/docs/bench.md +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/docs/changelog.md +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/docs/contributing.md +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/docs/index.md +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/docs/installation.md +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/docs/mcp.md +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/docs/memory.md +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/docs/models.md +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/docs/sandbox.md +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/docs/troubleshooting.md +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/install.sh +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/overrides/main.html +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/scripts/record_demo.py +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/scripts/social-preview.html +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/src/lcode/__main__.py +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/src/lcode/bench.py +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/src/lcode/catalog.py +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/src/lcode/checkpoints.py +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/src/lcode/hardware.py +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/src/lcode/limits.py +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/src/lcode/mcp/__init__.py +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/src/lcode/mcp/auth.py +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/src/lcode/mcp/catalog.py +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/src/lcode/mcp/catalog.toml +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/src/lcode/mcp/client.py +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/src/lcode/mcp/config.py +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/src/lcode/mcp/http.py +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/src/lcode/mcp/manager.py +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/src/lcode/mcp/protocol.py +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/src/lcode/mcp/stdio.py +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/src/lcode/models.toml +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/src/lcode/ollama.py +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/src/lcode/permissions.py +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/src/lcode/render.py +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/src/lcode/sandbox.py +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/src/lcode/sessions.py +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/src/lcode/vision.py +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/src/lcode/web.py +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/tests/fake_mcp_server.py +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/tests/test_agent.py +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/tests/test_bench.py +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/tests/test_catalog.py +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/tests/test_checkpoints.py +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/tests/test_cli.py +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/tests/test_config.py +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/tests/test_context_picker.py +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/tests/test_permissions.py +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/tests/test_sandbox.py +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/tests/test_sessions.py +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/tests/test_subagents.py +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/tests/test_tools.py +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/tests/test_vision.py +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/tests/test_web.py +0 -0
- {lcode_cli-0.8.0 → lcode_cli-0.10.0}/uv.lock +0 -0
|
@@ -6,6 +6,47 @@ All notable changes to lcode are documented here. The format follows
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.10.0] - 2026-10-05
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- Custom commands: prompt templates in `.lcode/commands/<name>.md` or
|
|
14
|
+
`~/.config/lcode/commands/`, run as `/name args`, with `$ARGUMENTS` and `$1`…`$9`, and an
|
|
15
|
+
optional frontmatter for the description, an argument hint and the tools allowed for the
|
|
16
|
+
request.
|
|
17
|
+
- Skills in the [Agent Skills](https://agentskills.io) format, from `.lcode/skills/`,
|
|
18
|
+
`.agents/skills/` and `.claude/skills/` (in the repository and in your home folder). Only their
|
|
19
|
+
names and descriptions are in the system prompt; the model loads a skill's instructions with the
|
|
20
|
+
new `skill` tool when a task matches, and its scripts and reference files when the instructions
|
|
21
|
+
call for them. `/name` starts a skill yourself. `/help` lists commands and skills and where each
|
|
22
|
+
comes from. The `skills` setting limits them to lcode's own folders (`lcode`) or turns them off.
|
|
23
|
+
An example command and skill are in `examples/`. See
|
|
24
|
+
[Commands and skills](https://nasser1941.github.io/lcode/commands/).
|
|
25
|
+
|
|
26
|
+
### Changed
|
|
27
|
+
|
|
28
|
+
- A repository's own commands, skills and agents are used only after you approve them; lcode asks
|
|
29
|
+
the first time and again when they change, like a project's `.mcp.json`. Custom agents from a
|
|
30
|
+
repository (new in 0.8.0) used to load without asking.
|
|
31
|
+
|
|
32
|
+
## [0.9.0] - 2026-10-05
|
|
33
|
+
|
|
34
|
+
### Added
|
|
35
|
+
|
|
36
|
+
- Plan mode: a `plan` permission mode (Shift+Tab from `ask`, `/mode plan`, `lcode --plan`, or
|
|
37
|
+
`/plan <request>`) in which the model can read, search, run read-only commands, use the web and
|
|
38
|
+
read-only subagents, but can't change anything. It presents a plan with the new `present_plan`
|
|
39
|
+
tool, and you approve it (in `ask` or `auto-edit` mode), edit it, save it to `.lcode/plans/`, or
|
|
40
|
+
send it back with feedback. An approved plan fills the todo list and is kept through compaction;
|
|
41
|
+
`/plan` shows it. See [Plan mode](https://nasser1941.github.io/lcode/usage/#plan-mode).
|
|
42
|
+
|
|
43
|
+
### Fixed
|
|
44
|
+
|
|
45
|
+
- `lcode mcp add` shows the default value in its questions again, such as `AWS region
|
|
46
|
+
[us-east-1]`; the terminal formatting swallowed it.
|
|
47
|
+
- The end-of-session "Worth remembering?" list shows each note's type (`[feedback]`, `[project]`, …),
|
|
48
|
+
which the same problem hid.
|
|
49
|
+
|
|
9
50
|
## [0.8.0] - 2026-10-05
|
|
10
51
|
|
|
11
52
|
### Added
|
|
@@ -246,7 +287,9 @@ First public release.
|
|
|
246
287
|
- `AGENTS.md` project instructions and `/init` to generate them.
|
|
247
288
|
- One-line installer for Linux and macOS.
|
|
248
289
|
|
|
249
|
-
[Unreleased]: https://github.com/nasser1941/lcode/compare/v0.
|
|
290
|
+
[Unreleased]: https://github.com/nasser1941/lcode/compare/v0.10.0...HEAD
|
|
291
|
+
[0.10.0]: https://github.com/nasser1941/lcode/compare/v0.9.0...v0.10.0
|
|
292
|
+
[0.9.0]: https://github.com/nasser1941/lcode/compare/v0.8.0...v0.9.0
|
|
250
293
|
[0.8.0]: https://github.com/nasser1941/lcode/compare/v0.7.0...v0.8.0
|
|
251
294
|
[0.7.0]: https://github.com/nasser1941/lcode/compare/v0.6.1...v0.7.0
|
|
252
295
|
[0.6.1]: https://github.com/nasser1941/lcode/compare/v0.6.0...v0.6.1
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: lcode-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.10.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/
|
|
@@ -80,6 +80,10 @@ through [Ollama](https://ollama.com), and when it needs current information it c
|
|
|
80
80
|
your approval. `auto-edit` and `yolo` modes when you want speed.
|
|
81
81
|
- **Sandbox (optional).** `lcode --sandbox` runs the model's shell commands in a container (Docker or
|
|
82
82
|
Podman) that only sees your project, without network access unless you allow it.
|
|
83
|
+
- **Commands and skills.** Your own `/commands` as prompt templates, and skills in the
|
|
84
|
+
[Agent Skills](https://agentskills.io) format that the model loads only when a task needs them.
|
|
85
|
+
- **Plan mode.** `/plan <request>` or Shift+Tab: the model explores read-only and presents a plan;
|
|
86
|
+
you approve, edit or send it back before anything changes.
|
|
83
87
|
- **Undo.** lcode saves a checkpoint before the model changes files; `/undo` takes back the last
|
|
84
88
|
request's edits, new files and shell-command changes, without touching your git history.
|
|
85
89
|
- **Subagents.** The model hands broad searches, planning and self-contained changes to subagents
|
|
@@ -195,7 +199,6 @@ fills up. Details: [How it works](https://nasser1941.github.io/lcode/how-it-work
|
|
|
195
199
|
|
|
196
200
|
See the pinned [Roadmap issue](https://github.com/nasser1941/lcode/issues/10). Next up:
|
|
197
201
|
|
|
198
|
-
- [Plan mode](https://github.com/nasser1941/lcode/issues/41) and [custom commands and skills](https://github.com/nasser1941/lcode/issues/42)
|
|
199
202
|
- [Ready-made MCP for Metabase, Encord and Valohai](https://github.com/nasser1941/lcode/issues/53)
|
|
200
203
|
- Then: [smarter context for small windows](https://github.com/nasser1941/lcode/issues/46), [language servers](https://github.com/nasser1941/lcode/issues/44), [a repository map with local embeddings](https://github.com/nasser1941/lcode/issues/45), [hooks](https://github.com/nasser1941/lcode/issues/43)
|
|
201
204
|
- More models in the catalog, and test reports from your hardware ([report one](https://github.com/nasser1941/lcode/issues/new?template=model_request.yml))
|
|
@@ -46,6 +46,10 @@ through [Ollama](https://ollama.com), and when it needs current information it c
|
|
|
46
46
|
your approval. `auto-edit` and `yolo` modes when you want speed.
|
|
47
47
|
- **Sandbox (optional).** `lcode --sandbox` runs the model's shell commands in a container (Docker or
|
|
48
48
|
Podman) that only sees your project, without network access unless you allow it.
|
|
49
|
+
- **Commands and skills.** Your own `/commands` as prompt templates, and skills in the
|
|
50
|
+
[Agent Skills](https://agentskills.io) format that the model loads only when a task needs them.
|
|
51
|
+
- **Plan mode.** `/plan <request>` or Shift+Tab: the model explores read-only and presents a plan;
|
|
52
|
+
you approve, edit or send it back before anything changes.
|
|
49
53
|
- **Undo.** lcode saves a checkpoint before the model changes files; `/undo` takes back the last
|
|
50
54
|
request's edits, new files and shell-command changes, without touching your git history.
|
|
51
55
|
- **Subagents.** The model hands broad searches, planning and self-contained changes to subagents
|
|
@@ -161,7 +165,6 @@ fills up. Details: [How it works](https://nasser1941.github.io/lcode/how-it-work
|
|
|
161
165
|
|
|
162
166
|
See the pinned [Roadmap issue](https://github.com/nasser1941/lcode/issues/10). Next up:
|
|
163
167
|
|
|
164
|
-
- [Plan mode](https://github.com/nasser1941/lcode/issues/41) and [custom commands and skills](https://github.com/nasser1941/lcode/issues/42)
|
|
165
168
|
- [Ready-made MCP for Metabase, Encord and Valohai](https://github.com/nasser1941/lcode/issues/53)
|
|
166
169
|
- Then: [smarter context for small windows](https://github.com/nasser1941/lcode/issues/46), [language servers](https://github.com/nasser1941/lcode/issues/44), [a repository map with local embeddings](https://github.com/nasser1941/lcode/issues/45), [hooks](https://github.com/nasser1941/lcode/issues/43)
|
|
167
170
|
- More models in the catalog, and test reports from your hardware ([report one](https://github.com/nasser1941/lcode/issues/new?template=model_request.yml))
|
|
@@ -134,7 +134,9 @@ Report bugs first, with `path:line`, then missing tests, then style. Don't fix a
|
|
|
134
134
|
| `~/.config/lcode/agents/<name>.md` | For every repository |
|
|
135
135
|
|
|
136
136
|
The file name is the agent's name. A repository's agent overrides one of yours with the same name,
|
|
137
|
-
and both override the built-in types.
|
|
137
|
+
and both override the built-in types. A repository's agents are used only after you
|
|
138
|
+
[approve them](commands.md#approving-a-repositorys-commands-skills-and-agents), together with its
|
|
139
|
+
commands and skills. `/agents` and `lcode doctor` point out files that couldn't be
|
|
138
140
|
read.
|
|
139
141
|
|
|
140
142
|
## Settings
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# Commands and skills
|
|
2
|
+
|
|
3
|
+
Teams repeat the same requests: "review this diff against our checklist", "write a migration the
|
|
4
|
+
way we do it", the release steps. `AGENTS.md` can't hold all of that, because it goes into every
|
|
5
|
+
request and every line costs context. lcode has two ways to keep such instructions ready without
|
|
6
|
+
paying for them until they're used.
|
|
7
|
+
|
|
8
|
+
| | Command | Skill |
|
|
9
|
+
|---|---|---|
|
|
10
|
+
| What it is | A prompt template | Instructions, plus scripts and reference files if needed |
|
|
11
|
+
| Who starts it | You, with `/name args` | The model, when a task matches its description, or you with `/name` |
|
|
12
|
+
| Context cost until used | Nothing | Its name and one-line description |
|
|
13
|
+
| Format | `<name>.md` | A folder with a `SKILL.md`, in the [Agent Skills](https://agentskills.io) format |
|
|
14
|
+
|
|
15
|
+
## Commands
|
|
16
|
+
|
|
17
|
+
A command is a markdown file whose body is the request to send. `$ARGUMENTS` becomes everything
|
|
18
|
+
you type after the command's name, and `$1` to `$9` single words. If the template has no
|
|
19
|
+
placeholder, what you type is added at the end.
|
|
20
|
+
|
|
21
|
+
```markdown
|
|
22
|
+
---
|
|
23
|
+
description: review the uncommitted changes for bugs and missing tests
|
|
24
|
+
argument-hint: "[path or what to focus on]"
|
|
25
|
+
allowed-tools: read_file grep glob list_dir bash
|
|
26
|
+
---
|
|
27
|
+
Review the uncommitted changes in this repository. $ARGUMENTS
|
|
28
|
+
|
|
29
|
+
Run `git diff` and `git diff --cached` to see them, and read the code around them where needed.
|
|
30
|
+
Report bugs first, with `path:line`, then missing tests. Don't change any files.
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
```text
|
|
34
|
+
❯ /review the parser changes
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
| Frontmatter (all optional) | |
|
|
38
|
+
|---|---|
|
|
39
|
+
| `description` | Shown in `/help` and completion (default: the first line) |
|
|
40
|
+
| `argument-hint` | Shown after the name in `/help`, e.g. `[path]` |
|
|
41
|
+
| `allowed-tools` | The only tools the model gets for this request, e.g. `read_file grep bash` (lcode's tool names) |
|
|
42
|
+
|
|
43
|
+
| Folder | Commands |
|
|
44
|
+
|---|---|
|
|
45
|
+
| `.lcode/commands/<name>.md` in the repository | For this repository; commit them to share them |
|
|
46
|
+
| `~/.config/lcode/commands/<name>.md` | For every repository |
|
|
47
|
+
|
|
48
|
+
The file name is the command's name. A repository's command overrides one of yours with the same
|
|
49
|
+
name; built-in commands such as `/help` can't be replaced.
|
|
50
|
+
|
|
51
|
+
## Skills
|
|
52
|
+
|
|
53
|
+
A skill is a folder with a `SKILL.md`: a frontmatter with a `name` and a `description` that says
|
|
54
|
+
what the skill does and when to use it, then instructions. Scripts, templates and reference files
|
|
55
|
+
can sit next to it.
|
|
56
|
+
|
|
57
|
+
```text
|
|
58
|
+
.lcode/skills/commit-message/
|
|
59
|
+
├── SKILL.md
|
|
60
|
+
└── scripts/
|
|
61
|
+
└── staged.sh
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
```markdown
|
|
65
|
+
---
|
|
66
|
+
name: commit-message
|
|
67
|
+
description: Writes a git commit message for the staged changes, in the style the repository
|
|
68
|
+
already uses. Use when the user asks for a commit message, or asks you to commit their changes.
|
|
69
|
+
---
|
|
70
|
+
# Commit messages
|
|
71
|
+
|
|
72
|
+
1. Run `scripts/staged.sh` from this skill's folder. It prints the staged files and the subjects
|
|
73
|
+
of the last 15 commits.
|
|
74
|
+
2. Match the style of the recent subjects …
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
How lcode uses them, step by step, so they cost almost nothing until needed:
|
|
78
|
+
|
|
79
|
+
1. At the start of a session, the model gets only each skill's name and description.
|
|
80
|
+
2. When a task matches a description, the model calls the `skill` tool. It gets the instructions,
|
|
81
|
+
the skill's folder and the list of files in it, but not their contents.
|
|
82
|
+
3. The model reads or runs those files when the instructions call for them. Files in a skill's
|
|
83
|
+
folder can be read even when the [sandbox](sandbox.md) limits the model to the project.
|
|
84
|
+
|
|
85
|
+
You can also start a skill yourself: `/commit-message` or `/commit-message only the parser
|
|
86
|
+
changes`. After the conversation is compacted, the model is told which skills were in use, so it
|
|
87
|
+
can load them again.
|
|
88
|
+
|
|
89
|
+
lcode reads skills from these folders; a repository's skill overrides one of yours with the same
|
|
90
|
+
name:
|
|
91
|
+
|
|
92
|
+
| Folder | |
|
|
93
|
+
|---|---|
|
|
94
|
+
| `.lcode/skills/`, `.agents/skills/`, `.claude/skills/` in the repository | For this repository |
|
|
95
|
+
| `~/.config/lcode/skills/`, `~/.agents/skills/`, `~/.claude/skills/` | For every repository |
|
|
96
|
+
|
|
97
|
+
`.agents/skills/` is the folder agents share by convention, and `.claude/skills/` is read too, so
|
|
98
|
+
skills you already have for other agents work in lcode. If other agents installed many skills you
|
|
99
|
+
don't need here, `lcode config set skills lcode` limits lcode to its own folders (`skills off` turns
|
|
100
|
+
skills off). However many there are, the list in the model's instructions stays within about 5% of
|
|
101
|
+
the context window: with many skills, each description is shortened so that all of them stay
|
|
102
|
+
listed. The same skill installed in two folders is used once. The format is the
|
|
103
|
+
[Agent Skills specification](https://agentskills.io/specification); like other agents, lcode is
|
|
104
|
+
lenient with skills that bend its rules (a name with capital letters, an unquoted colon in a
|
|
105
|
+
description) and skips only those without a description. `/help` lists the skills it found and
|
|
106
|
+
any it skipped.
|
|
107
|
+
|
|
108
|
+
## Approving a repository's commands, skills and agents
|
|
109
|
+
|
|
110
|
+
A repository's commands, skills and [agents](agents.md#custom-agents) steer the model, and skills
|
|
111
|
+
can bring scripts. A freshly cloned repository shouldn't be able to do that silently, so the first
|
|
112
|
+
time you start lcode in a repository that has any, it asks:
|
|
113
|
+
|
|
114
|
+
```text
|
|
115
|
+
This repository brings its own commands, skills or agents:
|
|
116
|
+
commands: /review
|
|
117
|
+
skills: commit-message
|
|
118
|
+
They can steer the model and include scripts it may run (commands still ask first, unless you
|
|
119
|
+
allow them).
|
|
120
|
+
Use them? [y/N]
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
lcode asks again whenever any of their files change. Until you say yes, only your own commands and
|
|
124
|
+
skills are used. `lcode -p` never asks and doesn't use them.
|
|
125
|
+
|
|
126
|
+
## Examples
|
|
127
|
+
|
|
128
|
+
The lcode repository has a ready-made command and skill in
|
|
129
|
+
[`examples/`](https://github.com/nasser1941/lcode/tree/main/examples): `/review` and the
|
|
130
|
+
`commit-message` skill above. Copy them into `.lcode/` of a repository, or into
|
|
131
|
+
`~/.config/lcode/` to have them everywhere.
|
|
@@ -20,7 +20,7 @@ lcode config path # print the file location
|
|
|
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
|
-
| `permission_mode` | `ask` | `ask`, `auto-edit` or `yolo` |
|
|
23
|
+
| `permission_mode` | `ask` | `ask`, `plan`, `auto-edit` or `yolo` |
|
|
24
24
|
| `think` | `true` | Let the model reason before answering |
|
|
25
25
|
| `web` | `on` | Web search and page fetching: `on`, `ask` (before each search/website) or `off` |
|
|
26
26
|
| `search_backend` | `auto` | `auto`, `ollama`, `brave`, `tavily` or `searxng`; `auto` uses the first one configured |
|
|
@@ -31,6 +31,7 @@ lcode config path # print the file location
|
|
|
31
31
|
| `vision_model` | `auto` | The model that [looks at images](usage.md#images): `auto`, `off` or an Ollama model that can see |
|
|
32
32
|
| `mcp_tools` | `auto` | How [MCP](mcp.md#context) tool definitions reach the model: `auto`, `direct` or `search` (on demand) |
|
|
33
33
|
| `memory` | `ask` | [Notes that carry over](memory.md) to later sessions: `ask` (confirm each), `auto` or `off` |
|
|
34
|
+
| `skills` | `all` | Which [skills](commands.md#skills) the model is offered: `all` (lcode's folders and the ones other agents share), `lcode` (only `.lcode/skills/` and `~/.config/lcode/skills/`) or `off` |
|
|
34
35
|
| `subagents` | `true` | Let the model hand tasks to [subagents](agents.md) with their own context |
|
|
35
36
|
| `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)) |
|
|
36
37
|
| `checkpoints` | `true` | Save a checkpoint before the model changes files, so [`/undo`](usage.md#undo-and-checkpoints) can restore them |
|
|
@@ -74,6 +75,8 @@ Environment variables override the file, which is useful for one-off runs and CI
|
|
|
74
75
|
| `~/.local/state/lcode/mcp-logs/` | Error output of local MCP servers |
|
|
75
76
|
| `~/.local/state/lcode/checkpoints/` | Checkpoints for `/undo` (copies of your project's files; deleted after 14 days) |
|
|
76
77
|
| `~/.local/state/lcode/memory/` | [Memory](memory.md) notes: `user/` for every repository, `projects/<repository>/` for each one |
|
|
78
|
+
| `~/.config/lcode/commands/`, `~/.config/lcode/skills/` | Your [commands and skills](commands.md) (a repository's go in `.lcode/`) |
|
|
79
|
+
| `~/.local/state/lcode/extensions-approved.json` | Repositories whose commands, skills and agents you approved |
|
|
77
80
|
| `~/.config/lcode/agents/` | Your [custom agents](agents.md#custom-agents) (a repository's go in `.lcode/agents/`) |
|
|
78
81
|
| `~/.local/state/lcode/limits.json` | Context sizes that ran out of GPU memory on this machine (safe to delete) |
|
|
79
82
|
|
|
@@ -89,6 +89,9 @@ the Ollama server you configure, it only contacts the web when the model searche
|
|
|
89
89
|
| `bench.py` | `lcode bench`: the benchmark tasks, their checks and the reports |
|
|
90
90
|
| `vision.py` | Looking at images with a model that can see |
|
|
91
91
|
| `subagents.py` | Subagents: agent types, running them (also in parallel), worktrees for workers |
|
|
92
|
+
| `extensions.py` | Custom commands and skills, and approving a repository's own |
|
|
93
|
+
| `frontmatter.py` | The `---` headers of notes, agents, commands and skills |
|
|
94
|
+
| `planning.py` | Plan mode: what it allows, presenting a plan and approving it |
|
|
92
95
|
| `memory.py` | Notes that carry over between sessions, and the end-of-session check |
|
|
93
96
|
| `sandbox.py` | The optional container for shell commands |
|
|
94
97
|
| `checkpoints.py` | Snapshots before the model changes files, for `/undo` and `/rewind` |
|
|
@@ -20,6 +20,7 @@ lcode mcp [catalog|add|list] # connect MCP servers: Jira, GitHub, AWS, databases
|
|
|
20
20
|
| `-r, --repo DIR` | Work in another directory |
|
|
21
21
|
| `-c, --continue` | Continue the most recently used session in this directory |
|
|
22
22
|
| `--resume [SESSION]` | Resume a saved session: pick from a list, or give its number, name or id |
|
|
23
|
+
| `--plan` | Start in [plan mode](#plan-mode): agree on a plan before anything changes |
|
|
23
24
|
| `--auto-edit` | Apply file edits without asking (commands still ask) |
|
|
24
25
|
| `--yolo` | Never ask for permission |
|
|
25
26
|
| `--no-think` | Turn off the model's reasoning: faster, less accurate |
|
|
@@ -38,7 +39,7 @@ lcode mcp [catalog|add|list] # connect MCP servers: Jira, GitHub, AWS, databases
|
|
|
38
39
|
| ++esc++ ++enter++ or a trailing `\` | New line |
|
|
39
40
|
| ++ctrl+c++ | Interrupt the model or a running command |
|
|
40
41
|
| ++ctrl+d++ | Quit |
|
|
41
|
-
| ++shift+tab++ | Cycle permission mode: ask → auto-edit → yolo |
|
|
42
|
+
| ++shift+tab++ | Cycle permission mode: ask → plan → auto-edit → yolo |
|
|
42
43
|
| ++tab++ | Complete slash commands and `@` paths |
|
|
43
44
|
| `@path` | Attach a file (or a directory listing) to your message |
|
|
44
45
|
| `@name` | Ask for a [subagent](agents.md) of that type, e.g. `@plan` |
|
|
@@ -58,17 +59,19 @@ reasoning is on.
|
|
|
58
59
|
| `/undo` | Undo the file changes of the last request ([details](#undo-and-checkpoints)) |
|
|
59
60
|
| `/rewind [N]` | Go back to before request N: its files, and optionally the conversation |
|
|
60
61
|
| `/checkpoints` | List the requests that changed files, and which files |
|
|
62
|
+
| `/name [args]` | Run one of your [commands or skills](commands.md); `/help` lists them |
|
|
61
63
|
| `/agents [N]` | [Subagent](agents.md) types, and what this session's subagents did |
|
|
62
64
|
| `/remember [-g] TEXT` | Save a [note](memory.md) for later sessions (`-g`: for every repository) |
|
|
63
65
|
| `/memory [show\|edit\|delete N]` | The [notes](memory.md) lcode remembers |
|
|
64
66
|
| `/sandbox [network on\|off]` | The [sandbox](sandbox.md) for shell commands |
|
|
65
67
|
| `/mcp [tools\|login\|restart NAME]` | [MCP servers](mcp.md), their status and tools |
|
|
68
|
+
| `/plan [request]` | Work out a [plan](#plan-mode) before changing anything, or show the approved plan |
|
|
66
69
|
| `/compact [focus]` | Summarize the conversation to free context |
|
|
67
70
|
| `/context [size]` | Show how full the context window is and change its size: pick from a list with memory estimates, or give a size like `/context 128k` (`/ctx` is a shortcut) |
|
|
68
71
|
| `/model [name]`, `/models` | Switch model, list models |
|
|
69
72
|
| `/think [on\|off]` | Toggle reasoning |
|
|
70
73
|
| `/verbose` | Toggle showing the reasoning text |
|
|
71
|
-
| `/mode [ask\|auto-edit\|yolo]` | Set the permission mode |
|
|
74
|
+
| `/mode [ask\|plan\|auto-edit\|yolo]` | Set the permission mode |
|
|
72
75
|
| `/cd DIR` | Change the working directory |
|
|
73
76
|
| `/todos` | Show the model's task list |
|
|
74
77
|
| `/exit` | Quit |
|
|
@@ -90,6 +93,8 @@ reasoning is on.
|
|
|
90
93
|
| `view_image` | Look at an image: a model that can see describes it ([Images](#images)) |
|
|
91
94
|
| `agent` | Hand a task to a [subagent](agents.md) with its own context; only its report comes back |
|
|
92
95
|
| `memory` | Save, update or delete [notes](memory.md) that later sessions load |
|
|
96
|
+
| `skill` | Load a [skill](commands.md#skills)'s instructions when a task matches it |
|
|
97
|
+
| `present_plan` | In [plan mode](#plan-mode): show the plan and ask for approval |
|
|
93
98
|
|
|
94
99
|
lcode refuses to edit a file the model hasn't read in the session, or one that changed on disk since
|
|
95
100
|
it was read, so the model always edits the current version.
|
|
@@ -127,12 +132,16 @@ image support off with `lcode config set vision_model off`.
|
|
|
127
132
|
| Mode | File edits | Shell commands |
|
|
128
133
|
|---|---|---|
|
|
129
134
|
| `ask` (default) | ask | ask, except read-only commands |
|
|
135
|
+
| `plan` | refused | only read-only commands ([Plan mode](#plan-mode)) |
|
|
130
136
|
| `auto-edit` | automatic | ask, except read-only commands |
|
|
131
137
|
| `yolo` | automatic | automatic |
|
|
132
138
|
|
|
139
|
+
++shift+tab++ cycles through them in this order, `/mode` sets one, and `--plan`, `--auto-edit` and
|
|
140
|
+
`--yolo` start in one.
|
|
141
|
+
|
|
133
142
|
Read-only commands run without asking: `ls`, `cat`, `head`, `tail`, `grep`, `rg`, `find`, `tree`,
|
|
134
143
|
`wc`, `diff`, `git status/log/diff/show/branch/blame` and similar, as long as they don't redirect
|
|
135
|
-
output, chain commands or run subshells.
|
|
144
|
+
output, chain commands or run subshells. A `cd <folder> &&` in front is fine.
|
|
136
145
|
|
|
137
146
|
When asked, answer ++y++ (once), ++a++ (always, for this command or for all edits, until you quit)
|
|
138
147
|
or ++n++. Text after ++n++ goes to the model as instructions: `n run the tests with -x first`.
|
|
@@ -146,6 +155,42 @@ or ++n++. Text after ++n++ goes to the model as instructions: `n run the tests w
|
|
|
146
155
|
With the [sandbox](sandbox.md) on, `auto-edit` mode runs shell commands without asking too: they can
|
|
147
156
|
only reach the project, and `/undo` can take their changes back.
|
|
148
157
|
|
|
158
|
+
## Plan mode
|
|
159
|
+
|
|
160
|
+
Local models are slower than cloud models and make more mistakes, so on a bigger change it pays to
|
|
161
|
+
agree on the approach before the model starts editing. In **plan mode** the model can read, search,
|
|
162
|
+
run read-only commands, use the web and [explore and plan subagents](agents.md), but it can't
|
|
163
|
+
change anything. It ends by presenting a plan: numbered steps, the files it will change, the risks
|
|
164
|
+
and how it will verify the work.
|
|
165
|
+
|
|
166
|
+
```text
|
|
167
|
+
❯ /plan add retries to the webhook handlers
|
|
168
|
+
…
|
|
169
|
+
╭─ Plan: Retries for webhook handlers ───────────────────────────────────────────╮
|
|
170
|
+
│ 1. Wrap the HTTP call in payments/webhooks.py:88 in a retry loop (3 tries, …) │
|
|
171
|
+
│ 2. Add tests for a timeout and a 500 in tests/test_webhooks.py │
|
|
172
|
+
│ Risks: duplicate deliveries if the endpoint isn't idempotent … │
|
|
173
|
+
│ Verify: pytest tests/test_webhooks.py │
|
|
174
|
+
╰────────────────────────────────────────────────────────────────────────────────╯
|
|
175
|
+
[y] run it, asking before changes · [a] run it, edits without asking (auto-edit)
|
|
176
|
+
[e] edit the plan · [s] save it to .lcode/plans/ · [n] keep planning (+ what to change)
|
|
177
|
+
>
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
| Answer | |
|
|
181
|
+
|---|---|
|
|
182
|
+
| ++y++ or ++enter++ | Approve: lcode switches to `ask` mode and the model starts on the plan right away |
|
|
183
|
+
| ++a++ | Approve and switch to `auto-edit`, so file edits don't ask |
|
|
184
|
+
| ++e++ | Edit the plan in your editor first; the model follows your version |
|
|
185
|
+
| ++s++ | Save it as `.lcode/plans/<title>.md`, for example to share it or commit it |
|
|
186
|
+
| ++n++ + text | Send it back: `n keep the old API working` |
|
|
187
|
+
|
|
188
|
+
After approval, the todo list is filled from the plan's numbered steps, and the plan is kept word
|
|
189
|
+
for word when the conversation is compacted. `/plan` shows the approved plan.
|
|
190
|
+
|
|
191
|
+
Start planning with `/plan <request>` (switches to plan mode and sends the request), with
|
|
192
|
+
++shift+tab++ (one step from `ask`), or with `lcode --plan`.
|
|
193
|
+
|
|
149
194
|
## Undo and checkpoints
|
|
150
195
|
|
|
151
196
|
Before the model first changes anything in a request (an edit, a new file, or a shell command that
|
|
@@ -233,6 +278,9 @@ At startup lcode reads `AGENTS.md` (or `LCODE.md`, or `CLAUDE.md`) from the work
|
|
|
233
278
|
adds it to the model's instructions. Use it for build and test commands, architecture notes and
|
|
234
279
|
conventions. `/init` writes a first version for you.
|
|
235
280
|
|
|
281
|
+
Instructions that are only needed for some tasks fit better in a [command or skill](commands.md),
|
|
282
|
+
which costs no context until it's used.
|
|
283
|
+
|
|
236
284
|
What doesn't belong in `AGENTS.md` but should carry over, such as your corrections and preferences,
|
|
237
285
|
goes into lcode's [memory](memory.md): short notes the model, you (`/remember`) or a short check at
|
|
238
286
|
the end of a session save, and that every later session in the repository loads.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Examples
|
|
2
|
+
|
|
3
|
+
Ready-made extensions for lcode. Copy them into a repository (or into `~/.config/lcode/` to use
|
|
4
|
+
them everywhere):
|
|
5
|
+
|
|
6
|
+
| Example | Copy to | Use it |
|
|
7
|
+
|---|---|---|
|
|
8
|
+
| [`commands/review.md`](commands/review.md) | `.lcode/commands/review.md` | `/review` or `/review the parser` |
|
|
9
|
+
| [`skills/commit-message/`](skills/commit-message/) | `.lcode/skills/commit-message/` | ask for a commit message, or `/commit-message` |
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
mkdir -p .lcode/commands .lcode/skills
|
|
13
|
+
cp examples/commands/review.md .lcode/commands/
|
|
14
|
+
cp -r examples/skills/commit-message .lcode/skills/
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
See [Commands and skills](https://nasser1941.github.io/lcode/commands/) for the format.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: review the uncommitted changes for bugs and missing tests
|
|
3
|
+
argument-hint: "[path or what to focus on]"
|
|
4
|
+
allowed-tools: read_file grep glob list_dir bash
|
|
5
|
+
---
|
|
6
|
+
Review the uncommitted changes in this repository. $ARGUMENTS
|
|
7
|
+
|
|
8
|
+
Run `git diff` and `git diff --cached` to see them, and read the code around them where needed.
|
|
9
|
+
|
|
10
|
+
Report, most important first:
|
|
11
|
+
1. Bugs: wrong behavior, unhandled errors and edge cases, with `path:line`.
|
|
12
|
+
2. Missing or weak tests for the changed behavior.
|
|
13
|
+
3. Anything that doesn't match the code around it.
|
|
14
|
+
|
|
15
|
+
Don't change any files.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: commit-message
|
|
3
|
+
description: Writes a git commit message for the staged changes, in the style the repository already uses. Use when the user asks for a commit message, or asks you to commit their changes.
|
|
4
|
+
license: MIT
|
|
5
|
+
---
|
|
6
|
+
# Commit messages
|
|
7
|
+
|
|
8
|
+
1. Run `scripts/staged.sh` from this skill's folder (with its absolute path). It prints the staged
|
|
9
|
+
files and the subjects of the last 15 commits.
|
|
10
|
+
2. If nothing is staged, tell the user and stop. Don't stage files yourself unless they asked.
|
|
11
|
+
3. Read the staged diff (`git diff --cached`) of the files that matter.
|
|
12
|
+
4. Match the style of the recent subjects: imperative mood or not, prefixes such as `feat:` or
|
|
13
|
+
`fix(scope):` only if the repository uses them, capitalization and length.
|
|
14
|
+
5. Write a subject under 72 characters that says what the change does. For anything but a trivial
|
|
15
|
+
change, add a blank line and a short body that says why, wrapped at 72 characters.
|
|
16
|
+
6. Show the message. Commit only if the user asked you to: `git commit -F -` with the message on
|
|
17
|
+
standard input.
|
|
@@ -71,6 +71,8 @@ ignore = [
|
|
|
71
71
|
"src/lcode/agent.py" = ["E501"] # the prompts are prose; wrapping them would change what the model sees
|
|
72
72
|
"src/lcode/memory.py" = ["E501"]
|
|
73
73
|
"src/lcode/subagents.py" = ["E501"]
|
|
74
|
+
"src/lcode/planning.py" = ["E501"]
|
|
75
|
+
"src/lcode/extensions.py" = ["E501"]
|
|
74
76
|
|
|
75
77
|
[tool.pytest.ini_options]
|
|
76
78
|
testpaths = ["tests"]
|
|
@@ -21,7 +21,7 @@ from rich.markup import escape
|
|
|
21
21
|
from rich.panel import Panel
|
|
22
22
|
from rich.text import Text
|
|
23
23
|
|
|
24
|
-
from lcode import catalog, limits, sessions, subagents, vision, web
|
|
24
|
+
from lcode import catalog, extensions, limits, planning, sessions, subagents, vision, web
|
|
25
25
|
from lcode import memory as memory_notes
|
|
26
26
|
from lcode.checkpoints import Checkpoints
|
|
27
27
|
from lcode.config import format_tokens
|
|
@@ -32,6 +32,7 @@ from lcode.render import MarkdownStreamer
|
|
|
32
32
|
from lcode.sandbox import Sandbox, SandboxError, project_root
|
|
33
33
|
from lcode.tools import (
|
|
34
34
|
MEMORY_SCHEMA,
|
|
35
|
+
PRESENT_PLAN_SCHEMA,
|
|
35
36
|
SCHEMAS,
|
|
36
37
|
VIEW_IMAGE_SCHEMA,
|
|
37
38
|
WEB_FETCH_SCHEMA,
|
|
@@ -77,7 +78,7 @@ SYSTEM_PROMPT = """You are lcode, an autonomous software-engineering agent runni
|
|
|
77
78
|
|
|
78
79
|
# Top-level layout of the working directory
|
|
79
80
|
{tree}
|
|
80
|
-
{web}{agents}{project}{notes}"""
|
|
81
|
+
{web}{agents}{skills}{project}{notes}"""
|
|
81
82
|
|
|
82
83
|
WEB_PROMPT = """
|
|
83
84
|
# Web access
|
|
@@ -170,6 +171,8 @@ class Settings:
|
|
|
170
171
|
vision_model: str = "auto" # auto, off or an Ollama model that can see images
|
|
171
172
|
memory: str = "off" # off, ask or auto: notes that carry over to later sessions (lcode.memory)
|
|
172
173
|
subagents: bool = False # the agent tool (lcode.subagents)
|
|
174
|
+
trust_project: bool = False # use the repository's own commands, skills and agents (lcode.extensions)
|
|
175
|
+
skills: str = "off" # all, lcode (only lcode's own skill folders) or off
|
|
173
176
|
max_parallel_agents: int = 1
|
|
174
177
|
|
|
175
178
|
|
|
@@ -198,6 +201,9 @@ class Agent:
|
|
|
198
201
|
self._memory: memory_notes.Memory | None = None
|
|
199
202
|
self._agent_types: tuple[Path, dict[str, subagents.AgentType], list[str]] | None = None
|
|
200
203
|
self.agent_runs: list[subagents.Record] = [] # subagents run in this session, for /agents
|
|
204
|
+
self.plan = "" # the plan the user approved; kept through compaction
|
|
205
|
+
self._extensions: tuple[Path, extensions.Extensions] | None = None
|
|
206
|
+
self.skills_loaded: set[str] = set() # skills whose instructions are in the conversation
|
|
201
207
|
# Set on subagents (see lcode.subagents):
|
|
202
208
|
self.allowed_tools: set[str] | None = None # None: every tool
|
|
203
209
|
self.read_only = False # only read-only shell commands
|
|
@@ -234,8 +240,15 @@ class Agent:
|
|
|
234
240
|
notes=self.memory().prompt(self.settings.context) if self.settings.memory != "off" else "",
|
|
235
241
|
web=self.web_prompt(),
|
|
236
242
|
agents=self.agents_prompt(),
|
|
243
|
+
skills=extensions.skills_prompt(self.extensions().skills, self.settings.context),
|
|
237
244
|
)
|
|
238
245
|
|
|
246
|
+
def extensions(self) -> extensions.Extensions:
|
|
247
|
+
"""Custom commands and skills for the current folder (a repository's only once approved)."""
|
|
248
|
+
if self._extensions is None or self._extensions[0] != self.cwd:
|
|
249
|
+
self._extensions = (self.cwd, extensions.load(self.cwd, self.settings.trust_project, self.settings.skills))
|
|
250
|
+
return self._extensions[1]
|
|
251
|
+
|
|
239
252
|
def agents_prompt(self) -> str:
|
|
240
253
|
if not self.settings.subagents:
|
|
241
254
|
return ""
|
|
@@ -250,7 +263,7 @@ class Agent:
|
|
|
250
263
|
def agent_types(self) -> dict[str, subagents.AgentType]:
|
|
251
264
|
"""Built-in and custom agent types for the current folder."""
|
|
252
265
|
if self._agent_types is None or self._agent_types[0] != self.cwd:
|
|
253
|
-
types, problems = subagents.load_types(self.cwd)
|
|
266
|
+
types, problems = subagents.load_types(self.cwd, self.settings.trust_project)
|
|
254
267
|
self._agent_types = (self.cwd, types, problems)
|
|
255
268
|
return self._agent_types[1]
|
|
256
269
|
|
|
@@ -259,6 +272,9 @@ class Agent:
|
|
|
259
272
|
assert self._agent_types is not None
|
|
260
273
|
return self._agent_types[2]
|
|
261
274
|
|
|
275
|
+
def planning(self) -> bool:
|
|
276
|
+
return self.perms.mode == "plan"
|
|
277
|
+
|
|
262
278
|
def tool_names(self) -> set[str]:
|
|
263
279
|
return {s["function"]["name"] for s in self.tool_schemas()}
|
|
264
280
|
|
|
@@ -283,6 +299,10 @@ class Agent:
|
|
|
283
299
|
schemas.append(MEMORY_SCHEMA)
|
|
284
300
|
if self.settings.subagents:
|
|
285
301
|
schemas.append(subagents.schema(self.agent_types(), self.settings.max_parallel_agents))
|
|
302
|
+
if self.planning():
|
|
303
|
+
schemas.append(PRESENT_PLAN_SCHEMA)
|
|
304
|
+
if self.extensions().skills:
|
|
305
|
+
schemas.append(extensions.schema(self.extensions().skills))
|
|
286
306
|
if self.mcp:
|
|
287
307
|
schemas += self.mcp.schemas(self.settings.context)
|
|
288
308
|
if self.allowed_tools is not None:
|
|
@@ -402,6 +422,7 @@ class Agent:
|
|
|
402
422
|
|
|
403
423
|
def new_session(self) -> None:
|
|
404
424
|
self.reset()
|
|
425
|
+
self.skills_loaded.clear()
|
|
405
426
|
self.session_id = self.new_session_id()
|
|
406
427
|
self.session_name = ""
|
|
407
428
|
self.session_title = ""
|
|
@@ -599,6 +620,8 @@ class Agent:
|
|
|
599
620
|
return f"list_dir({args.get('path', '.')})"
|
|
600
621
|
if name == "memory":
|
|
601
622
|
return f"memory({' '.join(str(args.get(k) or '') for k in ('action', 'name')).strip()})"
|
|
623
|
+
if name == "skill":
|
|
624
|
+
return f"skill({args.get('name', '')})"
|
|
602
625
|
if name == "agent":
|
|
603
626
|
return f"agent({args.get('type', '')}: {args.get('description') or str(args.get('task', ''))[:50]})"
|
|
604
627
|
if name == "bash":
|
|
@@ -638,7 +661,8 @@ class Agent:
|
|
|
638
661
|
|
|
639
662
|
def _run_turn(self, user_text: str, max_steps: int = MAX_STEPS_PER_TURN) -> None:
|
|
640
663
|
self.prepare_mcp()
|
|
641
|
-
self.
|
|
664
|
+
note = planning.NOTE if self.planning() and self.allowed_tools is None else ""
|
|
665
|
+
self.messages.append({"role": "user", "content": self.expand_mentions(user_text) + note})
|
|
642
666
|
malformed = 0
|
|
643
667
|
for _ in range(max_steps):
|
|
644
668
|
if self.cancel is not None and self.cancel.is_set():
|
|
@@ -777,6 +801,14 @@ class Agent:
|
|
|
777
801
|
{"role": "user", "content": f"[Summary of our conversation so far]\n\n{summary}"},
|
|
778
802
|
{"role": "assistant", "content": "Got it — I have the context from the summary and will continue."},
|
|
779
803
|
]
|
|
804
|
+
if self.plan: # the approved plan stays word for word
|
|
805
|
+
self.messages[1]["content"] += f"\n\n[The plan the user approved; keep following it]\n\n{self.plan}"
|
|
806
|
+
if self.skills_loaded: # their instructions were in the old messages: load them again when needed
|
|
807
|
+
names = ", ".join(sorted(self.skills_loaded))
|
|
808
|
+
self.messages[1]["content"] += (
|
|
809
|
+
f"\n\n[Skills in use before the summary: {names}. Load them again with the skill tool if you still need them.]"
|
|
810
|
+
)
|
|
811
|
+
self.skills_loaded.clear()
|
|
780
812
|
self.ctx_used = sum(len(m["content"]) for m in self.messages) // 3
|
|
781
813
|
self.reflected = len(self.messages)
|
|
782
814
|
self.console.print(Panel(Markdown(summary), title="Compacted summary", border_style="blue"))
|