An agentic coding tool that lives in your terminal.
Bring your own model, plug in your credentials, and let it read, write, and execute.
Documentation · Quick Start · CLI Reference
CaretForge is a BYOM (Bring Your Own Model) coding agent CLI — similar in spirit to Claude Code, but open-source and provider-agnostic. You bring your own model credentials, and CaretForge gives you an agentic coding assistant in your terminal that can:
- Read files in your codebase
- Write and create files (with permission)
- Execute shell commands (with permission)
- Stream responses in real-time
- Use any model via pluggable providers (Azure OpenAI, Azure Anthropic, and more)
What it is: A coding assistant CLI you control — your models, your credentials, your rules.
What it is not: A hosted service, a proprietary model wrapper, or a copy of any existing tool.
- Node.js 20+
- pnpm 9+
git clone https://github.com/walidabualafia/caretforge.git
cd caretforge
pnpm install
pnpm build
pnpm link --global # makes 'caretforge' available everywherecaretforge config initEdit ~/.config/caretforge/config.json with your provider credentials. For example, with Azure Anthropic (Claude):
{
"defaultProvider": "azure-anthropic",
"providers": {
"azureAnthropic": {
"endpoint": "https://YOUR-RESOURCE.openai.azure.com/anthropic",
"apiKey": "your-api-key",
"models": [{ "id": "claude-opus-4-6" }]
}
}
}caretforge doctorcaretforge # interactive chat
caretforge "explain this project" # one-shot taskCaretForge works just like Claude Code — run it with no arguments for interactive mode, or pass a task directly:
caretforge # start chatting
caretforge --model gpt-4.1 # use a specific model
caretforge --provider azure-foundry # use a specific providerInside the REPL, you have slash commands:
| Command | Description |
|---|---|
/help |
Show available commands |
/model |
List models from all providers |
/model <id> |
Switch model mid-conversation |
/clear |
Clear conversation history |
/compact |
Trim older messages from history |
/exit |
Exit CaretForge |
/quit |
Exit CaretForge (alias) |
You can also type exit, quit, or q without the slash to leave the REPL.
Reference files directly in your prompts using the @ prefix:
> Explain @src/core/agent.ts
> Compare @package.json and @tsconfig.json
Tab-completion is supported — press Tab after @ to see available files. Files in your working directory are indexed on startup with a comprehensive governance model: .gitignore rules are respected (via git ls-files), binary files are detected and skipped, symlinks are followed safely, files over 1 MB are excluded, and a 10-second timeout prevents stalls. You can add a .caretforgeignore file for custom exclusions. File sizes are shown during interactive browsing.
caretforge "Refactor the auth module"
caretforge "List all TODO comments" --json
echo "Fix the bug in server.ts" | caretforge runWhen the agent wants to write a file or run a shell command, you'll be prompted:
⚡ Write to src/utils.ts
Allow? [y]es / [n]o / [a]lways
- y — allow this one time
- n — deny (the agent will adapt)
- a — allow all future calls of this type for the session
To skip prompts entirely, use the auto-approve flags:
caretforge --allow-write # auto-approve file writes
caretforge --allow-shell # auto-approve shell execution
caretforge --allow-write --allow-shell # full autonomycaretforge run "List all TODO comments" --jsonCaretForge supports multiple providers through a pluggable interface:
| Provider | Models | Status |
|---|---|---|
azure-anthropic |
Claude Opus, Sonnet, etc. | Ready |
azure-foundry |
GPT-4o, GPT-4.1, Kimi K2.5 | Ready |
azure-responses |
gpt-5.2-codex, codex-mini | Ready |
azure-agents |
Azure AI Agent Service | Preview |
- Create
src/providers/myProvider.tsimplementing theProviderinterface - Register it in
src/cli/shared.ts - Add a Zod config schema in
src/config/schema.ts - Document it
| Flag | Description | Default |
|---|---|---|
--provider |
Provider name | from config |
--model |
Model ID | from config |
--stream |
Enable streaming output | true |
--no-stream |
Disable streaming | — |
--json |
Structured JSON output | false |
--trace |
Verbose debug logging | false |
--allow-shell |
Auto-approve shell execution | false |
--allow-write |
Auto-approve file writes | false |
| Command | Description |
|---|---|
| (none) | Interactive chat (default) |
"task" |
One-shot task execution |
chat |
Interactive chat (explicit) |
run <task> |
One-shot task execution (explicit) |
model list |
Show configured models |
config init |
Create configuration file |
config show |
Display config (secrets redacted) |
doctor |
Validate config and diagnose issues |
CLI flags > Environment variables > Config file > Defaults
| Variable | Maps to |
|---|---|
CARETFORGE_DEFAULT_PROVIDER |
defaultProvider |
CARETFORGE_AZURE_ENDPOINT |
providers.azureFoundry.endpoint |
CARETFORGE_AZURE_API_KEY |
providers.azureFoundry.apiKey |
CARETFORGE_AZURE_AUTH_MODE |
providers.azureFoundry.authMode |
| Platform | Path |
|---|---|
| macOS / Linux | ~/.config/caretforge/config.json |
| Windows | %APPDATA%\caretforge\config.json |
- Session disclaimer. Every time you start CaretForge, a disclaimer is displayed and you must accept before proceeding. Acceptance is never cached to disk.
- Permission prompts by default. Write and shell tools require explicit user approval per action (or
--allow-write/--allow-shellto auto-approve). - Command safety analysis. Shell commands are classified into risk tiers (safe, mutating, destructive, blocked). Destructive commands always prompt — even with
--allow-shell. Blocked commands (e.g.,rm -rf /, fork bombs) are denied outright. - File indexing governance. The
@file context system respects.gitignore, detects binary files, enforces size limits, handles symlinks safely, and supports.caretforgeignorefor custom exclusions. - Secrets are never printed in full. The
config showcommand and logs use redaction (first 4, last 2 characters). config initdoes not write API keys unless you pass--with-secrets.- Never commit your config file with secrets. Use environment variables in CI/CD.
src/
├── cli/ # Command definitions (Commander.js)
│ ├── index.ts # Program setup, global flags
│ ├── chat.ts # Interactive chat REPL
│ ├── run.ts # One-shot task execution
│ ├── model.ts # Model listing
│ ├── configCmd.ts# Config init/show
│ ├── doctor.ts # Diagnostic checks
│ └── shared.ts # Provider resolution
├── core/ # Agent loop and prompts
│ ├── agent.ts # Agent loop with tool dispatch + permissions
│ ├── messages.ts # Message factory helpers
│ └── prompts.ts # System/user prompt templates
├── providers/ # Provider abstraction
│ ├── provider.ts # Provider interface + shared types
│ ├── azureAnthropic.ts # Azure Anthropic (Claude) provider
│ ├── azureFoundry.ts # Azure OpenAI provider
│ ├── azureResponses.ts # Azure OpenAI Responses API provider
│ └── azureAgents.ts # Azure AI Agent Service provider
├── config/ # Configuration management
│ ├── schema.ts # Zod schemas + types
│ ├── paths.ts # Platform-aware config paths
│ └── index.ts # Load/save/init, env var merging
├── tools/ # Tool definitions and executors
│ ├── schema.ts # Tool JSON schemas for function calling
│ ├── readFile.ts # File reading
│ ├── writeFile.ts# File writing
│ ├── execShell.ts# Shell execution
│ └── index.ts # Tool dispatcher
├── safety/ # Command & path safety analysis
│ └── commandSafety.ts # Risk-tier classification
├── ui/ # Terminal UI
│ ├── format.ts # Colors, tool display, banners
│ ├── permissions.ts # Interactive permission prompts
│ ├── disclaimer.ts # Session acceptance prompt
│ └── fileContext.ts # @file indexing, completion, expansion
└── util/ # Shared utilities
├── logger.ts # Pino logger
├── errors.ts # Error classes
└── redact.ts # Secret redaction
- Claude Code-style UX:
caretforgealone starts interactive mode;caretforge "task"runs a one-shot task. Permission prompts appear inline.@filereferences expand into file content context. - Provider interface: All providers implement
listModels(),createChatCompletion(), andcreateStreamingChatCompletion(). - Permission model: The model always knows about all tools. Permission is checked at execution time, not tool selection time. Users approve per-action or use flags to auto-approve.
- Agent loop: Messages go to the model → tool calls are executed → results are fed back → loop until text response (max 20 iterations).
- Streaming via SSE: Providers parse Server-Sent Events for real-time token output.
pnpm install # install dependencies
pnpm build # compile TypeScript
pnpm test # run tests
pnpm test:watch # tests in watch mode
pnpm lint # lint with ESLint
pnpm format # format with Prettier
pnpm typecheck # type-check without emittingContributions are welcome! See CONTRIBUTING.md for setup instructions, development workflow, and PR guidelines.
