Filesystem tools exposed as bare symbols in the Python sandbox.
Two layers:
Structured helpers for read / tree / search:
(cat path) ; -> {:path :anchors {<N:hash> text…} :next-offset N? :truncated? B}
(cat path n) ; first n lines from line 1
(cat path offset n) ; n lines starting at line offset (1-based)
(cat path :tail) ; last 400 lines (tail)
(cat path :tail n) ; last n lines
(ls path) ; -> nested dict tree (name/path/type/size/children)
(ls path opts) ; opts keys: depth / is_hidden / is_respect_gitignore
(rg query) ; -> content hits; query = a term or list of terms (OR),
; smart-case substring. Opts: paths/include/context/is_files_only
Cwd-safe wrappers over the babashka.fs file API. patch is
the canonical text edit surface:
(cat path) (patch [edit-map]) ; keys: path / from_anchor / replace (create-dirs path) (copy src dest) (move src dest) (delete path) (delete-if-exists path) (exists? path)
Hard guard: every path must stay inside the session's working
directory (fs/cwd); .. traversal is rejected before any I/O.
Filesystem tools exposed as bare symbols in the Python sandbox.
Two layers:
1. Structured helpers for read / tree / search:
(cat path) ; -> {:path :anchors {<N:hash> text…} :next-offset N? :truncated? B}
(cat path n) ; first n lines from line 1
(cat path offset n) ; n lines starting at line `offset` (1-based)
(cat path :tail) ; last 400 lines (tail)
(cat path :tail n) ; last n lines
(ls path) ; -> nested dict tree (name/path/type/size/children)
(ls path opts) ; opts keys: depth / is_hidden / is_respect_gitignore
(rg query) ; -> content hits; query = a term or list of terms (OR),
; smart-case substring. Opts: paths/include/context/is_files_only
2. Cwd-safe wrappers over the babashka.fs file API. `patch` is
the canonical text edit surface:
(cat path)
(patch [edit-map]) ; keys: path / from_anchor / replace
(create-dirs path)
(copy src dest)
(move src dest)
(delete path)
(delete-if-exists path)
(exists? path)
Hard guard: every path must stay inside the session's working
directory (`fs/cwd`); `..` traversal is rejected before any I/O.Structural outline: a high-level, line-ranged skeleton of a source file produced via tree-sitter (com.blockether/tree-sitter-language-pack, which sources Clojure from our own grammar fork).
Every item carries FULL anchors — the same <lineno>:<hash> anchors cat
emits and patch consumes — for its first and last line, so you can replace
a whole definition straight from the index with one
patch([{from_anchor start, to_anchor end, replace …}]), no intermediate
cat. Each line is:
<kind> <name> <signature> @<start-anchor>..<end-anchor>
e.g.
class Greeter @3:a1b..7:c2d function hello @6:1b2..7:c2d function main @9:3c4..10:5d6
Read it BEFORE cat: a cheap map of a file so you jump straight to the right
range (and its anchors) instead of reading the whole file.
Requiring this namespace also requires the native resolver, which selects the right per-platform FFI library at runtime.
Structural outline: a high-level, line-ranged skeleton of a source file
produced via tree-sitter (com.blockether/tree-sitter-language-pack, which
sources Clojure from our own grammar fork).
Every item carries FULL anchors — the same `<lineno>:<hash>` anchors `cat`
emits and `patch` consumes — for its first and last line, so you can replace
a whole definition straight from the index with one
`patch([{from_anchor start, to_anchor end, replace …}])`, no intermediate
`cat`. Each line is:
<kind> <name> <signature> @<start-anchor>..<end-anchor>
e.g.
class Greeter @3:a1b..7:c2d
function hello @6:1b2..7:c2d
function main @9:3c4..10:5d6
Read it BEFORE `cat`: a cheap map of a file so you jump straight to the right
range (and its anchors) instead of reading the whole file.
Requiring this namespace also requires the native resolver, which selects the
right per-platform FFI library at runtime.Fuzzy line-based matching toolkit used by patch exact-replace.
This namespace USED to also carry the Codex apply_patch envelope
parser, but envelope mode was retired — we consolidated to a single
per-intent mutation surface (patch exact-replace + write /
move / delete). The fuzzy matcher stays because it is what
lets multi-line :search blocks tolerate whitespace and typographic
drift before they fall through to :no-match.
Public surface (all pure): seek-sequence lines pattern start eof? -> start-index or nil seek-sequence-with-pass lines pattern start eof? -> {:start :pass :indent-delta?} or nil split-content-lines string -> vec of lines (no trailing \n element) char-offset-at-line content line-idx -> char offset apply-indent-delta delta lines -> re-indented lines
It also owns the reusable HASHLINE layer (content-addressed editing):
line-hash / lines->anchors text -> 6-hex anchor / {ln hash}
render-hashline-block / -range-block tuples -> <hash>| text gutter
indices-matching-hash / resolve-anchor-edit self-locating range replace
Fuzzy line-based matching toolkit used by `patch` exact-replace.
This namespace USED to also carry the Codex `apply_patch` envelope
parser, but envelope mode was retired — we consolidated to a single
per-intent mutation surface (`patch` exact-replace + `write` /
`move` / `delete`). The fuzzy matcher stays because it is what
lets multi-line `:search` blocks tolerate whitespace and typographic
drift before they fall through to `:no-match`.
Public surface (all pure):
seek-sequence lines pattern start eof? -> start-index or nil
seek-sequence-with-pass lines pattern start eof?
-> {:start :pass :indent-delta?} or nil
split-content-lines string -> vec of lines (no trailing \n element)
char-offset-at-line content line-idx -> char offset
apply-indent-delta delta lines -> re-indented lines
It also owns the reusable HASHLINE layer (content-addressed editing):
line-hash / lines->anchors text -> 6-hex anchor / {ln hash}
render-hashline-block / -range-block tuples -> `<hash>| text` gutter
indices-matching-hash / resolve-anchor-edit self-locating range replaceThin Clojure adapter over the pack's Java structural-edit engine
(dev.kreuzberg.treesitterlanguagepack.StructuralApi). All the work —
locate the definition by name from the tree-sitter outline, splice its line
span, and re-parse to refuse syntax-breaking edits — lives in Java so it is
language-neutral, reusable from any JVM consumer, and native-image clean.
This namespace only maps vis op keywords onto the Java API.
Thin Clojure adapter over the pack's Java structural-edit engine (`dev.kreuzberg.treesitterlanguagepack.StructuralApi`). All the work — locate the definition by name from the tree-sitter outline, splice its line span, and re-parse to refuse syntax-breaking edits — lives in Java so it is language-neutral, reusable from any JVM consumer, and native-image clean. This namespace only maps vis op keywords onto the Java API.
Language-neutral STRUCTURAL ZIPPER over the tree-sitter pack (306+ langs) —
the unified cursor the name-based structural ops were missing.
A node's location is a STATELESS PATH: a vector of NAMED-child indices from
the root (e.g. [2 0] = first named child of the third named child of the
file). Stateless means it round-trips cleanly through async tool calls — no
live native cursor to keep between calls. Relative moves (down/up/next/prev)
are pure path arithmetic on top, so the model navigates like a rewrite-clj
zipper but over EVERY language tree-sitter understands.
Edits splice the target node's UTF-8 byte range and RE-PARSE, refusing a
result that introduces a syntax error the original didn't have — the same
safety contract as structural. Pairs with the name-based ops: locate a def
by name, then walk into it by path.
All native handles (Parser/Tree/Node) are opened and closed inside each call; only plain Clojure data escapes.
Language-neutral STRUCTURAL ZIPPER over the tree-sitter pack (306+ langs) — the unified cursor the name-based `structural` ops were missing. A node's location is a STATELESS PATH: a vector of NAMED-child indices from the root (e.g. `[2 0]` = first named child of the third named child of the file). Stateless means it round-trips cleanly through async tool calls — no live native cursor to keep between calls. Relative moves (down/up/next/prev) are pure path arithmetic on top, so the model navigates like a rewrite-clj zipper but over EVERY language tree-sitter understands. Edits splice the target node's UTF-8 byte range and RE-PARSE, refusing a result that introduces a syntax error the original didn't have — the same safety contract as `structural`. Pairs with the name-based ops: locate a def by name, then walk into it by path. All native handles (Parser/Tree/Node) are opened and closed inside each call; only plain Clojure data escapes.
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |