@cortexkit/aft-pi
Pi coding agent extension for Agent File Tools (AFT) — tree-sitter and LSP-powered code analysis
Package details
Install @cortexkit/aft-pi from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:@cortexkit/aft-pi- Package
@cortexkit/aft-pi- Version
0.50.1- Published
- Aug 14, 2026
- Downloads
- not available
- Author
- ismeth
- License
- MIT
- Types
- extension
- Size
- 1.6 MB
- Dependencies
- 5 dependencies · 2 peers
Pi manifest JSON
{
"extensions": [
"./dist/index.js"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
@cortexkit/aft-pi
AFT (Agent File Tools) extension for the Pi coding agent
AFT is a high-performance file-manipulation toolkit for AI coding agents. It replaces Pi's built-in read, write, edit, and grep tools with an indexed Rust backend that adds trigram search, semantic search, fuzzy edits, auto-format, LSP diagnostics, call-graph navigation, and more — all backed by one warm long-running aft process per session.
Install
pi install npm:@cortexkit/aft-pi
That's it. The extension auto-downloads the right AFT binary for your platform on first run (cached at ~/.cache/aft/bin/v<version>/aft).
Prefer to pin a specific version?
pi install npm:@cortexkit/aft-pi@0.13.1
What you get
Hoisted built-in overrides
Pi's default read, write, edit, and grep are replaced with AFT-backed versions.
| Tool | Pi built-in | AFT replacement |
|---|---|---|
read |
Node fs.readFile |
Rust reader with line-numbered output, directory listing, binary/image detection |
write |
Node fs.writeFile |
Atomic write with per-file backup, auto-format (biome/oxfmt/prettier/ruff/rustfmt), LSP diagnostics |
edit |
Plain substring replace | Progressive fuzzy match (handles whitespace/Unicode drift), backups, glob-wide edits |
grep |
ripgrep shell-out | Trigram-indexed search in-project, ripgrep fallback outside project root |
All four keep the same agent-facing parameters as Pi's built-ins, so your prompts, skills, and muscle memory don't change.
AFT-specific tools
| Tool | What it does |
|---|---|
aft_outline |
Structural outline (functions, classes, headings) for files or directories |
aft_zoom |
Symbol-level inspection with call-graph annotations |
aft_search |
Semantic code search (embeddings, local ONNX or OpenAI-compatible) |
aft_callgraph |
Call-graph navigation: callers, call_tree, impact, trace_to, trace_data |
aft_conflicts |
One-call merge-conflict inspection across all conflicted files |
aft_import |
Language-aware import add / remove / organize (TS, JS, Python, Rust, Go) |
aft_safety |
Per-file undo, named checkpoints, restore |
ast_grep_search |
AST-aware pattern search across the filesystem |
ast_grep_replace |
AST-aware pattern rewrite |
lsp_diagnostics |
On-demand LSP diagnostics (edit/write already inline diagnostics automatically) |
aft_delete |
Delete a file with backup (surface: all) |
aft_move |
Move/rename a file (surface: all) |
aft_refactor |
Workspace-wide refactor: move symbol, extract function, inline call (surface: all) |
Slash command
/aft-status— show AFT version, search/semantic index state, LSP servers, storage paths
Configure
AFT reads config from two levels, project overrides user:
- User:
~/.config/cortexkit/aft.jsonc - Project:
<project>/.cortexkit/aft.jsonc
All keys are optional. Example:
{
// "minimal" | "recommended" (default) | "all"
"tool_surface": "recommended",
// Auto-format on write/edit using project formatter config.
"format_on_edit": true,
// "syntax" (tree-sitter parse) | "full" (LSP typecheck)
"validate_on_edit": "syntax",
// When true, write-capable commands reject paths outside project_root.
// Defaults to false to match Pi's built-in behavior.
"restrict_to_project_root": false,
// Enable the trigram-indexed grep/glob (hoists them when true).
"experimental_search_index": true,
// Enable semantic search (aft_search). Requires ONNX runtime for local
// embeddings; downloaded automatically on supported platforms.
"experimental_semantic_search": true,
// Disable specific tool names (applied after tool_surface selection).
"disabled_tools": ["aft_refactor"],
"formatter": {
"typescript": "biome",
"python": "ruff",
"rust": "rustfmt"
},
"checker": {
"typescript": "biome"
},
// Missing formatter/checker/LSP warnings after configure: "toast" (default), "log", or "chat".
"configure_warnings_delivery": "toast",
// Semantic backend (when experimental_semantic_search=true).
// "fastembed" (default, local ONNX) | "openai_compatible" | "ollama"
"semantic": {
"backend": "fastembed",
"model": "all-MiniLM-L6-v2",
"timeout_ms": 25000,
"max_batch_size": 64
}
}
Sensitive semantic backend fields (backend, base_url, api_key_env) are only read from user-level config. Project configs that try to set them are ignored with a warning to prevent credential-exfiltration via malicious repos.
Tool surface tiers
| Tier | Tools |
|---|---|
minimal |
aft_outline, aft_zoom, aft_safety |
recommended (default) |
minimal + hoisted read/write/edit + aft_import + ast_grep_* + lsp_diagnostics + aft_conflicts + (optional) grep + (optional) aft_search |
all |
recommended + aft_callgraph + aft_delete + aft_move + aft_refactor |
Architecture
- One persistent Rust process per session. Pi loads the extension once per session; AFT spawns one
aftbinary for the session's working directory and keeps it alive. Trigram index, semantic index, tree-sitter caches, and LSP servers all stay warm. - NDJSON bridge. The TypeScript extension talks to the Rust binary over stdin/stdout using a versioned JSON-RPC-style protocol.
- Session isolation. Pi's
session_shutdownevent triggers clean bridge shutdown — undo history, checkpoints, and LSP state don't leak across sessions. - Auto-download + version check. Each plugin version pins a compatible binary version and resolves it in order: versioned cache → platform npm package →
PATH→~/.cargo/bin/aft→ GitHub release download. Mismatched binaries hot-swap transparently.
Logs
Plugin logs go to <storage_root>/logs/aft-plugin.log with an [aft-pi] tag. The file rotates at 20 MB through five retained generations; Rust module processes use adjacent aft-<pid>.log files.
Set AFT_LOG_STDERR=1 to route logs to stderr instead (useful for piping or subprocess tests).
License
MIT
Main project: https://github.com/cortexkit/aft Issues / feature requests: https://github.com/cortexkit/aft/issues