pi-fence-check
Syntax-check fenced code blocks in assistant messages (text + thinking) via tree-sitter WASM — 112 languages, real-time, quiet by design.
Package details
Install pi-fence-check from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:pi-fence-check- Package
pi-fence-check- Version
0.3.1- Published
- Aug 13, 2026
- Downloads
- 286/mo · 12/wk
- Author
- nuctori
- License
- MIT
- Types
- extension, skill
- Size
- 425.7 KB
- Dependencies
- 2 dependencies · 0 peers
Pi manifest JSON
{
"extensions": [
"./index.ts"
],
"skills": [
"./skills"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
fence-check
Syntax-check fenced code blocks in assistant messages via tree-sitter WASM — 112 languages, zero configuration.
Every assistant message (visible text and chain-of-thought/thinking parts) is checked the moment it finishes; syntax errors surface as a compact fence-check report. Clean code stays silent.
Install
pi install npm:fence-check
What it does
- 112 languages — js/ts/py/go/rs/java/c#/haskell/scheme/clojure/racket/erlang/julia/elm/ocaml/dart/ruby/vue + datalog(souffle)/sml/prolog (locally built grammars, see
grammars/README.md) - Real-time — report injects right after the message ends (
message_endhook), not at turn end - CoT included — code blocks inside thinking parts are checked too
- Fault-point location — deepest error node + region span (
L6:20 ERROR (region L1-L6)) - Quiet by design — only reports on errors;
no-checkmarker opts blocks out; audit stops atagent_end /fence-check— re-check the latest assistant message on demand
Usage
Write code blocks as usual — they get checked automatically:
```datalog
dep(a, b). dep(b, c). dep(c, a).
reach(X, Y) :- dep(X, Y).
```
Marking pseudocode / design sketches (anything that is not real source code) skips checking:
```typescript no-check
tool_call(todo) → gate → BLOCK
```
Report format
**fence-check v6: 1 block(s) with syntax errors**
**`js`** (block at message line 4) — 1 issue(s):
- ✗ L3:9 ERROR — `return a + b`
_语法提示,无需回应——后续写代码注意严谨即可。_
The report is a hint, not a task: no need to respond to it — just keep the code rigorous.
Design philosophy
This extension was shaped by a simple observation: an AI that gets told "your code block is wrong" every turn starts explaining, defending, and eventually stops writing code blocks. The fix is not stricter discipline — it is better signal design:
- Syntax-level, not semantic — only guarantees the block parses. No execution, no type checking. Minimal surface, minimal noise.
- Quiet by default — report only on errors; clean code stays silent.
- A hint, not a task — the report carries a built-in "no need to respond" line and the skill forbids responding/explaining/defending it. The AI knows there is an error; the correction lives in the next code it writes, not in a token-consuming rebuttal.
- An escape hatch, not an exemption culture —
no-checkexists for pseudocode/design sketches only. Real code never gets exempted: the report is a fix signal, not a threat. - Real-time but bounded — checks inject right after the message ends (
message_end), and auditing stops atagent_end. No stale reports, no after-the-fact nagging. - Chain-of-thought included — thinking parts are checked too. This is where agents do their symbol reasoning (datalog models, verification sketches); that is exactly the code that benefits most from a parse check.
- Version self-identification — the report header carries a logic version (
v6), so "did my reload take effect" is answered by the report itself. - Empirically driven grammar set — every grammar is probe-verified (load + parse) before inclusion; the runtime (web-tree-sitter 0.26.x) and grammar source (tree-sitter-wasm 1.1.4, uniform ABI 15) were chosen by version-compatibility experiments, not by declaration.
- Local drop-in grammars — languages without any prebuilt wasm (sml, souffle/datalog, prolog) are compiled locally once and placed in
grammars/; the directory is auto-scanned, zero code change.
How it works
tree-sitter-wasm(106 prebuilt grammars, CLI 0.26.x, ABI 15) +web-tree-sitter0.26.x- Local
grammars/directory for grammars with no prebuilt wasm (sml, souffle, prolog) — auto-scanned, drop-in - Tag aliases (
js→javascript,dl→souffle,hs→haskell, …) inlanguages.ts
Development
node test.ts # smoke tests (parser, checking, no-check, thinking extraction)
node probe.ts # verify every grammar loads + parses
Building a local grammar (when tree-sitter build --wasm hangs with emsdk 6.x on Windows, use the manual recipe): see grammars/README.md.
License
MIT