53 KiB
ipuaro Roadmap
Local AI agent for codebase operations with "infinite" context feeling through lazy loading.
Project Structure (Clean Architecture)
packages/ipuaro/
├── bin/
│ └── ipuaro.js # CLI entry point
├── src/
│ ├── domain/ # Business logic (no dependencies)
│ │ ├── entities/
│ │ │ ├── Session.ts
│ │ │ └── Project.ts
│ │ ├── value-objects/
│ │ │ ├── FileData.ts
│ │ │ ├── FileAST.ts
│ │ │ ├── FileMeta.ts
│ │ │ ├── ChatMessage.ts
│ │ │ ├── ToolCall.ts
│ │ │ ├── ToolResult.ts
│ │ │ └── UndoEntry.ts
│ │ ├── services/ # Interfaces (ports)
│ │ │ ├── IStorage.ts
│ │ │ ├── ILLMClient.ts
│ │ │ ├── ITool.ts
│ │ │ └── IIndexer.ts
│ │ └── constants/
│ │ └── index.ts
│ ├── application/ # Use cases & orchestration
│ │ ├── use-cases/
│ │ │ ├── StartSession.ts
│ │ │ ├── HandleMessage.ts
│ │ │ ├── IndexProject.ts
│ │ │ ├── ExecuteTool.ts
│ │ │ └── UndoChange.ts
│ │ ├── dtos/
│ │ │ ├── SessionDto.ts
│ │ │ ├── MessageDto.ts
│ │ │ └── ToolCallDto.ts
│ │ ├── mappers/
│ │ │ └── SessionMapper.ts
│ │ └── interfaces/
│ │ └── IToolRegistry.ts
│ ├── infrastructure/ # External implementations
│ │ ├── storage/
│ │ │ ├── RedisClient.ts
│ │ │ ├── RedisStorage.ts
│ │ │ └── schema.ts
│ │ ├── llm/
│ │ │ ├── OllamaClient.ts
│ │ │ ├── prompts.ts
│ │ │ └── ResponseParser.ts
│ │ ├── indexer/
│ │ │ ├── FileScanner.ts
│ │ │ ├── ASTParser.ts
│ │ │ ├── MetaAnalyzer.ts
│ │ │ ├── IndexBuilder.ts
│ │ │ └── Watchdog.ts
│ │ ├── tools/
│ │ │ ├── registry.ts
│ │ │ ├── read/
│ │ │ │ ├── GetLinesTool.ts
│ │ │ │ ├── GetFunctionTool.ts
│ │ │ │ ├── GetClassTool.ts
│ │ │ │ └── GetStructureTool.ts
│ │ │ ├── edit/
│ │ │ │ ├── EditLinesTool.ts
│ │ │ │ ├── CreateFileTool.ts
│ │ │ │ └── DeleteFileTool.ts
│ │ │ ├── search/
│ │ │ │ ├── FindReferencesTool.ts
│ │ │ │ └── FindDefinitionTool.ts
│ │ │ ├── analysis/
│ │ │ │ ├── GetDependenciesTool.ts
│ │ │ │ ├── GetDependentsTool.ts
│ │ │ │ ├── GetComplexityTool.ts
│ │ │ │ └── GetTodosTool.ts
│ │ │ ├── git/
│ │ │ │ ├── GitStatusTool.ts
│ │ │ │ ├── GitDiffTool.ts
│ │ │ │ └── GitCommitTool.ts
│ │ │ └── run/
│ │ │ ├── RunCommandTool.ts
│ │ │ └── RunTestsTool.ts
│ │ ├── security/
│ │ │ ├── Blacklist.ts
│ │ │ ├── Whitelist.ts
│ │ │ └── PathValidator.ts
│ │ └── constants/
│ │ ├── blacklist.ts
│ │ └── whitelist.ts
│ ├── shared/ # Cross-cutting concerns
│ │ ├── types/
│ │ │ └── index.ts
│ │ ├── constants/
│ │ │ ├── config.ts
│ │ │ └── messages.ts
│ │ ├── utils/
│ │ │ ├── hash.ts
│ │ │ └── tokens.ts
│ │ └── errors/
│ │ └── IpuaroError.ts
│ ├── tui/ # Terminal UI (Ink/React)
│ │ ├── App.tsx
│ │ ├── components/
│ │ │ ├── StatusBar.tsx
│ │ │ ├── Chat.tsx
│ │ │ ├── Input.tsx
│ │ │ ├── DiffView.tsx
│ │ │ ├── ConfirmDialog.tsx
│ │ │ ├── ErrorDialog.tsx
│ │ │ └── Progress.tsx
│ │ └── hooks/
│ │ ├── useSession.ts
│ │ ├── useHotkeys.ts
│ │ └── useAutocomplete.ts
│ └── cli/ # CLI commands
│ ├── index.ts
│ └── commands/
│ ├── start.ts
│ ├── init.ts
│ └── index-cmd.ts
├── tests/
│ ├── unit/
│ │ ├── domain/
│ │ ├── application/
│ │ └── infrastructure/
│ ├── e2e/
│ │ ├── cli.test.ts
│ │ └── full-flow.test.ts
│ └── fixtures/
│ └── sample-project/
├── examples/
│ └── demo-project/
├── config/
│ ├── default.json
│ ├── blacklist.json
│ └── whitelist.json
├── CHANGELOG.md
├── TODO.md
├── README.md
├── package.json
├── tsconfig.json
└── vitest.config.ts
Version 0.1.0 - Foundation ⚙️ ✅
Priority: CRITICAL Status: Complete (v0.1.0 released)
0.1.1 - Project Setup
Dependencies:
{
"dependencies": {
"ink": "^4.0.0",
"ink-text-input": "^5.0.0",
"react": "^18.0.0",
"ioredis": "^5.0.0",
"tree-sitter": "^0.20.0",
"tree-sitter-typescript": "^0.20.0",
"tree-sitter-javascript": "^0.20.0",
"ollama": "^0.5.0",
"simple-git": "^3.0.0",
"chokidar": "^3.0.0",
"commander": "^11.0.0",
"zod": "^3.0.0",
"ignore": "^5.0.0"
},
"devDependencies": {
"vitest": "^1.0.0",
"@vitest/coverage-v8": "^1.0.0",
"tsup": "^8.0.0",
"typescript": "^5.0.0"
}
}
Deliverables:
- package.json with all dependencies
- tsconfig.json (strict, jsx react, nodenext)
- tsup.config.ts (bundle ESM + CJS)
- vitest.config.ts (coverage 80%)
- bin/ipuaro.js entry point
0.1.2 - Domain Value Objects
// src/domain/value-objects/FileData.ts
interface FileData {
lines: string[]
hash: string // MD5
size: number
lastModified: number
}
// src/domain/value-objects/FileAST.ts
interface FileAST {
imports: ImportInfo[]
exports: ExportInfo[]
functions: FunctionInfo[]
classes: ClassInfo[]
parseError: boolean
}
interface ImportInfo {
name: string
from: string
line: number
type: "internal" | "external" | "builtin"
isDefault: boolean
}
interface FunctionInfo {
name: string
lineStart: number
lineEnd: number
params: string[]
isAsync: boolean
isExported: boolean
}
interface ClassInfo {
name: string
lineStart: number
lineEnd: number
methods: MethodInfo[]
extends?: string
isExported: boolean
}
// src/domain/value-objects/ChatMessage.ts
interface ChatMessage {
role: "user" | "assistant" | "tool"
content: string
timestamp: number
toolCalls?: ToolCall[]
toolResults?: ToolResult[]
stats?: { tokens: number; timeMs: number; toolCalls: number }
}
// src/domain/value-objects/UndoEntry.ts
interface UndoEntry {
id: string
timestamp: number
filePath: string
previousContent: string[]
newContent: string[]
description: string
}
0.1.3 - Domain Services (Interfaces)
// src/domain/services/IStorage.ts
interface IStorage {
getFile(path: string): Promise<FileData | null>
setFile(path: string, data: FileData): Promise<void>
deleteFile(path: string): Promise<void>
getAllFiles(): Promise<Map<string, FileData>>
getAST(path: string): Promise<FileAST | null>
setAST(path: string, ast: FileAST): Promise<void>
getSymbolIndex(): Promise<SymbolIndex>
setSymbolIndex(index: SymbolIndex): Promise<void>
}
// src/domain/services/ILLMClient.ts
interface ILLMClient {
chat(messages: ChatMessage[], tools?: ToolDef[]): Promise<LLMResponse>
countTokens(text: string): Promise<number>
isAvailable(): Promise<boolean>
}
// src/domain/services/ITool.ts
interface ITool {
name: string
description: string
parameters: ToolParameter[]
requiresConfirmation: boolean
execute(params: Record<string, unknown>, ctx: ToolContext): Promise<ToolResult>
}
0.1.4 - Shared Config
// src/shared/constants/config.ts
interface Config {
redis: { host: string; port: number; db: number }
llm: { model: string; contextWindow: number; temperature: number }
project: { ignorePatterns: string[]; binaryExtensions: string[] }
watchdog: { debounceMs: number }
undo: { stackSize: number }
edit: { autoApply: boolean }
}
// loadConfig(): reads config/default.json + .ipuaro.json
// validates with zod schema
Tests:
- Unit tests for value objects
- Unit tests for config loader
Version 0.2.0 - Redis Storage 🗄️ ✅
Priority: CRITICAL Status: Complete (v0.2.0 released)
0.2.1 - Redis Client
// src/infrastructure/storage/RedisClient.ts
class RedisClient {
connect(): Promise<void> // AOF config on connect
disconnect(): Promise<void>
isConnected(): boolean
getClient(): Redis
}
// Redis config for AOF persistence
// appendonly yes
// appendfsync everysec
0.2.2 - Redis Schema
project:{name}:files # Hash<path, FileData>
project:{name}:ast # Hash<path, FileAST>
project:{name}:meta # Hash<path, FileMeta>
project:{name}:indexes # Hash<symbols|deps_graph, JSON>
project:{name}:config # Hash<settings|last_indexed, JSON>
session:{id}:data # Hash<history|context|stats>
session:{id}:undo # List<UndoEntry> (max 10)
sessions:list # List<session_id>
Project name format: {parent-folder}-{project-folder}
0.2.3 - Redis Storage Implementation
// src/infrastructure/storage/RedisStorage.ts
class RedisStorage implements IStorage {
constructor(private client: RedisClient, private projectName: string)
async getFile(path: string): Promise<FileData | null>
async setFile(path: string, data: FileData): Promise<void>
async deleteFile(path: string): Promise<void>
async getAllFiles(): Promise<Map<string, FileData>>
// ... all IStorage methods
}
Tests:
- Unit tests for RedisStorage (mock Redis)
- Integration tests with real Redis
Version 0.3.0 - Indexer 📂 ✅
Priority: CRITICAL Status: Complete (v0.3.0, v0.3.1 released)
0.3.1 - File Scanner
// src/infrastructure/indexer/FileScanner.ts
class FileScanner {
scan(root: string): AsyncGenerator<ScanResult>
}
interface ScanResult {
path: string
type: "file" | "dir" | "symlink"
stats: Stats
}
// Filters: .gitignore (via ignore lib), node_modules, dist
// Supports: .ts, .tsx, .js, .jsx, .json, .yaml
// Only UTF-8 files (skip binary)
// Progress callback: onProgress(current, total, file)
0.3.2 - AST Parser
// src/infrastructure/indexer/ASTParser.ts
class ASTParser {
parse(content: string, lang: "ts" | "tsx" | "js" | "jsx"): FileAST
}
// Uses tree-sitter
// Extracts: imports, exports, functions, classes
// On error: parseError: true, continue with partial data
0.3.3 - Meta Analyzer
// src/infrastructure/indexer/MetaAnalyzer.ts
class MetaAnalyzer {
analyze(path: string, ast: FileAST, allASTs: Map<string, FileAST>): FileMeta
}
interface FileMeta {
complexity: { loc: number; nesting: number; score: number }
dependencies: string[] // files this imports
dependents: string[] // files importing this
isHub: boolean // >5 dependents
isEntryPoint: boolean // index.ts or 0 dependents
}
0.3.4 - Index Builder
// src/infrastructure/indexer/IndexBuilder.ts
class IndexBuilder {
buildSymbolIndex(asts: Map<string, FileAST>): SymbolIndex
buildDepsGraph(asts: Map<string, FileAST>): DepsGraph
}
// SymbolIndex: { [name]: { path, line, type } }
// DepsGraph: { [path]: { imports: [], importedBy: [] } }
0.3.5 - Watchdog
// src/infrastructure/indexer/Watchdog.ts
class Watchdog {
start(root: string, storage: IStorage): void
stop(): void
onFileChange(callback: (path: string) => void): void
}
// chokidar with 500ms debounce
// On change: recalc hash → update lines/AST/meta if changed
// Silent updates (no UI notification)
Tests:
- Unit tests for ASTParser (fixtures)
- Unit tests for MetaAnalyzer
- Integration tests for full indexing
Version 0.4.0 - LLM Integration 🤖 ✅
Priority: CRITICAL Status: Complete (v0.4.0 released)
0.4.1 - Ollama Client
// src/infrastructure/llm/OllamaClient.ts
class OllamaClient implements ILLMClient {
constructor(config: { model: string; contextWindow: number; temperature: number })
async chat(messages: ChatMessage[], tools?: ToolDef[]): Promise<LLMResponse>
async countTokens(text: string): Promise<number>
async isAvailable(): Promise<boolean>
async pullModel(model: string): Promise<void>
}
interface LLMResponse {
content: string
toolCalls?: ToolCall[]
tokens: number
timeMs: number
}
0.4.2 - System Prompt
// src/infrastructure/llm/prompts.ts
const SYSTEM_PROMPT: string // EN, role + rules + tools
function buildInitialContext(
structure: ProjectStructure,
asts: Map<string, FileAST>
): string
// Returns: project structure + AST metadata (NO code)
// Code loaded lazily via tools
0.4.3 - Tool Definitions
// src/infrastructure/llm/toolDefs.ts
const TOOL_DEFINITIONS: ToolDef[] // 18 tools
interface ToolDef {
name: string
description: string
parameters: {
type: "object"
properties: Record<string, { type: string; description: string }>
required: string[]
}
}
// XML format in prompt: <tool_call name="..."><param>...</param></tool_call>
0.4.4 - Response Parser
// src/infrastructure/llm/ResponseParser.ts
function parseToolCalls(response: string): ToolCall[]
// Parses XML tool calls from model response
// Handles multiple tool calls in one response
Tests:
- Unit tests for ResponseParser
- Mock tests for OllamaClient
Version 0.5.0 - Read Tools 📖 ✅
Priority: HIGH Status: Complete (v0.5.0 released)
4 tools for reading code without modification.
0.5.1 - Tool Registry
// src/infrastructure/tools/registry.ts
class ToolRegistry implements IToolRegistry {
register(tool: ITool): void
get(name: string): ITool | undefined
getAll(): ITool[]
execute(name: string, params: Record<string, unknown>, ctx: ToolContext): Promise<ToolResult>
}
0.5.2 - get_lines
// src/infrastructure/tools/read/GetLinesTool.ts
class GetLinesTool implements ITool {
name = "get_lines"
requiresConfirmation = false
// get_lines(path, start?, end?)
// Returns lines from Redis (or file if not indexed)
// Default: entire file
}
0.5.3 - get_function
// src/infrastructure/tools/read/GetFunctionTool.ts
class GetFunctionTool implements ITool {
name = "get_function"
requiresConfirmation = false
// get_function(path, name)
// Uses AST lineStart/lineEnd to return function code
}
0.5.4 - get_class
// src/infrastructure/tools/read/GetClassTool.ts
class GetClassTool implements ITool {
name = "get_class"
requiresConfirmation = false
// get_class(path, name)
// Uses AST lineStart/lineEnd to return class code
}
0.5.5 - get_structure
// src/infrastructure/tools/read/GetStructureTool.ts
class GetStructureTool implements ITool {
name = "get_structure"
requiresConfirmation = false
// get_structure(path?)
// Returns folder/file tree
// Default: entire project
}
Tests:
- Unit tests for each read tool
- Integration tests with real storage
Version 0.6.0 - Edit Tools ✏️ ✅
Priority: HIGH Status: Complete (v0.6.0 released)
3 tools for file modifications. All require confirmation (unless autoApply).
0.6.1 - edit_lines
// src/infrastructure/tools/edit/EditLinesTool.ts
class EditLinesTool implements ITool {
name = "edit_lines"
requiresConfirmation = true
// edit_lines(path, start, end, content)
// Replaces lines start-end with content
// Checks hash conflict before apply
}
0.6.2 - create_file
// src/infrastructure/tools/edit/CreateFileTool.ts
class CreateFileTool implements ITool {
name = "create_file"
requiresConfirmation = true
// create_file(path, content)
// Creates new file
// Validates path inside project
}
0.6.3 - delete_file
// src/infrastructure/tools/edit/DeleteFileTool.ts
class DeleteFileTool implements ITool {
name = "delete_file"
requiresConfirmation = true
// delete_file(path)
// Deletes file from filesystem and Redis
}
Tests:
- Unit tests for each edit tool
- Integration tests with filesystem
Version 0.7.0 - Search Tools 🔍 ✅
Priority: HIGH Status: Complete (v0.7.0 released)
0.7.1 - find_references
// src/infrastructure/tools/search/FindReferencesTool.ts
class FindReferencesTool implements ITool {
name = "find_references"
requiresConfirmation = false
// find_references(symbol)
// Searches SymbolIndex for all usages
// Returns: [{ path, line, context }]
}
0.7.2 - find_definition
// src/infrastructure/tools/search/FindDefinitionTool.ts
class FindDefinitionTool implements ITool {
name = "find_definition"
requiresConfirmation = false
// find_definition(symbol)
// Finds where symbol is defined
// Returns: { path, line, type }
}
Tests:
- Unit tests for search tools
Version 0.8.0 - Analysis Tools 📊 ✅
Priority: MEDIUM Status: Complete (v0.8.0 released)
0.8.1 - get_dependencies
// src/infrastructure/tools/analysis/GetDependenciesTool.ts
// get_dependencies(path)
// Returns files this file imports (from FileMeta)
0.8.2 - get_dependents
// src/infrastructure/tools/analysis/GetDependentsTool.ts
// get_dependents(path)
// Returns files that import this file
0.8.3 - get_complexity
// src/infrastructure/tools/analysis/GetComplexityTool.ts
// get_complexity(path?)
// Returns complexity metrics
// Default: all files sorted by score
0.8.4 - get_todos
// src/infrastructure/tools/analysis/GetTodosTool.ts
// get_todos(path?)
// Finds TODO/FIXME comments in code
// Returns: [{ path, line, text }]
Tests:
- Unit tests for analysis tools
Version 0.9.0 - Git & Run Tools 🚀 ✅
Priority: MEDIUM Status: Complete (v0.9.0 released) — includes CommandSecurity (Blacklist/Whitelist)
0.9.1 - git_status
// src/infrastructure/tools/git/GitStatusTool.ts
// git_status()
// Returns: { branch, staged, modified, untracked }
0.9.2 - git_diff
// src/infrastructure/tools/git/GitDiffTool.ts
// git_diff(path?)
// Returns uncommitted changes
// Default: all changes
0.9.3 - git_commit
// src/infrastructure/tools/git/GitCommitTool.ts
// git_commit(message, files?)
// Creates commit
// requiresConfirmation: true
0.9.4 - run_command
// src/infrastructure/tools/run/RunCommandTool.ts
// run_command(command)
// Executes shell command with security checks:
// 1. Check blacklist → reject
// 2. Check whitelist → allow
// 3. Unknown → ask user confirmation
0.9.5 - run_tests
// src/infrastructure/tools/run/RunTestsTool.ts
// run_tests(path?, filter?)
// Detects test runner (vitest/jest/npm test)
// Runs tests and returns results
Tests:
- Unit tests for git tools
- Unit tests for run tools
Version 0.10.0 - Session Management 💾 ✅
Priority: HIGH Status: Complete (v0.10.0 released) — includes HandleMessage orchestrator (originally planned for 0.14.0)
0.10.1 - Session Entity
// src/domain/entities/Session.ts
class Session {
id: string
projectName: string
createdAt: number
lastActivityAt: number
history: ChatMessage[]
context: ContextState
undoStack: UndoEntry[]
stats: SessionStats
inputHistory: string[]
}
interface SessionStats {
totalTokens: number
totalTime: number
toolCalls: number
editsApplied: number
editsRejected: number
}
0.10.2 - Session Use Cases
// src/application/use-cases/StartSession.ts
class StartSession {
execute(projectName: string): Promise<Session>
// Creates new or loads latest session
}
// src/application/use-cases/HandleMessage.ts
class HandleMessage {
execute(session: Session, message: string): Promise<void>
// Main message flow
}
0.10.3 - Undo Use Case
// src/application/use-cases/UndoChange.ts
class UndoChange {
execute(session: Session): Promise<UndoResult>
// Reverts last file change from undo stack
}
0.10.4 - Context Manager
// src/application/use-cases/pipeline/ContextManager.ts
class ContextManager {
addToContext(file: string, tokens: number): void
getUsage(): number // 0-1
needsCompression(): boolean // >80%
compress(llm: ILLMClient): Promise<void>
}
// Compression: LLM summarizes old messages + removes tool results
Tests:
- Unit tests for session use cases
- Integration tests for full session flow
Version 0.11.0 - TUI Basic 🖥️ ✅
Priority: CRITICAL Status: Complete (v0.11.0 released) — includes useHotkeys (originally planned for 0.16.0)
0.11.1 - App Shell
// src/tui/App.tsx
function App({ projectPath }: { projectPath: string }) {
const [session, setSession] = useState<Session | null>(null)
const [status, setStatus] = useState<"ready" | "thinking" | "error">("ready")
const [messages, setMessages] = useState<ChatMessage[]>([])
return (
<Box flexDirection="column" height="100%">
<StatusBar ... />
<Chat messages={messages} isThinking={status === "thinking"} />
<Input onSubmit={handleSubmit} disabled={status === "thinking"} />
</Box>
)
}
0.11.2 - StatusBar
// src/tui/components/StatusBar.tsx
// [ipuaro] [ctx: 12%] [project: myapp] [main] [47m] ✓
interface Props {
contextUsage: number
projectName: string
branch: string
sessionTime: number
status: "ready" | "thinking" | "error"
}
0.11.3 - Chat
// src/tui/components/Chat.tsx
// Displays message history
// Tool calls as: [tool_name params...]
// Stats after response: ⏱ 3.2s │ 1,247 tokens │ 1 tool call
interface Props {
messages: ChatMessage[]
isThinking: boolean
}
0.11.4 - Input
// src/tui/components/Input.tsx
// Prompt: > _
// ↑/↓ for history
// Tab for path autocomplete
interface Props {
onSubmit: (text: string) => void
history: string[]
disabled: boolean
}
Tests:
- Component tests for TUI
Version 0.12.0 - TUI Advanced 🎨 ✅
Priority: HIGH Status: Complete (v0.12.0 released)
0.12.1 - DiffView
// src/tui/components/DiffView.tsx
// Inline highlights: green added, red removed
// Header: ┌─── path (lines X-Y) ───┐
interface Props {
filePath: string
oldLines: string[]
newLines: string[]
startLine: number
}
0.12.2 - ConfirmDialog
// src/tui/components/ConfirmDialog.tsx
// [Y] Apply [N] Cancel [E] Edit
interface Props {
message: string
diff?: DiffProps
onSelect: (choice: "apply" | "cancel" | "edit") => void
}
0.12.3 - ErrorDialog
// src/tui/components/ErrorDialog.tsx
// ❌ type: message
// [R] Retry [S] Skip [A] Abort
interface Props {
error: { type: string; message: string; recoverable: boolean }
onChoice: (choice: "retry" | "skip" | "abort") => void
}
0.12.4 - Progress
// src/tui/components/Progress.tsx
// [=====> ] 45% (120/267 files)
// Used during indexing
interface Props {
current: number
total: number
label: string
}
Tests:
- Component tests for dialogs
Version 0.13.0 - Security 🔒 ✅
Priority: HIGH Status: Complete (v0.13.0 released) — Blacklist/Whitelist done in v0.9.0, PathValidator in v0.13.0
0.13.1 - Blacklist
// src/infrastructure/security/Blacklist.ts
const BLACKLIST = [
"rm -rf", "rm -r",
"git push --force", "git reset --hard", "git clean -fd",
"npm publish", "sudo", "chmod", "chown"
]
function isBlacklisted(command: string): boolean
// Substring match - always reject
0.13.2 - Whitelist
// src/infrastructure/security/Whitelist.ts
const DEFAULT_WHITELIST = [
"npm", "pnpm", "yarn", "git",
"node", "npx", "tsx",
"vitest", "jest", "tsc", "eslint", "prettier"
]
function isWhitelisted(command: string): boolean
// First word match
// User can extend via config.whitelist.user
0.13.3 - Path Validator
// src/infrastructure/security/PathValidator.ts
function validatePath(path: string, projectRoot: string): boolean
// Rejects: .., absolute paths outside project
Tests:
- Unit tests for security validators
[DONE] Original 0.14.0 - Orchestrator 🎭 ✅
Note: This was implemented in v0.10.0 as part of Session Management
Originally planned (click to expand)
HandleMessage Use Case (Done in v0.10.5)
// src/application/use-cases/HandleMessage.ts
class HandleMessage {
constructor(
private storage: IStorage,
private llm: ILLMClient,
private tools: IToolRegistry
)
async execute(session: Session, message: string): Promise<void> {
// 1. Add user message to history
// 2. Build context: system prompt + structure + AST + history
// 3. Send to LLM
// 4. Parse tool calls
// 5. For each tool:
// - if requiresConfirmation → emit onEdit
// - else → execute
// 6. If tool results → repeat from step 3
// 7. Show final response with stats
}
// Events
onMessage: (msg: ChatMessage) => void
onToolCall: (call: ToolCall) => void
onEdit: (edit: EditRequest) => Promise<EditChoice>
onError: (error: IpuaroError) => Promise<ErrorChoice>
onStatusChange: (status: Status) => void
}
Edit Flow (Done in v0.10.5)
// Edit handling inside HandleMessage:
// 1. Check hash conflict (file changed during generation?)
// 2. If conflict → onEdit with choices: apply/skip/regenerate
// 3. If not autoApply → onEdit with diff
// 4. On "apply":
// - Save to undo stack
// - Apply changes to file
// - Update storage (lines, AST, meta)
[DONE] Original 0.16.0 - Hotkeys & Polish ⌨️ ✅
Note: useHotkeys done in v0.11.0, ContextManager auto-compression in v0.10.3
Originally planned (click to expand)
Hotkeys (Done in v0.11.0)
// src/tui/hooks/useHotkeys.ts
Ctrl+C // Interrupt generation (1st), exit (2nd)
Ctrl+D // Exit with session save
Ctrl+Z // Undo (= /undo)
↑/↓ // Input history
Tab // Path autocomplete
Auto-compression (Done in v0.10.3)
// Triggered at >80% context:
// 1. LLM summarizes old messages
// 2. Remove tool results older than 5 messages
// 3. Update status bar (ctx% changes)
// No modal notification - silent
Version 0.14.0 - Commands 📝 ✅
Priority: HIGH Status: Complete (v0.14.0 released)
8 slash commands for TUI.
// src/tui/hooks/useCommands.ts
/help // Shows all commands and hotkeys
/clear // Clears chat history (keeps session)
/undo // Reverts last file change from undo stack
/sessions // list | load <id> | delete <id>
/status // Shows: Redis, context, model, session stats
/reindex // Forces full project reindexation
/eval // LLM self-check for hallucinations
/auto-apply // on | off - toggle auto-apply mode
Tests:
- Unit tests for command handlers (38 tests)
Version 0.15.0 - CLI Entry Point 🚪 ✅
Priority: HIGH Status: Complete (v0.15.0 released)
0.15.1 - CLI Commands
// src/cli/index.ts
ipuaro [path] // Start TUI in directory (default: cwd)
ipuaro init // Create .ipuaro.json config
ipuaro index // Index only (no TUI)
0.15.2 - CLI Options
--auto-apply # Enable auto-apply mode
--model <name> # Override model (default: qwen2.5-coder:7b-instruct)
--help # Show help
--version # Show version
0.15.3 - Onboarding
// src/cli/commands/start.ts
// On first run:
// 1. Check Redis → error with install instructions if missing
// 2. Check Ollama → error if unavailable
// 3. Check model → offer to pull if missing
// 4. Check project size → warn if >10K files, offer subdirectory
Tests:
- Unit tests for CLI commands (29 tests)
Version 0.16.0 - Error Handling ⚠️ ✅
Priority: HIGH Status: Complete (v0.16.0 released)
0.16.1 - Error Types ✅
// src/shared/errors/IpuaroError.ts
type ErrorType = "redis" | "parse" | "llm" | "file" | "command" | "conflict" | "validation" | "timeout" | "unknown"
type ErrorOption = "retry" | "skip" | "abort" | "confirm" | "regenerate"
interface ErrorMeta {
type: ErrorType
recoverable: boolean
options: ErrorOption[]
defaultOption: ErrorOption
}
class IpuaroError extends Error {
type: ErrorType
recoverable: boolean
suggestion?: string
options: ErrorOption[]
defaultOption: ErrorOption
context?: Record<string, unknown>
getMeta(): ErrorMeta
hasOption(option: ErrorOption): boolean
toDisplayString(): string
}
0.16.2 - Error Handling Matrix ✅
| Error | Recoverable | Options | Default |
|---|---|---|---|
| Redis unavailable | No | Retry / Abort | Abort |
| AST parse failed | Yes | Skip / Abort | Skip |
| LLM timeout | Yes | Retry / Skip / Abort | Retry |
| File not found | Yes | Skip / Abort | Skip |
| Command not in whitelist | Yes | Confirm / Skip / Abort | Confirm |
| Edit conflict | Yes | Skip / Regenerate / Abort | Skip |
| Validation error | Yes | Skip / Abort | Skip |
| Timeout | Yes | Retry / Skip / Abort | Retry |
| Unknown | No | Abort | Abort |
0.16.3 - ErrorHandler Service ✅
// src/shared/errors/ErrorHandler.ts
class ErrorHandler {
handle(error: IpuaroError, contextKey?: string): Promise<ErrorHandlingResult>
handleSync(error: IpuaroError, contextKey?: string): ErrorHandlingResult
wrap<T>(fn: () => Promise<T>, errorType: ErrorType, contextKey?: string): Promise<Result>
withRetry<T>(fn: () => Promise<T>, errorType: ErrorType, contextKey: string): Promise<T>
resetRetries(contextKey?: string): void
getRetryCount(contextKey: string): number
isMaxRetriesExceeded(contextKey: string): boolean
}
Tests:
- Unit tests for IpuaroError (27 tests)
- Unit tests for ErrorHandler (32 tests)
Version 0.17.0 - Documentation Complete 📚 ✅
Priority: HIGH Status: Complete (v0.17.0 released)
Documentation
- README.md comprehensive update with all features
- ARCHITECTURE.md explaining design and decisions
- TOOLS.md complete reference for all 18 tools
- Troubleshooting guide
- FAQ section
- API examples
- ~2500 lines of documentation added
Version 0.18.0 - Working Examples 📦 ✅
Priority: HIGH Status: Complete (v0.18.0 released)
Examples
- Demo project with TypeScript application (336 LOC)
- User management service (UserService)
- Authentication service (AuthService)
- Utilities (Logger, Validation)
- Unit tests (Vitest)
- Configuration files (package.json, tsconfig.json, .ipuaro.json)
- Comprehensive README with 35+ example queries
- Workflow scenarios (bug fix, refactoring, code review)
- Demonstrates all 18 tools
- 15 files, 977 total lines
Version 0.19.0 - XML Tool Format Refactor 🔄 ✅
Priority: HIGH Status: Complete (v0.19.0 released)
Refactoring: transition to pure XML format for tool calls (as in CONCEPT.md).
Current Problem
OllamaClient uses Ollama native tool calling (JSON Schema), while ResponseParser implements XML parsing. This creates confusion and doesn't match CONCEPT.md.
0.19.1 - OllamaClient Refactor
// src/infrastructure/llm/OllamaClient.ts
// BEFORE:
// - Pass tools in Ollama SDK format
// - Extract tool_calls from response.message.tool_calls
// AFTER:
// - DON'T pass tools to SDK
// - Tools described in system prompt as XML
// - LLM returns XML in content
// - Parse via ResponseParser
Changes:
- Remove
convertTools()method - Remove
extractToolCalls()method - Remove
toolsfromclient.chat()call - Return only
contentwithouttoolCalls
0.19.2 - System Prompt Update
// src/infrastructure/llm/prompts.ts
// Add full XML format description to SYSTEM_PROMPT:
const TOOL_FORMAT_INSTRUCTIONS = `
## Tool Calling Format
When you need to use a tool, format your call as XML:
<tool_call name="tool_name">
<param_name>value</param_name>
<another_param>value</another_param>
</tool_call>
Examples:
<tool_call name="get_lines">
<path>src/index.ts</path>
<start>1</start>
<end>50</end>
</tool_call>
<tool_call name="edit_lines">
<path>src/utils.ts</path>
<start>10</start>
<end>15</end>
<content>const newCode = "hello";</content>
</tool_call>
You can use multiple tool calls in one response.
Always wait for tool results before making conclusions.
`
Changes:
- Add
TOOL_FORMAT_INSTRUCTIONSto prompts.ts - Include in
SYSTEM_PROMPT - Add examples for all 18 tools
0.19.3 - HandleMessage Simplification
// src/application/use-cases/HandleMessage.ts
// BEFORE:
// const response = await this.llm.chat(messages)
// const parsed = parseToolCalls(response.content)
// AFTER:
// const response = await this.llm.chat(messages) // without tools
// const parsed = parseToolCalls(response.content) // single source
Changes:
- Remove tool definitions from
llm.chat() - ResponseParser — single source of tool calls
- Simplify processing logic
0.19.4 - ILLMClient Interface Update
// src/domain/services/ILLMClient.ts
// BEFORE:
interface ILLMClient {
chat(messages: ChatMessage[], tools?: ToolDef[]): Promise<LLMResponse>
}
// AFTER:
interface ILLMClient {
chat(messages: ChatMessage[]): Promise<LLMResponse>
// tools no longer passed - they're in system prompt
}
Changes:
- Remove
toolsparameter fromchat() - Remove
toolCallsfromLLMResponse(parsed from content) - Update all implementations
0.19.5 - ResponseParser Enhancements
// src/infrastructure/llm/ResponseParser.ts
// Improvements:
// - Better error handling for parsing
// - CDATA support for multiline content
// - Tool name validation
Changes:
- Add
<![CDATA[...]]>support for content - Validation: tool name must be from known list
- Improve parsing error messages
Tests:
- Update OllamaClient tests
- Update HandleMessage tests
- Add ResponseParser tests for edge cases
- E2E test for full XML flow (optional, may be in 0.20.0)
Version 0.20.0 - Missing Use Cases 🔧 ✅
Priority: HIGH Status: Complete (v0.20.0 released)
0.20.1 - IndexProject Use Case ✅
// src/application/use-cases/IndexProject.ts
class IndexProject {
constructor(storage: IStorage, projectRoot: string)
async execute(
projectRoot: string,
options?: IndexProjectOptions
): Promise<IndexingStats>
// Full indexing pipeline:
// 1. Scan files
// 2. Parse AST
// 3. Analyze metadata
// 4. Build indexes
// 5. Store in Redis
}
Deliverables:
- IndexProject use case implementation (184 LOC)
- Progress reporting via callback
- Unit tests (318 LOC)
0.20.2 - ExecuteTool Use Case ✅
// src/application/use-cases/ExecuteTool.ts
class ExecuteTool {
constructor(
storage: IStorage,
sessionStorage: ISessionStorage,
tools: IToolRegistry,
projectRoot: string
)
async execute(
toolCall: ToolCall,
session: Session,
options?: ExecuteToolOptions
): Promise<ExecuteToolResult>
// Orchestrates tool execution with:
// - Parameter validation
// - Confirmation flow (with edit support)
// - Undo stack management
// - Storage updates
}
Deliverables:
- ExecuteTool use case implementation (225 LOC)
- HandleMessage uses ExecuteTool
- Support for edited content from confirmation dialog
- Dedicated unit tests (covered indirectly via integration)
Tests:
- Unit tests for IndexProject
- Unit tests for ExecuteTool (optional - covered via integration)
Version 0.21.0 - TUI Enhancements 🎨 ✅
Priority: MEDIUM Status: Complete (v0.21.0 released)
0.21.1 - useAutocomplete Hook ✅
// src/tui/hooks/useAutocomplete.ts
function useAutocomplete(options: {
storage: IStorage
projectRoot: string
enabled?: boolean
maxSuggestions?: number
}): {
suggestions: string[]
complete: (partial: string) => string[]
accept: (suggestion: string) => string
reset: () => void
}
// Tab autocomplete for file paths
// Sources: Redis file index
// Fuzzy matching with scoring algorithm
Deliverables:
- useAutocomplete hook implementation
- Integration with Input component (Tab key)
- Path completion from Redis index
- Fuzzy matching support
- Unit tests (21 tests)
- Visual feedback in Input component
- Real-time suggestion updates
0.21.2 - Edit Mode in ConfirmDialog ✅
// Enhanced ConfirmDialog with edit mode
// When user presses [E]:
// 1. Show editable text area with proposed changes
// 2. User modifies the content
// 3. Apply modified version
interface ConfirmDialogProps {
message: string
diff?: DiffViewProps
onSelect: (choice: ConfirmChoice, editedContent?: string[]) => void
editableContent?: string[]
}
Deliverables:
- EditableContent component for inline editing
- Integration with ConfirmDialog [E] option
- Handler in App.tsx for edit choice
- ExecuteTool support for edited content
- ConfirmationResult type with editedContent field
- All existing tests passing (1484 tests)
0.21.3 - Multiline Input ✅
// src/tui/components/Input.tsx
interface InputProps {
multiline?: boolean | "auto" // auto = detect based on content
}
Deliverables:
- Multiline support in Input component
- Line navigation support
- Auto-expand based on content
- Unit tests (37 tests)
0.21.4 - Syntax Highlighting in DiffView ✅
// src/tui/utils/syntax-highlighter.ts (167 LOC)
// Custom tokenizer for TypeScript/JavaScript/JSON/YAML
// Highlights keywords, strings, comments, numbers, operators
interface DiffViewProps {
language?: Language
syntaxHighlight?: boolean
}
Deliverables:
- Syntax highlighter implementation (167 LOC)
- Language detection from file extension
- Integration with DiffView and ConfirmDialog
- Unit tests (24 tests)
Tests:
- Unit tests for useAutocomplete (21 tests)
- Unit tests for enhanced ConfirmDialog
- Unit tests for multiline Input (37 tests)
- Unit tests for syntax highlighting (24 tests)
Version 0.22.0 - Extended Configuration ⚙️
Priority: MEDIUM Status: Complete (5/5 complete) ✅
0.22.1 - Display Configuration ✅
// src/shared/constants/config.ts additions
export const DisplayConfigSchema = z.object({
showStats: z.boolean().default(true),
showToolCalls: z.boolean().default(true),
theme: z.enum(["dark", "light"]).default("dark"),
bellOnComplete: z.boolean().default(false),
progressBar: z.boolean().default(true),
})
Deliverables:
- DisplayConfigSchema in config.ts
- Bell notification on response complete
- Theme support (dark/light color schemes)
- Configurable stats display
- Unit tests (46 new tests: 20 schema, 24 theme, 2 bell)
0.22.2 - Session Configuration ✅
// src/shared/constants/config.ts additions
export const SessionConfigSchema = z.object({
persistIndefinitely: z.boolean().default(true),
maxHistoryMessages: z.number().int().positive().default(100),
saveInputHistory: z.boolean().default(true),
})
Deliverables:
- SessionConfigSchema in config.ts
- History truncation based on maxHistoryMessages
- Input history persistence toggle
- Unit tests (19 new tests)
0.22.3 - Context Configuration ✅
// src/shared/constants/config.ts additions
export const ContextConfigSchema = z.object({
systemPromptTokens: z.number().int().positive().default(2000),
maxContextUsage: z.number().min(0).max(1).default(0.8),
autoCompressAt: z.number().min(0).max(1).default(0.8),
compressionMethod: z.enum(["llm-summary", "truncate"]).default("llm-summary"),
})
Deliverables:
- ContextConfigSchema in config.ts
- ContextManager reads from config
- Configurable compression threshold
- Unit tests (40 new tests: 32 schema, 8 ContextManager integration)
0.22.4 - Autocomplete Configuration ✅
// src/shared/constants/config.ts additions
export const AutocompleteConfigSchema = z.object({
enabled: z.boolean().default(true),
source: z.enum(["redis-index", "filesystem", "both"]).default("redis-index"),
maxSuggestions: z.number().int().positive().default(10),
})
Deliverables:
- AutocompleteConfigSchema in config.ts
- useAutocomplete reads from config
- Unit tests (27 tests)
0.22.5 - Commands Configuration ✅
// src/shared/constants/config.ts additions
export const CommandsConfigSchema = z.object({
timeout: z.number().int().positive().nullable().default(null),
})
Deliverables:
- CommandsConfigSchema in config.ts
- Timeout support for run_command tool
- Unit tests (19 schema tests + 3 RunCommandTool integration tests)
Tests:
- Unit tests for CommandsConfigSchema (19 tests)
- Integration tests for RunCommandTool with config (3 tests)
Version 0.23.0 - JSON/YAML & Symlinks 📄 ✅
Priority: LOW Status: Complete (v0.23.0 released)
0.23.1 - JSON/YAML AST Parsing ✅
// src/infrastructure/indexer/ASTParser.ts enhancements
type Language = "ts" | "tsx" | "js" | "jsx" | "json" | "yaml"
// For JSON: extract keys, structure (tree-sitter-json)
// For YAML: extract keys, structure (yaml npm package)
Note: YAML parsing uses yaml npm package instead of tree-sitter-yaml due to native binding compatibility issues.
Deliverables:
- Add tree-sitter-json dependency
- JSON parsing in ASTParser
- YAML parsing in ASTParser (using
yamlpackage) - Unit tests (2 tests)
0.23.2 - Symlinks Metadata ✅
// src/domain/services/IIndexer.ts enhancements
export interface ScanResult {
path: string
type: "file" | "directory" | "symlink"
size: number
lastModified: number
symlinkTarget?: string // <-- NEW: target path for symlinks
}
Deliverables:
- Add symlinkTarget to ScanResult
- FileScanner extracts symlink targets via safeReadlink()
- Unit tests (FileScanner tests)
Tests:
- Unit tests for JSON/YAML parsing (2 tests)
- Unit tests for symlink handling (FileScanner tests)
Version 0.24.0 - Rich Initial Context 📋 ✅
Priority: HIGH Status: Complete (v0.24.0 released)
Enhance initial context for LLM: add function signatures, interface field types, and enum values. This allows LLM to answer questions about types and parameters without tool calls.
0.24.1 - Function Signatures with Types ⭐ ✅
Problem: Currently LLM only sees function names: fn: getUser, createUser
Solution: Show full signatures: async getUser(id: string): Promise<User>
// src/infrastructure/llm/prompts.ts changes
// BEFORE:
// - src/services/user.ts [fn: getUser, createUser]
// AFTER:
// ### src/services/user.ts
// - async getUser(id: string): Promise<User>
// - async createUser(data: UserDTO): Promise<User>
// - validateEmail(email: string): boolean
Changes:
- Extend
FunctionInfoin FileAST for parameter types and return type (already existed) - Update
ASTParser.tsto extract parameter types and return types (arrow functions fixed) - Update
formatFileSummary()in prompts.ts to output signatures - Add
includeSignatures: booleanoption to config
Why: LLM won't hallucinate parameters and return types.
0.24.2 - Interface/Type Field Definitions ⭐ ✅
Problem: LLM only sees interface: User, UserDTO
Solution: Show fields: User { id: string, name: string, email: string }
// BEFORE:
// - src/types/user.ts [interface: User, UserDTO]
// AFTER:
// ### src/types/user.ts
// - interface User { id: string, name: string, email: string, createdAt: Date }
// - interface UserDTO { name: string, email: string }
// - type UserId = string
Changes:
- Extend
InterfaceInfoin FileAST for field types (already existed) - Update
ASTParser.tsto extract interface fields (already existed) - Update
formatFileSummary()to output fields - Handle type aliases with their definitions
Why: LLM knows data structure, won't invent fields.
0.24.3 - Enum Value Definitions ⭐ ✅
Problem: LLM only sees type: Status
Solution: Show values: Status { Active=1, Inactive=0, Pending=2 }
// BEFORE:
// - src/types/enums.ts [type: Status, Role]
// AFTER:
// ### src/types/enums.ts
// - enum Status { Active=1, Inactive=0, Pending=2 }
// - enum Role { Admin="admin", User="user" }
Changes:
- Add
EnumInfoto FileAST with members and values - Update
ASTParser.tsto extract enum members - Update
formatFileSummary()to output enum values
Why: LLM knows valid enum values.
0.24.4 - Decorator Extraction ⭐ ✅
Problem: LLM doesn't see decorators (important for NestJS, Angular) Solution: Show decorators in context
// AFTER:
// ### src/controllers/user.controller.ts
// - @Controller('users') class UserController
// - @Get(':id') async getUser(id: string): Promise<User>
// - @Post() @Body() async createUser(data: UserDTO): Promise<User>
Changes:
- Add
decorators: string[]to FunctionInfo, MethodInfo, and ClassInfo - Update
ASTParser.tsto extract decorators viaextractNodeDecorators()andextractDecoratorsFromSiblings() - Update
prompts.tsto display decorators viaformatDecoratorsPrefix()
Why: LLM understands routing, DI, guards in NestJS/Angular.
Tests:
- Unit tests for ASTParser decorator extraction (14 tests)
- Unit tests for prompts decorator formatting (6 tests)
Version 0.25.0 - Graph Metrics in Context 📊
Priority: MEDIUM Status: Planned
Add graph metrics to initial context: dependency graph, circular dependencies, impact score.
0.25.1 - Inline Dependency Graph
Problem: LLM doesn't see file relationships without tool calls Solution: Show dependency graph in context
// Add to initial context:
// ## Dependency Graph
// src/services/user.ts: → types/user, utils/validation ← controllers/user, api/routes
// src/services/auth.ts: → services/user, utils/jwt ← controllers/auth
// src/utils/validation.ts: ← services/user, services/auth, controllers/*
Changes:
- Add
formatDependencyGraph()to prompts.ts - Use data from
FileMeta.dependenciesandFileMeta.dependents - Group by hub files (many connections)
- Add
includeDepsGraph: booleanoption to config
Why: LLM sees architecture without tool call.
0.25.2 - Circular Dependencies in Context
Problem: Circular deps are computed but not shown in context Solution: Show cycles immediately
// Add to initial context:
// ## ⚠️ Circular Dependencies
// - services/user → services/auth → services/user
// - utils/a → utils/b → utils/c → utils/a
Changes:
- Add
formatCircularDeps()to prompts.ts - Get circular deps from IndexBuilder
- Store in Redis as separate key or in meta
Why: LLM immediately sees architecture problems.
0.25.3 - Impact Score
Problem: LLM doesn't know which files are critical Solution: Show impact score (% of codebase that depends on file)
// Add to initial context:
// ## High Impact Files
// | File | Impact | Dependents |
// |------|--------|------------|
// | src/utils/validation.ts | 67% | 12 files |
// | src/types/user.ts | 45% | 8 files |
// | src/services/user.ts | 34% | 6 files |
Changes:
- Add
impactScore: numberto FileMeta (0-100) - Compute in MetaAnalyzer: (transitiveDepByCount / totalFiles) * 100
- Add
formatHighImpactFiles()to prompts.ts - Show top-10 high impact files
Why: LLM understands which files are critical for changes.
0.25.4 - Transitive Dependencies Count
Problem: Currently only counting direct dependencies Solution: Add transitive dependencies to meta
// FileMeta additions:
interface FileMeta {
// existing...
transitiveDepCount: number; // how many files depend on this (transitively)
transitiveDepByCount: number; // how many files this depends on (transitively)
}
Changes:
- Add
computeTransitiveDeps()to MetaAnalyzer - Use DFS with memoization for efficiency
- Store in FileMeta
Tests:
- Unit tests for graph metrics computation
- Unit tests for new context sections
- Performance tests for large codebases
Version 1.0.0 - Production Ready 🚀
Target: Stable release
Checklist:
- All 18 tools implemented and tested ✅ (v0.9.0)
- TUI fully functional ✅ (v0.11.0, v0.12.0)
- Session persistence working ✅ (v0.10.0)
- Error handling complete ✅ (v0.16.0)
- Performance optimized
- Documentation complete ✅ (v0.17.0)
- Test coverage ≥91% branches, ≥95% lines/functions/statements ✅ (91.21% branches, 97.5% lines, 98.58% functions, 97.5% statements - 1687 tests)
- 0 ESLint errors ✅
- Examples working ✅ (v0.18.0)
- CHANGELOG.md up to date ✅
- Rich initial context (v0.24.0) — function signatures, interface fields, enum values, decorators ✅
- Graph metrics in context (v0.25.0) — dependency graph, circular deps, impact score
Post 1.0 - Future 💡
1.1.0 - Performance
- Parallel AST parsing
- Incremental indexing
- Response caching
1.2.0 - Features
- Multiple file edits in one operation
- Batch operations
- Custom prompt templates
1.3.0 - Extensibility
- Plugin system for tools
- Custom LLM providers (OpenAI, Anthropic)
- IDE integration (LSP?)
Summary Tables
Tool Summary (18 total)
| Category | Tool | Confirm | Description |
|---|---|---|---|
| Read | get_lines | No | Get file lines |
| get_function | No | Get function by name | |
| get_class | No | Get class by name | |
| get_structure | No | Get project tree | |
| Edit | edit_lines | Yes | Replace lines |
| create_file | Yes | Create new file | |
| delete_file | Yes | Delete file | |
| Search | find_references | No | Find symbol usages |
| find_definition | No | Find symbol definition | |
| Analysis | get_dependencies | No | File imports |
| get_dependents | No | Files importing this | |
| get_complexity | No | Complexity metrics | |
| get_todos | No | Find TODO/FIXME | |
| Git | git_status | No | Repository status |
| git_diff | No | Uncommitted changes | |
| git_commit | Yes | Create commit | |
| Run | run_command | Conditional | Execute shell command |
| run_tests | No | Run test suite |
Redis Schema
# Project (5 keys per project)
project:{name}:files # Hash<path, FileData>
project:{name}:ast # Hash<path, FileAST>
project:{name}:meta # Hash<path, FileMeta>
project:{name}:indexes # Hash<name, JSON>
project:{name}:config # Hash<key, JSON>
# Sessions (3 keys per session)
session:{id}:data # Hash<field, JSON>
session:{id}:undo # List<UndoEntry> max 10
sessions:list # List<session_id>
Context Budget (128K window)
| Component | Tokens | % |
|---|---|---|
| System prompt | ~2,000 | 1.5% |
| Structure + AST (v0.23) | ~10,000 | 8% |
| Signatures + Types (v0.24) | ~5,000 | 4% |
| Graph Metrics (v0.25) | ~3,000 | 2.5% |
| Total Initial Context | ~20,000 | 16% |
| Available for Chat | ~108,000 | 84% |
Last Updated: 2025-12-05 Target Version: 1.0.0 Current Version: 0.26.0 Next Milestones: v0.25.0 (Graph Metrics - 0/4 complete)
Note: v0.24.0 complete ✅. v0.25.0 (Graph Metrics) is required for 1.0.0 release. It enables LLM to see architecture without tool calls.