README.md
README.md
Turns a local LM Studio model (built and tested against google/gemma-4-e4b, 7.5B) into something
close to a coding agent: it can orient itself in a repo, grep it, edit files surgically, run and watch
processes, read git history, fetch docs, and track its own checklist — all inside one folder you
choose, with every capability behind a switch that is off by default.
The model only sees tools whose capability is enabled, so the list stays small until you widen it.
| Config | Tools exposed |
|---|---|
| Default (everything off) | 12 — orient, read, search, checklist |
| + Allow writing files | 20 — adds the full edit suite and backups |
| + Allow shell | 32 — adds commands, retries, background processes, read-only git |
| + web, git writes, loops | 42 — everything |
Twelve tools is a comfortable working set for a 7.5B model; forty-two is not. Enable what the job needs and leave the rest off.
An LM Studio tools provider plugin. It gives any local model in LM Studio hands on a single folder: list, read, search, optionally write files, and optionally run shell commands.
Every filesystem path the model supplies is resolved against the workspace root and rejected if it escapes it, so a model cannot wander out of the folder you point it at.
| Tool | Always on? | What it does |
|---|---|---|
list_directory | yes | Lists entries at a path, with file sizes. |
read_file | yes | Reads a text file, truncated at the configured size limit. |
search_files | yes | Recursive case-insensitive text search, returns path:line: text. Skips node_modules, .git, dist, etc. Caps at 100 matches. |
write_file | only if Allow writing files | Writes a file, creating parent directories. Overwrites. |
run_command | only if Allow running shell commands | Runs a command with the workspace root as cwd, with a timeout. |
run_until_success | only if Allow running shell commands | Retries a command until it exits 0 or hits the attempt cap, with a delay between tries. Returns the last failure so the model can fix the cause. |
start_loop / check_loop / list_loops / stop_loop | only if Allow shell and Allow background interval loops | Background timer that re-runs a command every N seconds across messages, buffering the last 10 results. |
set_tasks / get_tasks / update_task | yes | Persistent checklist. The model plans steps, marks them in_progress / done / blocked, and can resume from it in a later message. |
project_overview / directory_tree / read_project_instructions / count_lines | yes | Orientation. project_overview detects the stack, scripts, git branch and layout in one call — what the model should run first in an unfamiliar folder. |
glob_files / grep / find_file | yes | Real discovery. grep takes a JavaScript regex with context lines and three output modes; glob_files supports **, *, ? and {a,b}, newest first. |
edit_file / multi_edit / insert_lines / replace_lines / preview_edit / list_backups / restore_file | only if Allow writing files | Surgical editing. edit_file refuses an ambiguous match and tells the model to add context; multi_edit is all-or-nothing; preview_edit is a dry run. Every mutation snapshots first. |
git_status / git_diff / git_log / git_show / git_blame | only if Allow shell | Read-only history and change awareness. |
git_add / git_commit / git_create_branch / git_restore | only if Allow git writes | Staging and committing. Push, reset --hard, clean and history rewriting are not implemented at any setting. |
start_process / read_process_output / write_process_input / stop_process / list_processes | only if Allow shell | Dev servers and watchers that outlive a tool call. Output is a ring buffer; reads are incremental so polling does not re-send the same lines. |
fetch_url / web_search | only if Allow web access | Reads real docs instead of hallucinating an API. Fetched page text is labelled as untrusted data in the result. |
verify | only if Allow shell | Detects and runs this project's typecheck, lint, build and test commands, then reports only the lines that matter. Closes the edit → check → fix loop without the model having to know the command. |
undo_last_edit | only if Allow writing files | Restores the most recently modified file from its automatic backup. |
apply_patch | only if Allow writing files | Applies a unified diff, all hunks or none. Tolerates drifted line numbers, refuses mismatched context. |
remember / recall | recall always; remember needs write | Durable project notes in .lmstudio-notes.md, so a convention learned today survives into next week's session. |
changed_files | yes | What the model has modified this session, derived from the backup trail. |
run_subagent delegates a job to a second prediction against the same loaded model, with its own
fresh context and a narrowed tool set, and returns only its final report. The point is context
isolation: a subagent can burn twenty tool calls crawling a codebase and hand back five lines, which
matters enormously when the main model has a small context window.
| Type | Powers | Tools | For |
|---|---|---|---|
explorer | read only, no shell | 11 | "where is X implemented, and how does it work" |
reviewer | read + git history | 17 | "review this file and list real problems" |
verifier | read + shell | 17 | "run the tests and tell me exactly what fails" |
worker | read + write + shell | 27 | one small, well-defined change, carried out end to end |
The scoping is structural, not advisory. A subagent's tools are built by the same factories the main
provider uses, but against a Workspace whose capability flags have been turned off — so a read-only
subagent is not asked to avoid editing, it is handed no edit tools at all. No type ever receives
run_subagent, so subagents cannot spawn subagents.
Guard rails: one subagent at a time, a step ceiling (config, hard max 25), a refusal if the task is too short to stand alone, and a refusal if the requested type needs a capability you have switched off. Each round is a full local prediction, so this trades wall-clock time for context.
Which model a subagent runs on. The same one you are chatting with, in the normal case. The SDK's
no-argument llm.model() returns any loaded model and will happily load one that was never asked
for, so it is deliberately not used: with Subagent model set, that key is used; with it empty, the
subagent takes a model from the already-loaded list and never triggers a load. Either way the report
names the model it ran on, so a wrong pick is visible rather than silent. Set the field explicitly if
you keep more than one model loaded.
The subagent also inherits the parent generation's abort signal, so stopping the chat stops the subagent instead of leaving it running against your GPU.
verify matters more than it looksA local model will happily edit five files and announce success without ever running anything. verify
removes the excuse: it reads package.json scripts (picking npm/pnpm/yarn/bun from the lockfile),
Cargo.toml, go.mod, pyproject.toml or a Makefile, runs what it finds, stops at the first
failure, and returns the error lines rather than a thousand lines of build spam. The operating brief
tells the model to call it after every batch of edits and to keep fixing until it is green.
Long conversations lose their beginning: once the chat exceeds the model's context window, the host drops the oldest turns and the model forgets decisions it made an hour ago.
A plugin cannot delete or rewrite earlier turns — a prompt preprocessor may only change the newest user message. So compaction works the other way round. When the conversation passes a configurable share of the context window (default 75%), the plugin summarises the older turns and attaches that summary to each new message. As the raw turns fall out of the window, the summary stays, because it now lives at the end of the conversation rather than the beginning.
The summary is deliberately factual: what the user is building, decisions that must not be revisited, files changed with paths, commands run and what they reported, and what is still outstanding.
Cost control matters here, because each refresh is a real generation on your local model:
Settings: Auto-compact long conversations (on) and Compact at (% of context) (75).
Registered alongside the tools, this is the piece that makes a small model behave like a coding
agent rather than merely having the buttons. It prepends a <workspace-context> block to each
message containing a tight operating brief (orient first, read before editing, prefer edit_file
over rewriting, verify after changing, keep the checklist current) plus live facts: workspace root,
git branch and dirty state (read straight from .git, never by spawning git), detected project type,
the current checklist, and the head of AGENTS.md / CLAUDE.md if present.
It is cached for ~30s per root, wrapped so a failure can never cost you your message, and switched off with Inject workspace context.
Configured per-chat in LM Studio's plugin settings panel:
Development (plugin lives only while this runs, hot-reloads on save):
Install permanently into LM Studio / publish to your LM Studio account:
Typecheck:
package.json must not set "type": "module" — LM Studio bundles the plugin as CommonJS and
a module-typed package makes the generated entrypoint fail with
ReferenceError: require is not defined in ES module scope.Turns a local LM Studio model (built and tested against google/gemma-4-e4b, 7.5B) into something
close to a coding agent: it can orient itself in a repo, grep it, edit files surgically, run and watch
processes, read git history, fetch docs, and track its own checklist — all inside one folder you
choose, with every capability behind a switch that is off by default.
The model only sees tools whose capability is enabled, so the list stays small until you widen it.
| Config | Tools exposed |
|---|---|
| Default (everything off) | 12 — orient, read, search, checklist |
| + Allow writing files | 20 — adds the full edit suite and backups |
| + Allow shell | 32 — adds commands, retries, background processes, read-only git |
| + web, git writes, loops | 42 — everything |
Twelve tools is a comfortable working set for a 7.5B model; forty-two is not. Enable what the job needs and leave the rest off.
An LM Studio tools provider plugin. It gives any local model in LM Studio hands on a single folder: list, read, search, optionally write files, and optionally run shell commands.
Every filesystem path the model supplies is resolved against the workspace root and rejected if it escapes it, so a model cannot wander out of the folder you point it at.
| Tool | Always on? | What it does |
|---|---|---|
list_directory | yes | Lists entries at a path, with file sizes. |
read_file | yes | Reads a text file, truncated at the configured size limit. |
search_files | yes | Recursive case-insensitive text search, returns path:line: text. Skips node_modules, .git, dist, etc. Caps at 100 matches. |
write_file | only if Allow writing files | Writes a file, creating parent directories. Overwrites. |
run_command | only if Allow running shell commands | Runs a command with the workspace root as cwd, with a timeout. |
run_until_success | only if Allow running shell commands | Retries a command until it exits 0 or hits the attempt cap, with a delay between tries. Returns the last failure so the model can fix the cause. |
start_loop / check_loop / list_loops / stop_loop | only if Allow shell and Allow background interval loops | Background timer that re-runs a command every N seconds across messages, buffering the last 10 results. |
set_tasks / get_tasks / update_task | yes | Persistent checklist. The model plans steps, marks them in_progress / done / blocked, and can resume from it in a later message. |
project_overview / directory_tree / read_project_instructions / count_lines | yes | Orientation. project_overview detects the stack, scripts, git branch and layout in one call — what the model should run first in an unfamiliar folder. |
glob_files / grep / find_file | yes | Real discovery. grep takes a JavaScript regex with context lines and three output modes; glob_files supports **, *, ? and {a,b}, newest first. |
edit_file / multi_edit / insert_lines / replace_lines / preview_edit / list_backups / restore_file | only if Allow writing files | Surgical editing. edit_file refuses an ambiguous match and tells the model to add context; multi_edit is all-or-nothing; preview_edit is a dry run. Every mutation snapshots first. |
git_status / git_diff / git_log / git_show / git_blame | only if Allow shell | Read-only history and change awareness. |
git_add / git_commit / git_create_branch / git_restore | only if Allow git writes | Staging and committing. Push, reset --hard, clean and history rewriting are not implemented at any setting. |
start_process / read_process_output / write_process_input / stop_process / list_processes | only if Allow shell | Dev servers and watchers that outlive a tool call. Output is a ring buffer; reads are incremental so polling does not re-send the same lines. |
fetch_url / web_search | only if Allow web access | Reads real docs instead of hallucinating an API. Fetched page text is labelled as untrusted data in the result. |
verify | only if Allow shell | Detects and runs this project's typecheck, lint, build and test commands, then reports only the lines that matter. Closes the edit → check → fix loop without the model having to know the command. |
undo_last_edit | only if Allow writing files | Restores the most recently modified file from its automatic backup. |
apply_patch | only if Allow writing files | Applies a unified diff, all hunks or none. Tolerates drifted line numbers, refuses mismatched context. |
remember / recall | recall always; remember needs write | Durable project notes in .lmstudio-notes.md, so a convention learned today survives into next week's session. |
changed_files | yes | What the model has modified this session, derived from the backup trail. |
run_subagent delegates a job to a second prediction against the same loaded model, with its own
fresh context and a narrowed tool set, and returns only its final report. The point is context
isolation: a subagent can burn twenty tool calls crawling a codebase and hand back five lines, which
matters enormously when the main model has a small context window.
| Type | Powers | Tools | For |
|---|---|---|---|
explorer | read only, no shell | 11 | "where is X implemented, and how does it work" |
reviewer | read + git history | 17 | "review this file and list real problems" |
verifier | read + shell | 17 | "run the tests and tell me exactly what fails" |
worker | read + write + shell | 27 | one small, well-defined change, carried out end to end |
The scoping is structural, not advisory. A subagent's tools are built by the same factories the main
provider uses, but against a Workspace whose capability flags have been turned off — so a read-only
subagent is not asked to avoid editing, it is handed no edit tools at all. No type ever receives
run_subagent, so subagents cannot spawn subagents.
Guard rails: one subagent at a time, a step ceiling (config, hard max 25), a refusal if the task is too short to stand alone, and a refusal if the requested type needs a capability you have switched off. Each round is a full local prediction, so this trades wall-clock time for context.
Which model a subagent runs on. The same one you are chatting with, in the normal case. The SDK's
no-argument llm.model() returns any loaded model and will happily load one that was never asked
for, so it is deliberately not used: with Subagent model set, that key is used; with it empty, the
subagent takes a model from the already-loaded list and never triggers a load. Either way the report
names the model it ran on, so a wrong pick is visible rather than silent. Set the field explicitly if
you keep more than one model loaded.
The subagent also inherits the parent generation's abort signal, so stopping the chat stops the subagent instead of leaving it running against your GPU.
verify matters more than it looksA local model will happily edit five files and announce success without ever running anything. verify
removes the excuse: it reads package.json scripts (picking npm/pnpm/yarn/bun from the lockfile),
Cargo.toml, go.mod, pyproject.toml or a Makefile, runs what it finds, stops at the first
failure, and returns the error lines rather than a thousand lines of build spam. The operating brief
tells the model to call it after every batch of edits and to keep fixing until it is green.
Long conversations lose their beginning: once the chat exceeds the model's context window, the host drops the oldest turns and the model forgets decisions it made an hour ago.
A plugin cannot delete or rewrite earlier turns — a prompt preprocessor may only change the newest user message. So compaction works the other way round. When the conversation passes a configurable share of the context window (default 75%), the plugin summarises the older turns and attaches that summary to each new message. As the raw turns fall out of the window, the summary stays, because it now lives at the end of the conversation rather than the beginning.
The summary is deliberately factual: what the user is building, decisions that must not be revisited, files changed with paths, commands run and what they reported, and what is still outstanding.
Cost control matters here, because each refresh is a real generation on your local model:
Settings: Auto-compact long conversations (on) and Compact at (% of context) (75).
Registered alongside the tools, this is the piece that makes a small model behave like a coding
agent rather than merely having the buttons. It prepends a <workspace-context> block to each
message containing a tight operating brief (orient first, read before editing, prefer edit_file
over rewriting, verify after changing, keep the checklist current) plus live facts: workspace root,
git branch and dirty state (read straight from .git, never by spawning git), detected project type,
the current checklist, and the head of AGENTS.md / CLAUDE.md if present.
It is cached for ~30s per root, wrapped so a failure can never cost you your message, and switched off with Inject workspace context.
Configured per-chat in LM Studio's plugin settings panel:
Development (plugin lives only while this runs, hot-reloads on save):
Install permanently into LM Studio / publish to your LM Studio account:
Typecheck:
package.json must not set "type": "module" — LM Studio bundles the plugin as CommonJS and
a module-typed package makes the generated entrypoint fail with
ReferenceError: require is not defined in ES module scope.run_until_success. Tight inner loop inside one tool call. Attempt count is
capped by Max retry attempts regardless of what the model asks for.start_loop. Survives between messages, ticks on a timer, fires once
immediately so the model gets a first result without waiting a full interval. Bounded by
Minimum loop interval, a max_runs argument (hard ceiling 200), and a limit of 5 concurrent
loops. Loops die when the plugin process stops.set_tasks / update_task. Not a timer at all; it is durable state so a long job
survives across turns. Written to .lmstudio-tasks.json in the workspace root only if
Allow writing files is on — otherwise it lives in plugin memory, so the write toggle is never
quietly bypassed.search_files and the
output buffer of run_command.run_until_success.start_loop, so a model cannot
busy-spin your machine.cd C:/Users/Admin/lmstudio-plugins/workspace-tools && npx lms dev
cd C:/Users/Admin/lmstudio-plugins/workspace-tools && npx lms push
cd C:/Users/Admin/lmstudio-plugins/workspace-tools && npx tsc --noEmit
run_until_success. Tight inner loop inside one tool call. Attempt count is
capped by Max retry attempts regardless of what the model asks for.start_loop. Survives between messages, ticks on a timer, fires once
immediately so the model gets a first result without waiting a full interval. Bounded by
Minimum loop interval, a max_runs argument (hard ceiling 200), and a limit of 5 concurrent
loops. Loops die when the plugin process stops.set_tasks / update_task. Not a timer at all; it is durable state so a long job
survives across turns. Written to .lmstudio-tasks.json in the workspace root only if
Allow writing files is on — otherwise it lives in plugin memory, so the write toggle is never
quietly bypassed.search_files and the
output buffer of run_command.run_until_success.start_loop, so a model cannot
busy-spin your machine.cd C:/Users/Admin/lmstudio-plugins/workspace-tools && npx lms dev
cd C:/Users/Admin/lmstudio-plugins/workspace-tools && npx lms push
cd C:/Users/Admin/lmstudio-plugins/workspace-tools && npx tsc --noEmit