This file provides context for Codi, the AI coding wingman, when working on the Codi codebase.
The codebase includes an experimental “open files” working-set concept:
src/open-files.ts:OpenFilesManager+ serializableOpenFilesStatesrc/session.ts:Session.openFilesState?: OpenFilesStateand persistence viasaveSession()
When changing this area:
- keep
OpenFilesStatebackwards-compatible (old sessions may not have it) - update tests that assert on session serialization/deserialization
This project is designed to work optimally with Codi, your AI coding wingman. Codi provides direct access to codebase tools:
Codi can call tools directly by mentioning them in conversation:
get_context_status(): Check token usage and context status in real-timeread_file(path): Read file contents efficiently with cachingsearch_codebase(query): Semantic search across the entire codebasefind_symbol(name): Locate function/class/interface definitions instantlygrep(pattern, path): Search for patterns within filesglob(pattern): Find files matching patterns- And dozens of other tools for file operations, shell commands, and code intelligence
Monitor and optimize resource usage:
- Automatic context compaction when approaching token limits
- Cached results via
recall_result(cache_id)to avoid re-fetching - Working set tracking of recently accessed files
- Tier-based configuration adapting to model context window size
Using Codi with this codebase:
"I need to understand the session management system"
find_symbol("SessionInfo") // Locates all definitions
read_file("src/session.ts") // Reads the session implementation
grep("saveSession", "src/") // Finds all references to saveSession
get_context_status() // Checks current context usage
Codi is your AI coding wingman for the terminal - a CLI tool that supports multiple AI providers (Claude, OpenAI, Ollama, RunPod). It enables developers to work with AI models through a conversational interface while giving the AI access to filesystem tools, and this project's architecture anticipates intelligent tool use and context management.
# Development
pnpm dev # Run with TypeScript directly
pnpm build # Compile to JavaScript
pnpm test # Run tests
pnpm test:watch # Watch mode
# Interactive mode (default)
ANTHROPIC_API_KEY=... pnpm dev
# Testing with different providers
ANTHROPIC_API_KEY=... pnpm dev
OPENAI_API_KEY=... pnpm dev -- --provider openai
pnpm dev -- --provider ollama --model llama3.2IMPORTANT: Never push directly to main. Always use feature/bugfix branches and pull requests.
# Start new work (from main or dev if using worktrees)
git checkout main # Always start from main
git pull origin main --rebase # Rebase to stay current
git checkout -b feat/my-feature # Create feature branch for actual work
# ... make changes ...
git add -A && git commit -m "feat: description"
git push -u origin feat/my-feature
# When feature branch needs to sync with main (before PR or to resolve conflicts)
git checkout feat/my-feature
git rebase origin/main # Use rebase, NEVER merge
git push origin feat/my-feature --force-with-lease # Force push after rebase
# Create PR (always targets main)
gh pr create --title "feat: description" --body "Summary of changes"
# After PR is approved and merged
# Switch back to main and delete the feature branch
git checkout main
git pull origin main --rebase # Get latest changes
git branch -d feat/my-feature # Delete local branch
git push origin --delete feat/my-feature # Delete remote branchMain Branch (main)
- Production-ready code
- Protected with PR requirements and CI checks
- All PRs must target
main - Use
git pull origin main --rebaseto stay current
Dev Branch (if using worktrees)
- Purpose Only: Stays in the worktree directory
- No Development: All actual work happens on feature branches
- Keep Synced: Rebase regularly with
origin/main -
# If using dev branch in worktree: git checkout dev git rebase origin/main # Keep dev synced git push origin dev
- Never commit work directly to dev - create feature branches instead
Feature Branches (feat/*, fix/*, chore/*)
- All development happens here
- Short-lived, deleted after merge
- Always rebase from
origin/main, never merge - Clean merge history when rebased properly
✅ Use REBASE (correct):
git rebase origin/main # Keeps history linear
git push --force-with-lease # Safe force-push after rebase❌ DO NOT Use MERGE (incorrect):
git merge origin/main # Creates unnecessary merge commitsfeat/- New featuresfix/- Bug fixeschore/- Maintenance, refactoring, docs
After merging PRs, tag and release from main:
# Update version in package.json and src/version.ts
git add -A && git commit -m "chore: bump version to X.Y.Z"
git tag -a vX.Y.Z -m "vX.Y.Z: Brief description"
git push origin main && git push origin vX.Y.Z
gh release create vX.Y.Z --title "vX.Y.Z: Title" --notes "Release notes"IMPORTANT: Never merge a PR without reviewing it first. Always review your own PRs before merging. This creates a traceable review history and catches mistakes before they reach main.
CRITICAL: Never merge a PR until ALL checks pass. This includes:
- All tests must pass (
pnpm testwith zero failures) - Build must succeed (
pnpm build) - Any CI/CD checks must be green
If tests are failing, fix them before merging - even if the failures appear unrelated to your changes.
For AI agents (Claude, Codi, etc.): Do NOT immediately merge after creating a PR. Always:
- Create the PR
- Run
pnpm build && pnpm testto verify nothing is broken - Review the diff with
gh pr diff <number> - Check feature completeness (see checklist below)
- Add a review comment documenting what was checked
- Only then merge (if all tests pass and no issues found)
Full Process:
- Create the PR with clear title and description
- Run build and tests to verify nothing is broken:
If tests fail, fix the issues before proceeding.
pnpm build && pnpm test
- Review the diff thoroughly using
gh pr diff <number> - Check feature completeness (for new features/commands):
-
/helpupdated with new commands (showHelp()insrc/index.ts) - System prompts reviewed for relevance (search for
generateSystemPrompt) - Worker/delegation prompts correct if feature involves AI calls
-
README.mdupdated with user-facing documentation -
CLAUDE.mdupdated with developer documentation -
docs/index.htmlupdated if significant feature - CLI
--helpflags documented if new options added - Tests added for new functionality
- Version bumped if significant change (package.json + src/version.ts)
-
- Document the review - add a comment listing what was verified:
gh pr comment <number> --body "## Self-Review - ✅ Build passes - ✅ All tests pass (N tests) - ✅ Verified change X - ✅ Verified change Y - ✅ Feature completeness checked - No issues found. Ready to merge."
- If issues found, add comments and fix:
# Add a review comment on specific issues gh pr review <number> --comment --body "Found issue: description of problem"
- Fix the issues in a new commit (don't amend if already pushed)
- For issues to address later, create a GitHub issue:
gh issue create --title "Title" --body "Description of future work"
- Merge only after review is complete and all tests pass
This ensures:
- All review feedback is tracked in the PR history
- Future contributors can understand why changes were made
- Deferred work is captured as issues, not forgotten
- AI agents don't blindly merge without verification
- No broken code reaches main - tests must pass before merge
If you're working in a directory on the dev branch instead of main, it's likely because multiple worktrees are in use. Git doesn't allow the same branch to be checked out in multiple worktrees simultaneously.
When on dev branch:
- Keep
devsynced withmainusing rebase:git fetch origin && git rebase origin/main - Never merge - only rebase to keep history clean
- Create feature branches from
main, notdev(switch to main first) - PRs always target
mainas the base branch - After feature branches merge, sync
devwith:git fetch origin && git rebase origin/main && git push origin dev - Remember:
devis just a placeholder for the worktree - all actual work happens on feature branches
Check worktree setup:
git worktree list # Shows all worktrees and their branchessrc/
├── index.ts # CLI entry, REPL loop, readline interface
├── agent.ts # Core agent loop - orchestrates model + tools
├── config.ts # Workspace configuration loading and merging
├── context.ts # Project detection (Node, Python, Rust, Go)
├── session.ts # Session persistence management
├── types.ts # TypeScript interfaces
├── logger.ts # Level-aware logging (NORMAL/VERBOSE/DEBUG/TRACE)
├── spinner.ts # Ora spinner manager for visual feedback
├── compression.ts # Entity-based context compression
├── commands/ # Slash command system
│ ├── index.ts # Command registry
│ ├── prompt-commands.ts # Information prompts (explain, review, analyze)
│ ├── code-commands.ts # Code modification (refactor, fix, test)
│ ├── git-commands.ts
│ ├── session-commands.ts
│ ├── compact-commands.ts # Context management
│ ├── config-commands.ts
│ └── orchestrate-commands.ts # Multi-agent orchestration
├── providers/ # AI model backends
├── tools/ # Filesystem interaction tools
├── orchestrate/ # Multi-agent orchestration
│ ├── commander.ts # Parent orchestrator managing workers
│ ├── child-agent.ts # Agent wrapper with IPC-based permissions
│ ├── worktree.ts # Git worktree management
│ └── ipc/ # Unix socket communication
│ ├── protocol.ts # Message types and serialization
│ ├── server.ts # Socket server (commander side)
│ └── client.ts # Socket client (worker side)
└── rag/ # RAG system for semantic code search
├── indexer.ts # File indexing and chunking
├── search.ts # Semantic search
└── embeddings.ts # Embedding generation
| File | Purpose |
|---|---|
src/agent.ts |
The agentic loop - sends messages, handles tool calls, manages conversation |
src/index.ts |
CLI setup, REPL, command parsing, user interaction |
src/config.ts |
Workspace configuration loading, validation, and merging |
src/session.ts |
Session persistence - save/load conversation history |
src/logger.ts |
Level-aware logging with NORMAL/VERBOSE/DEBUG/TRACE levels |
src/spinner.ts |
Ora spinner manager with TTY detection |
src/compression.ts |
Entity-based context compression for token savings |
src/providers/base.ts |
Abstract provider interface all backends implement |
src/tools/registry.ts |
Tool registration and execution |
src/tools/run-tests.ts |
Automatic test runner detection and execution |
src/rag/indexer.ts |
RAG file indexing and chunking |
src/rag/search.ts |
Semantic code search using embeddings |
src/types.ts |
All TypeScript interfaces |
src/index.tsrunsmain()- Detects project with
detectProject() - Registers tools + commands
- Determines provider (
detectProvider()orcreateProvider()) - Builds system prompt with project context
- Instantiates
Agentwith provider, registry, callbacks - Starts readline prompt loop
- Built-in commands:
/exit,/clear,/compact,/status,/context - Slash commands: Parse
/command args, execute → returns prompt string, send to agent - Normal chat: Send raw input to
agent.chat()
- Append user message to
this.messages - Compact context if token estimate exceeds threshold
- Repeat up to
MAX_ITERATIONS:- Compute tool definitions if tools enabled
- Build system context with optional conversation summary
- Call provider
streamChat() - Extract tool calls (native or from text)
- If no tool calls → finish
- Otherwise: execute tools, add results to conversation, continue
- Provider Abstraction:
BaseProvider+ factory pattern for easy backend additions - Tool Registry: Decoupled tools with self-describing schemas
- Safety Limits:
MAX_ITERATIONSprevents infinite loops,MAX_CONSECUTIVE_ERRORSstops on repeated failures - Context Compaction: Token estimation + model-based summarization of older messages
- Cross-Provider Normalization: Internal format supports both string and structured tool blocks
- Fallback Tool Extraction: Parses JSON from text for models without native tool calling
- Streaming-First: Provider
streamChatfor incremental text display
- ES Modules: Use
.jsextension in imports (even for.tsfiles) - Async/Await: Prefer async/await over callbacks
- Type Safety: Use TypeScript interfaces, avoid
any - Error Handling: Tools should catch errors and return descriptive messages
- Streaming: Use callbacks for real-time output (
onText,onToolCall, etc.)
// 1. Create src/tools/my-tool.ts
export class MyTool extends BaseTool {
getDefinition(): ToolDefinition { /* JSON schema */ }
async execute(input: Record<string, unknown>): Promise<string> { /* logic */ }
}
// 2. Register in src/tools/index.ts
registry.register(new MyTool());// In src/commands/*.ts
export const myCommand: Command = {
name: 'mycommand',
aliases: ['mc'],
description: 'Description',
usage: '/mycommand <args>',
execute: async (args, context) => `Prompt for AI: ${args}`,
};
registerCommand(myCommand);// 1. Create src/providers/my-provider.ts extending BaseProvider
// 2. Implement: chat(), streamChat(), getName(), getModel(), supportsToolUse()
// 3. Add to createProvider() in src/providers/index.tsTests use Vitest and are located in tests/. Run with pnpm test.
Key test areas:
- Tool execution and error handling
- Provider instantiation
- Agent initialization
- File system operations (uses temp directories)
Codi supports a non-interactive mode for scripting and automation. Instead of starting the interactive REPL, you can run a single prompt and get the result.
| Option | Description |
|---|---|
-P, --prompt <text> |
Run a single prompt and exit |
-f, --output-format <format> |
Output format: text (default) or json |
-q, --quiet |
Suppress spinners and progress output |
-y, --yes |
Auto-approve all tool operations |
# Basic usage - get response and exit
codi -P "explain what this function does" src/utils.ts
# JSON output for scripting
codi -P "list all TODO comments" -f json
# Quiet mode for CI/CD pipelines
codi -P "run tests and fix any failures" -q -y
# Combine with shell commands
codi -P "generate a commit message" | git commit -F -When using -f json, the output is a JSON object:
{
"success": true,
"response": "The function calculates...",
"toolCalls": [
{ "name": "read_file", "input": { "path": "src/utils.ts" } }
],
"usage": { "inputTokens": 1000, "outputTokens": 500 }
}On error:
{
"success": false,
"response": "",
"toolCalls": [],
"usage": null,
"error": "API key not found"
}| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | Error (API error, tool failure, etc.) |
Below are feature ideas organized by complexity and impact. Each includes implementation guidance.
Status: Complete
All git commands are consolidated under /git <subcommand> with convenient aliases.
Main Command (in src/commands/git-commands.ts):
| Command | Aliases | Description |
|---|---|---|
/git commit [type] |
/commit, /ci |
Generate commit message with conventional commits |
/git branch [action] [name] |
/branch, /br |
Create, switch, list, delete, rename branches |
/git diff [target] |
- | Show and explain git differences |
/git pr [base] |
/pr |
Generate PR description |
/git stash [action] |
- | Manage stash (save, list, pop, apply, drop, clear) |
/git log [target] |
- | Show and explain git history |
/git status |
- | Detailed git status with explanations |
/git undo [what] |
- | Safely undo commits, staged changes, file changes |
/git merge <branch> |
- | Merge branches with conflict guidance |
/git rebase <branch> |
- | Rebase with safety warnings |
Key Features:
- Consolidated under
/gitprefix with subcommand structure - Standalone aliases for common commands:
/commit,/branch,/pr - Conventional commits support (feat, fix, docs, etc.)
- Branch actions: list, create, switch, delete, rename
- Safe undo operations with appropriate warnings
Status: Complete
Implemented Commands (in src/commands/session-commands.ts):
| Command | Description |
|---|---|
/save [name] |
Save current conversation to a session file |
/load <name> |
Load a previously saved session |
/sessions |
List all saved sessions |
/sessions info [name] |
Show details about a session |
/sessions delete <name> |
Delete a saved session |
/sessions clear |
Delete all saved sessions |
/label [text] |
Set/show conversation label |
/label clear |
Remove the conversation label |
Key Features:
- Sessions stored in
~/.codi/sessions/as JSON - Includes full message history, compaction summaries, project context
- Metadata: provider, model, timestamps, project name/path
- Fuzzy search for session names
- Load session on startup with
-s/--session <name>CLI option - Auto-saves to current session name if one is loaded
- Conversation labels displayed as
[label] You:prompt prefix - Labels persist and restore with session save/load
Status: Complete
Config File Locations (searched in order):
.codi.json.codi/config.jsoncodi.config.json
Configuration Options (in src/config.ts):
{
"provider": "anthropic",
"model": "claude-sonnet-4-20250514",
"baseUrl": "https://api.example.com",
"endpointId": "runpod-endpoint-id",
"autoApprove": ["read_file", "glob", "grep", "list_directory"],
"dangerousPatterns": ["custom-pattern-.*"],
"systemPromptAdditions": "Always use TypeScript strict mode.",
"noTools": false,
"defaultSession": "my-project-session",
"commandAliases": {
"t": "/test src/",
"b": "/build"
},
"projectContext": "This is a React app using Next.js 14."
}Implemented Commands (in src/commands/config-commands.ts):
| Command | Description |
|---|---|
/config |
Show current workspace configuration |
/config init |
Create a new .codi.json file |
/config example |
Show example configuration |
Key Features:
- Per-tool auto-approval (e.g., auto-approve
read_filebut confirmbash) - Custom dangerous patterns (regex) for bash command warnings
- System prompt additions for project-specific instructions
- Project context for AI awareness
- Command aliases for shortcuts
- Default session to load on startup
- CLI options override config settings
Status: Complete
Implemented Commands (in src/commands/model-commands.ts):
| Command | Aliases | Description |
|---|---|---|
/models [provider] [--local] |
/model, /list-models |
List available models with pricing and capabilities |
/switch <provider> [model] |
/use, /model-switch |
Switch to a different model during a session |
Key Features:
- Live API fetching with static fallback for model lists
- Shows model capabilities (vision, tool use)
- Shows context window sizes
- Shows pricing per million tokens (input/output)
- Supports filtering by provider:
/models anthropic,/models openai,/models ollama,/models ollama-cloud - Local-only mode:
/models --localshows only Ollama models - Switch models mid-session without restarting
- Switch providers mid-session:
/switch openai gpt-4o - Switch models within current provider:
/switch claude-3-5-haiku-latest
Files:
src/commands/model-commands.ts- Command implementationssrc/models.ts- Static model registry with pricing datasrc/providers/base.ts-ModelInfointerface,listModels()methodsrc/providers/anthropic.ts- Live model listing from APIsrc/providers/openai-compatible.ts- Live model listing from API + Ollamasrc/index.ts- Output formatting for model tables
Status: Complete
Implemented Commands (in src/commands/memory-commands.ts):
| Command | Aliases | Description |
|---|---|---|
/remember [category:] <fact> |
/mem, /note |
Remember a fact for future sessions |
/forget <pattern> |
/unmem |
Remove memories matching pattern |
/memories [query] |
/mems |
List or search stored memories |
/profile [set key value] |
/me |
View or update user profile |
Key Features:
- Implements context personalization pattern from OpenAI Agents SDK
- Structured user profile (name, preferences, expertise, avoid lists)
- Categorized memory notes with timestamps
- Automatic memory injection into system prompt
- Session notes with consolidation (
/memories consolidate) - Duplicate detection prevents redundant memories
Storage:
~/.codi/profile.yaml- User profile in YAML format~/.codi/memories.md- Persistent memories in Markdown format~/.codi/session-notes.md- Temporary session notes
Profile Keys:
name- User's namepreferences.language- Preferred programming languagepreferences.style- Coding style (functional, oop, etc.)preferences.verbosity- Response verbosity (concise, normal, detailed)expertise- Add an area of expertiseavoid- Add something to avoid
Files:
src/memory.ts- Memory and profile managementsrc/commands/memory-commands.ts- Command implementationssrc/index.ts- Memory context injection into system prompt
Status: Complete
Implemented Commands (in src/commands/prompt-commands.ts):
| Command | Aliases | Description |
|---|---|---|
/prompt explain <file> |
/prompt e |
Explain code in a file |
/prompt review <file> |
/prompt cr |
Code review for a file |
/prompt analyze <file> |
/prompt a |
Analyze code structure |
/prompt summarize <file> |
/prompt sum |
Summarize code purpose |
Key Features:
- Information-only prompts that don't modify files
- Subcommand-based interface under unified
/promptcommand - All prompts include file content and project context
- Suitable for read-only code understanding tasks
Files:
src/commands/prompt-commands.ts- Command implementations
Status: Complete
All code action commands are consolidated under /code <subcommand> with convenient aliases.
Implemented Commands (in src/commands/code-commands.ts):
| Command | Aliases | Description |
|---|---|---|
/code refactor <file> [focus] |
/refactor, /r |
Refactor code for quality |
/code fix <file> <issue> |
/fix, /f |
Fix a bug or issue |
/code test <file> [function] |
/test, /t |
Generate tests |
/code doc <file> |
- | Generate JSDoc documentation |
/code optimize <file> |
- | Optimize for performance |
Key Features:
- Consolidated under
/codeprefix with subcommand structure - Standalone aliases for common commands:
/refactor,/fix,/test - All commands instruct AI to use edit_file/write_file tools
- Project-aware (detects test framework, language, etc.)
Files:
src/commands/code-commands.ts- Command implementations
Status: Complete
Key Features (in src/diff.ts):
- Unified diff preview for
write_fileandedit_fileoperations - Color-coded diff display in terminal (green for additions, red for removals)
- Automatic truncation for large diffs (shows first/last portions)
- Statistics: lines added, lines removed, new file detection
- Integrated into confirmation flow - shows diff before user approves
How it works:
- When you use
write_fileoredit_file, the confirmation prompt now shows a unified diff - Green lines (
+) show what will be added - Red lines (
-) show what will be removed - The diff is automatically truncated if it's too long
Files:
src/diff.ts- Diff generation and formatting utilitiessrc/agent.ts- Generates diffs during confirmationsrc/index.ts- Displays formatted diffs in confirmation prompt- Dependency:
diffpackage
Status: Complete
Key Features (in src/history.ts):
- Automatic tracking of all file modifications (write, edit, insert, patch)
- Original file content backed up before each change
- History stored in
~/.codi/history/with timestamps - Maximum 50 entries kept (oldest pruned automatically)
- Full undo/redo support
Implemented Commands (in src/commands/history-commands.ts):
| Command | Aliases | Description |
|---|---|---|
/revert-file |
/rf, /fileundo, /fu |
Undo the last file change |
/redo |
- | Redo an undone change |
/filehistory |
/fh |
Show file change history |
/filehistory clear |
- | Clear all history |
/filehistory <file> |
- | Show history for specific file |
How it works:
- Every
write_file,edit_file,insert_line, andpatch_fileoperation is recorded - Original content is saved as backup before modification
- Undo restores the original content (or deletes file if it was created)
- Redo reapplies the change
- History is persistent across sessions
Files:
src/history.ts- History tracking and undo/redo logicsrc/commands/history-commands.ts- User-facing commands- All file tools modified:
write-file.ts,edit-file.ts,insert-line.ts,patch-file.ts
Status: Temporarily disabled pending investigation (see GitHub issue #17)
Key Features (in src/plugins.ts):
- Plugin interface for third-party extensions
- Automatic loading from
~/.codi/plugins/directory - Support for tools, commands, and providers
- Lifecycle hooks (onLoad, onUnload)
- Dynamic ESM imports
Plugin Interface:
interface CodiPlugin {
name: string;
version: string;
description?: string;
tools?: BaseTool[];
commands?: Command[];
providers?: {
type: string;
factory: (options: ProviderConfig) => BaseProvider;
}[];
onLoad?: () => Promise<void>;
onUnload?: () => Promise<void>;
}Implemented Commands (in src/commands/plugin-commands.ts):
| Command | Description |
|---|---|
/plugins |
List all loaded plugins |
/plugins info <name> |
Show details about a plugin |
/plugins dir |
Show plugins directory path |
Plugin Structure:
~/.codi/plugins/my-plugin/
├── package.json # Must include "main" entry point
├── index.js # Exports CodiPlugin object
└── ... # Additional files
Example Plugin (~/.codi/plugins/my-plugin/index.js):
export default {
name: 'my-plugin',
version: '1.0.0',
description: 'My custom plugin',
commands: [{
name: 'my-command',
description: 'My custom command',
execute: async (args) => `Received: ${args}`,
}],
onLoad: async () => console.log('Plugin loaded!'),
};Files:
src/plugins.ts- Plugin loader and registrysrc/commands/plugin-commands.ts- Plugin management commandssrc/providers/index.ts- Map-based provider factory (for plugin providers)
Status: Complete
Key Features (in src/usage.ts):
- Automatic token counting for each API request/response
- Cost estimation based on model pricing (Claude, GPT models)
- Session-level tracking (current session stats)
- Historical tracking stored in
~/.codi/usage.json - Aggregated statistics by provider and model
Implemented Commands (in src/commands/usage-commands.ts):
| Command | Aliases | Description |
|---|---|---|
/usage |
/cost, /tokens |
Show current session usage |
/usage session |
- | Show current session usage (default) |
/usage today |
- | Show today's usage |
/usage week |
- | Show last 7 days usage |
/usage month |
- | Show last 30 days usage |
/usage all |
- | Show all-time usage |
/usage recent |
- | Show recent usage records |
/usage reset |
- | Reset session usage |
/usage clear |
- | Clear all usage history |
Files:
src/usage.ts- Core usage tracking and cost calculationsrc/commands/usage-commands.ts- User-facing commandssrc/agent.ts- Records usage after each API callsrc/providers/anthropic.ts- Returns usage infosrc/providers/openai-compatible.ts- Returns usage info
Status: Complete
Key Features (in src/tools/analyze-image.ts):
analyze_imagetool for analyzing images using vision-capable models- Supports JPEG, PNG, GIF, and WebP formats
- Base64 encoding of image data
- Size warnings for large images (>5MB)
- Works with Claude 3+ and GPT-4V/4O models
How It Works:
- User asks to analyze an image
- AI calls
analyze_imagetool with the image path - Tool reads image, converts to base64, returns special format
- Agent parses the image data and adds it as an image content block
- Model receives the image and provides analysis
Provider Support:
- Anthropic: Claude 3 family (Haiku, Sonnet, Opus), Claude 4 (Sonnet, Opus)
- OpenAI: GPT-4V, GPT-4O, GPT-5, and models with "vision" in name
- Ollama: Most models don't support vision (graceful error)
Files:
src/tools/analyze-image.ts- Image analysis toolsrc/types.ts- ImageMediaType, ImageSource, ContentBlock with image supportsrc/providers/base.ts-supportsVision()methodsrc/providers/anthropic.ts- Image block handlingsrc/providers/openai-compatible.ts- Image URL format handlingsrc/agent.ts- Image result parsing and message formatting
What: Fuzzy file finder for commands.
Implementation:
- Add
fzf-like interface for file selection - Use when file argument is omitted
- Integrate with readline for better UX
Dependencies: inquirer or prompts package
What: Execute independent tools concurrently.
Implementation:
- Detect independent tool calls (no shared files)
- Execute with
Promise.all() - Merge results for model response
Files to modify:
- Modify:
src/agent.ts(parallel execution logic)
Status: Complete
Key Features (in src/tools/web-search.ts):
web_searchtool for searching the web via DuckDuckGo- No API key required - uses DuckDuckGo's public lite interface
- Returns titles, URLs, and snippets from search results
- Configurable number of results (1-10, default: 5)
How It Works:
- AI calls
web_searchtool with a query - Tool fetches results from DuckDuckGo lite
- Parses HTML to extract titles, URLs, and snippets
- Returns formatted text results
Example Output:
Search results for: "TypeScript 5.0 features"
1. TypeScript 5.0 Release Notes
https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html
TypeScript 5.0 introduces decorators, const type parameters, and more...
2. What's New in TypeScript 5.0
https://blog.example.com/typescript-5
A comprehensive guide to the latest TypeScript features...
Files:
src/tools/web-search.ts- Web search tool implementationtests/web-search.test.ts- Unit tests
Status: Complete
Key Features:
- Use a separate (cheaper) model for summarization during context compaction
- CLI options:
--summarize-modeland--summarize-provider - Config file support via
models.summarizesection - Graceful fallback to primary model if secondary unavailable
- Provider agnostic - secondary can use different provider than primary
CLI Usage:
# Use Ollama llama3.2 for summarization (free!)
codi --summarize-provider ollama --summarize-model llama3.2
# Use Claude Haiku for summarization (cheap)
codi --summarize-provider anthropic --summarize-model claude-3-5-haiku-latestConfig File (.codi.json):
{
"provider": "anthropic",
"model": "claude-sonnet-4-20250514",
"models": {
"summarize": {
"provider": "ollama",
"model": "llama3.2"
}
}
}Recommended Combinations:
| Use Case | Primary | Summarize |
|---|---|---|
| Cost-conscious | Claude Haiku | Ollama llama3.2 (free) |
| Balanced | Claude Sonnet | Claude Haiku |
| Local-first | Ollama deepseek-coder | Ollama llama3.2 |
| Quality-first | Claude Opus | Claude Sonnet |
Files:
src/index.ts- CLI optionssrc/config.ts- Config schemasrc/providers/index.ts-createSecondaryProvider()functionsrc/agent.ts-getSummaryProvider()methodtests/multi-model.test.ts- Unit tests
Status: Complete (Phases 1-3 + Model Roles)
Key Features (in src/model-map/):
- Docker-compose style configuration for multi-model orchestration
- Named model definitions with provider, model, and settings
- Task categories (fast, code, complex, summarize) with model assignments
- Per-command model overrides
- Fallback chains for reliability
- Pipeline definitions for multi-step workflows
- Model Roles: Provider-agnostic role mappings for portable pipelines
- Lazy provider instantiation with connection pooling
Config File (codi-models.yaml):
version: "1"
models:
haiku:
provider: anthropic
model: claude-3-5-haiku-latest
description: "Fast, cheap model for quick tasks"
sonnet:
provider: anthropic
model: claude-sonnet-4-20250514
gpt-5-nano:
provider: openai
model: gpt-5-nano
gpt-5:
provider: openai
model: gpt-5.2
local:
provider: ollama
model: llama3.2
tasks:
fast:
model: haiku
code:
model: sonnet
complex:
model: sonnet
summarize:
model: local
commands:
commit:
task: fast
fix:
task: complex
fallbacks:
primary: [sonnet, haiku, local]
# Model roles map abstract roles to concrete models per provider
model-roles:
fast:
anthropic: haiku
openai: gpt-5-nano
ollama: local
capable:
anthropic: sonnet
openai: gpt-5
ollama: local
pipelines:
# Direct model references
smart-refactor:
steps:
- name: analyze
model: haiku
prompt: "Analyze: {input}"
output: analysis
- name: implement
model: sonnet
prompt: "Implement based on: {analysis}"
output: result
result: "{result}"
# Provider-agnostic pipeline using roles
code-review:
description: "Multi-step code review"
provider: openai # default provider
steps:
- name: scan
role: fast # resolves based on --provider
prompt: "Quick scan: {input}"
output: issues
- name: analyze
role: capable # resolves based on --provider
prompt: "Deep analysis: {issues}"
output: analysis
result: "{analysis}"Model Roles Usage:
# Uses default provider (openai) - gpt-5-nano and gpt-5
/pipeline code-review src/file.ts
# Uses anthropic models - haiku and sonnet
/pipeline --provider anthropic code-review src/file.ts
# Uses local ollama models
/pipeline --provider ollama code-review src/file.tsImplemented Commands:
| Command | Aliases | Description |
|---|---|---|
/modelmap |
/mm |
Show current model map configuration |
/modelmap init |
- | Create a new codi-models.yaml file |
/modelmap example |
- | Show example configuration |
/pipeline [name] [input] |
/pipe |
Execute or list multi-model pipelines |
/pipeline --provider <ctx> [name] [input] |
- | Execute pipeline with specific provider context |
Architecture:
ModelMapLoader- Load/validate YAML configModelRegistry- Lazy provider instantiation with pooling (max 5, 5-min idle)TaskRouter- Route tasks/commands to models or pipelines, resolve rolesPipelineExecutor- Execute multi-step pipelines with variable substitution and role resolution
Files:
src/model-map/types.ts- Type definitions (including ProviderContext, RoleMapping, ModelRoles)src/model-map/loader.ts- YAML loading and validationsrc/model-map/registry.ts- Provider pool managementsrc/model-map/router.ts- Task/command routing and role resolutionsrc/model-map/executor.ts- Pipeline execution with role supportsrc/model-map/index.ts- Module exportstests/model-map.test.ts- 38 unit tests
Completed Features:
-
taskTypeon Command interface for automatic routing -
/pipelinecommand for manual pipeline execution - Pipeline execution via command routing (commands with
pipelineconfig) - Task-based model routing (fast, code, complex, summarize)
- Model roles for provider-agnostic pipelines
-
--providerflag for pipeline execution
Remaining Work (Phase 4):
- Config hot-reload support (watch file changes)
- Cost tracking per model/pipeline
Status: Complete
Key Features (in src/orchestrate/):
- Run multiple AI agents in parallel using git worktrees
- Each worker operates in an isolated branch
- Permission requests bubble up to the commander via Unix domain sockets
- Human-in-the-loop approval for all tool operations
Architecture:
┌─────────────────────────────────────────────┐
│ Commander (has readline) │
│ ┌─────────────────────────────────────┐ │
│ │ Unix Socket Server │ │
│ │ ~/.codi/orchestrator.sock │ │
│ └──────────┬──────────────┬───────────┘ │
└─────────────┼──────────────┼───────────────┘
│ │
┌──────┴───┐ ┌─────┴────┐
│ Worker 1 │ │ Worker 2 │
│ (IPC │ │ (IPC │
│ Client) │ │ Client) │
└──────────┘ └──────────┘
Worktree A Worktree B
Implemented Commands (in src/commands/orchestrate-commands.ts):
| Command | Description |
|---|---|
/delegate <branch> <task> |
Spawn a worker agent in a new worktree |
/workers |
List active workers and their status |
/workers cancel <id> |
Cancel a running worker |
/worktrees |
List all managed worktrees |
/worktrees cleanup |
Remove completed worktrees |
CLI Flags for Child Mode:
--child-mode- Run as child agent (connects to commander via IPC)--socket-path <path>- IPC socket path for permission routing--child-id <id>- Unique worker identifier--child-task <task>- Task description for the worker
IPC Protocol:
- Newline-delimited JSON over Unix domain sockets
- Message types:
handshake,permission_request,permission_response,status_update,task_complete,task_error,ping/pong - Workers request permissions, commander prompts user, sends response back
Workflow Example:
# Start Codi (commander)
codi
# Spawn parallel workers
/delegate feat/auth "implement OAuth2 login flow"
/delegate feat/api "add REST endpoints for user management"
# Workers run in isolated worktrees
# When a worker needs to write a file:
# [feat/auth] Permission: write_file (src/auth/oauth.ts)
# Approve? [y/n]
# Monitor progress
/workers
# Shows: feat/auth (thinking), feat/api (waiting_permission)
# Results are merged when workers completeFiles:
src/orchestrate/commander.ts- Parent orchestrator, spawns/manages workerssrc/orchestrate/child-agent.ts- Agent wrapper with IPC-based onConfirmsrc/orchestrate/worktree.ts- Git worktree creation/cleanupsrc/orchestrate/ipc/protocol.ts- Message types and serializationsrc/orchestrate/ipc/server.ts- Unix socket server (commander)src/orchestrate/ipc/client.ts- Unix socket client (worker)src/orchestrate/types.ts- WorkerConfig, WorkerState, WorkerResult typessrc/commands/orchestrate-commands.ts- User-facing commandstests/orchestrate.test.ts- 14 unit tests
Tested Providers:
- ✅ Anthropic (Claude)
- ✅ Ollama (glm-4.7:cloud, qwen3-coder:480b-cloud)
- ✅ OpenAI
Status: Complete
Key Features (in src/symbol-index/):
- SQLite-based symbol index using better-sqlite3
- Regex-based symbol extraction for TypeScript/JavaScript and Kotlin
- TypeScript path alias resolution via tsconfig.json parsing
- Usage-based dependency detection
Commands:
| Command | Description |
|---|---|
/symbols rebuild |
Rebuild the symbol index |
/symbols update |
Incremental update |
/symbols stats |
Show index statistics |
/symbols search <name> |
Search for symbols |
/symbols clear |
Clear the index |
MCP Tools:
find_symbol- Find symbols by name (fuzzy search)find_references- Find where a symbol is usedget_dependency_graph- Show file dependencies
Potential Future Enhancements:
- Custom include/exclude patterns in
.codi.jsonconfig - Optional node_modules indexing for specific packages (power users)
- Symbol rename/refactor support
- Call graph tracking
What: Save and reuse code snippets.
Implementation:
- Store snippets in
~/.codi/snippets/ - Add
/snippet save <name>and/snippet use <name>commands - Support tags and search
What: Coordinated changes across multiple files.
Implementation:
- Add
/refactor-all <pattern> <description>command - Collect all matching files
- Generate coordinated edit plan
- Apply changes atomically (all or nothing)
Status: Complete
Key Features (in src/tools/run-tests.ts):
run_teststool for automatic test runner detection and execution- Supports npm, yarn, pnpm package managers
- Auto-detects test frameworks: Jest, Vitest, Mocha, pytest, go test, cargo test
- Custom command and filter support
- Timeout handling and output truncation
How It Works:
- AI calls
run_teststool (optionally with filter or custom command) - Tool detects project type and test runner from config files
- Executes tests and captures output
- Returns structured results with pass/fail status
Files:
src/tools/run-tests.ts- Test runner tool implementationtests/run-tests.test.ts- Comprehensive test coverage
Status: Complete
Key Features (in src/agent.ts):
- Smart Windowing: Automatically compacts context when token limit approached
- Semantic Deduplication: Removes duplicate/similar messages
- Summarization: Creates summaries of older messages to preserve context
- Token counting with model-specific limits
- Configurable token threshold (default 8000)
How It Works:
- Before each API call, checks if token count exceeds threshold
- If over limit, applies smart windowing algorithm
- Keeps recent messages intact, summarizes older ones
- Preserves system prompt and critical context
Implemented Commands (in src/commands/compact-commands.ts):
| Command | Aliases | Description |
|---|---|---|
/compact |
/summarize, /compress, /compression |
Show context status (default) |
/compact status |
- | Show current context size and compression status |
/compact summarize [--force] |
- | Summarize older messages to reduce context |
/compact compress [on|off|--preview] |
- | Toggle entity-based compression |
CLI Options:
-c, --compress- Enable context compression (entity normalization) at startup- Automatic compaction happens regardless of flag when needed
Status: Complete
Key Features (in src/rag/):
- Local vector database using
vectrafor embeddings storage - Automatic project indexing on startup
- Semantic code search based on query similarity
- Chunked file processing for large files
- Background indexing with progress feedback
Files:
src/rag/indexer.ts- File indexing and chunkingsrc/rag/search.ts- Semantic search implementationsrc/rag/embeddings.ts- Embedding generation (OpenAI API)- Index stored in
.codi/rag-index/
How It Works:
- On startup, indexes project files (respects .gitignore)
- Creates embeddings for code chunks
- When AI needs context, searches for relevant code snippets
- Injects relevant context into system prompt
Requirements:
- OpenAI API key (for embeddings)
- Automatic fallback if unavailable
Status: Complete
Key Features:
- Ora Spinners (
src/spinner.ts): Visual feedback during long operations - Graduated Verbosity (
src/logger.ts): Four log levels for debugging
CLI Options:
| Option | Description |
|---|---|
--verbose |
Show tool inputs/outputs with timing |
--debug |
Show API details, context info |
--trace |
Show full request/response payloads |
Log Levels:
NORMAL(default): Clean output, spinners for progressVERBOSE: Tool calls with parameters and durationDEBUG: API request/response metadata, context statsTRACE: Full payloads for debugging
Example Output (--verbose):
📎 read_file
path: "src/index.ts"
✓ read_file (523 lines, 0.12s)
Example Output (--debug):
[Context] 15,234 tokens, 12 messages
[API] Sending to claude-3-5-sonnet...
[API] Response: 234 tokens, tool_use, 1.2s
Files:
src/spinner.ts- Ora spinner manager with TTY detectionsrc/logger.ts- Level-aware logging utilitiestests/spinner.test.ts- Spinner teststests/logger.test.ts- Logger tests
For maximum impact with reasonable effort:
Git Integration - Most requested workflow improvementDONESession Persistence - Essential for longer projectsDONEWorkspace Config - Professional/team useDONEDiff Preview - Safety improvementDONEUndo System - Safety net for file changesDONECost Tracking - API usage and cost monitoringDONEPlugin System - Third-party extensions (DISABLED)DONEVision Support - Image analysis capabilitiesDONEInteractive File Selection - Fuzzy file finder (LOWER PRIORITY)PLANNEDParallel Tool Execution - Concurrent operations (LOWER PRIORITY)PLANNEDWeb Search - Search web via DuckDuckGoDONEMulti-Model Orchestration - Use cheaper models for summarizationDONEModel Map - Docker-compose style multi-model configDONE (Phases 1-3 complete)Multi-Agent Orchestration - Parallel agents with IPC permission bubblingDONESymbol Index - Code navigation enhancementsDONECode Snippets Library - Code reuse system (LOWER PRIORITY)PLANNEDMulti-file Refactoring - Coordinated changes (LOWER PRIORITY)PLANNEDTest Runner - Automated test executionDONEContext Optimization - Smart compaction and deduplicationDONERAG System - Semantic code searchDONEDebug UI - Spinners and graduated verbosityDONESecurity Model Validation - AI-powered security analysis for bash commandsDONE
Codi follows a principle of explicit consent for all file system and process operations. This includes several layers of protection:
Direct shell commands (using the ! prefix) now require explicit permission for chained commands. For example:
!ls | grep "test"will show both commands and require approval!echo "hello" && pwdwill show each command separately!command1; command2 | command3will list all three commands
The system detects command chaining through pipes (|), semicolons (;), and logical operators (&&, ||). Each command in the chain must be explicitly approved by the user.
All tool executions go through a permission system that:
- Automatically approves safe tools specified in config (
autoApprove) - Prompts for confirmation on potentially dangerous operations
- Provides pattern-based auto-approval suggestions
The bash tool includes built-in dangerous command detection with customizable patterns.
Codi supports optional AI-powered security analysis for bash commands using a local Ollama model. When enabled, commands are analyzed for security risks before user confirmation.
Configuration (in .codi.json):
{
"securityModel": {
"enabled": true,
"model": "llama3.2",
"blockThreshold": 8,
"warnThreshold": 5,
"tools": ["bash"]
}
}Behavior:
- Commands with risk score >=
blockThreshold(default 8) are automatically blocked - Commands with risk score >=
warnThreshold(default 5) show security warnings - Falls back gracefully if Ollama is unavailable
Files:
src/security-validator.ts- Core SecurityValidator classscripts/test-security-model.ts- Testing script for security models- See
docs/PLAN-security-model-validation.mdfor full documentation
There's ongoing work on gitgrip - a griptree (worktree-based parallel workspace) management tool:
- Location:
/Users/layne/Development/codi-workspace/gitgrip/ - Main Workspace:
/Users/layne/Development/codi-workspace/ - Active Griptree:
/Users/layne/Development/codi-dev/
# List all griptrees
gr tree list
# Create a new griptree
cd main-workspace
gr tree add branch-name
# Remove a griptree (WARNING: Only for test/stale gripspaces!)
gr tree remove --force test-branch-name
# Check griptree status
cd griptree-directory
gr statusALWAYS USE TEMP DIRECTORIES FOR TESTING
// ✅ CORRECT - Tests in temp directory
let tempDir = tempfile::tempdir()?;
let workspaceRoot = tempDir.path().join("workspace");
// ❌ WRONG - Tests on real workspace
let workspaceRoot = "/Users/layne/Development/codi-workspace";Never:
- Delete active gripspaces (e.g.,
codi-dev) - Run destructive commands on production workspaces
- Use production branch names for testing (
main,dev,codi-dev)
Always:
- Use unique test branch names:
test-feature-$(date +%s) - Verify with
gr tree listbefore runninggr tree remove - Test in isolated temp directories
Griptree Repository Branch Tracking (Feb 2, 2026):
- Track original branch for each repo in griptree
- Reference repos sync with upstream before worktree creation
- Worktrees created on repo's current branch (not griptree branch)
- Branch info stored in
.griptreepointer file for merge back support
See: gitgrip/docs/PLAN-griptree-repo-branches.md