Shoddy · Fettler
File, search and edit tools for a model and a script. One program, two front ends, and no shell between it and the file.
An assistant given Fettler cannot go wandering. Everything outside the boundary is denied. Every path it touches must sit inside a tree — a folder you named ahead of time. Outside those trees, everything is refused: writing, reading, listing, even learning that a file exists. There is no current directory to change. No path can climb out of a tree. There is no shell to sneak past it with. So the assistant cannot wander into a sibling project, an old copy, or your home directory, read the wrong thing, and then answer from it with complete confidence.
Inside the boundary, it does the work an assistant actually does on source files. It can find a file, search its contents, read it, write it, edit it, move it, copy it, and delete it. It can also run a named build task. It is written in C#, ships from this repository, and installs as one file. And nothing it does changes how you work. Your shell, your file explorer, your editor, and your git stay exactly as they were.
fettle. The command uses the verb form because
fettle move a.txt b.txt reads as an instruction, and
fettler move does not. Both spellings are correct. Neither
is a typo.Note This page asks you to type nothing. To have it working in about five minutes instead, go straight to the quick start.
| Bounded, not advisory | Every path resolves inside a tree you declared. Outside is refused identically whether or not the file exists, so a refusal cannot be used to probe a disk. No current directory, no path that climbs out, no shell to reach past it with. |
| Every answer is the next call's argument | search hands back tree:path:line:column. read numbers its lines and states a hash. edit asks for exactly those. Refused edits stop happening. |
| It reads more than source | Notebooks as cells, spreadsheets as rows with their formulas, Word as paragraphs under their headings, PDF as text per page, images as facts — and inside archives without unpacking them. |
| Batches are all or nothing | Every edit resolves before the first byte moves. A permission not granted, a file changed underneath, an anchor that no longer matches: any of these stops the whole batch with the tree exactly as it was. |
| Two front ends, one core | A CLI for a script, an MCP server for a model, over the same operations. Machine-readable mode puts the complete result on stdout — failures included. |
| Nothing changes how you work | Your shell, file explorer, editor and git stay exactly as they were. |
Rename a C# type in this repository and you touch 200 occurrences
across 23 files. That number is measured, not estimated —
fettle search counted it. This is the change nobody does by
hand, and every assistant is asked to do anyway.
| Built-in file tools | Fettler | |
|---|---|---|
| Calls | one search, then a read and an edit for each file — 47 | search, replace --dry-run, replace — 3 |
| Context spent | 23 whole files pulled through it | the matching lines |
| If it fails at file 15 | 14 files renamed, 9 not: a tree that no longer compiles, half-changed — and nothing says which half | nothing is written unless all 23 resolved first; if a write then fails, it names the file it stopped at and how many were already done |
| Per-file properties | whatever the writer happened to emit | each file keeps its own encoding, line endings and execute bit |
Optional, off by default, and it costs one line to try. A tree
can declare that certain things must not leave it. The first tier runs
inside fettle with nothing installed: labelled record
numbers, dates of birth, SSNs, Luhn-valid cards, emails, phone numbers.
"trees": {
"records": { "path": "./records", "can": ["list", "read"], "screen": ["identifiers"] }
}Anything it finds refuses the whole response rather than handing back a redacted copy that looks safe and is not — and an image, which it cannot read into, is refused rather than served unchecked.
And here is what it does not catch. Names, addresses,
conditions and free text need a model, which is a separate download.
identifiers is the only one of the four categories that
works with nothing installed; clinical,
legal and scientific screen nothing at all
until you install one, and fettle roots says so in as many
words rather than letting the category name imply otherwise.
How screening works →
burler, the model host the screen's second tier
uses, is a separate download wanted only by people who switch that tier
on.