bajajbot
v1.5.0
Published
Terminal AI chat client
Readme
BajajBot
A terminal AI coding assistant for any OpenAI-compatible model.
Bring your own API key, pick your model, and chat with an agent that can read, write, edit, and run code directly in your project — all from your terminal. BajajBot supports OpenRouter and custom endpoints such as Ollama, vLLM, and LM Studio, on macOS, Linux, and Windows.
npx bajajbotFeatures
- Live token streaming in a clean terminal UI (Ink + React)
- Agent tools — read/write/edit/delete files, search file contents, run shell commands, fetch web pages, load skills, and maintain a visible task plan
- Live plan board — for multi-step tasks the agent shows a ✓/▸/○ checklist above your input, updating in real time
- Skills — markdown playbooks from
.bajajbot/skills/, plus folders installed for other agents (~/.claude,~/.agents,~/.codex) - Project instructions — drop a
BAJAJBOT.mdin your repo (or~/.bajajbot/BAJAJBOT.mdfor global rules); its contents are injected into every system prompt automatically - Persistent memory — the agent saves durable facts (your prefs, project conventions) to
~/.bajajbot/memory.mdand recalls them in every future session; inspect anytime with/memory - Done notifications — replies that take 3+ seconds ring the terminal bell and pop a desktop notification (OSC 9/777, tmux-aware), so you can switch windows while it works
/btwside questions — ask "btw, why?" mid-task and get an instant aside without derailing the running agent; the status bar teaches context-aware command hints as you go/compareA/B — fire one question at two models, see answers side by side, press 1 or 2 to keep the winner into the chat history/subagentparallel research — fan out background mini-agents (/subagent summarize TODO.md | check node version | find bugs) that investigate while you keep chatting; live status chips below the chat, esc cancels the batch, finished reports fold into the chat as boxed blocks- File & image mentions — type
@src/app.tsto attach code,@error.pngto attach images for vision models, with Tab autocomplete - Risky actions require explicit confirmation with a colorized diff preview; nothing runs without your approval
- Any model, switchable mid-chat with
/model; recently-used models at top of picker; ctrl+f toggles ★ favorites (also settable via config) - Message queueing while streaming,
/retry,/undo,/export,/search - Git checkpoints — every reply auto-snapshots the project to a hidden ref (your branch/index/stash untouched); browse and restore with
/checkpoints /changes— every file the agent created/edited/deleted this session/commit— AI writes a conventional commit message from your working-tree diff; review the suggested message and file stats, press y to commit the whole tree (n regenerates, ⌃e edits the subject, esc cancels)/theme— six UI colorways (ember, ocean, matrix, rose, violet, mono), switchable live and persisted- Auto-compaction — long chats are summarized automatically instead of hitting the model's limit, with a live context meter in the status bar
- Rate-limit handling — automatic retries with backoff, honors
Retry-After, plain-English error messages - Auto-failover chain — on a rate limit, 5xx, or unreachable provider the turn automatically retries on each entry in config
fallbackModels; manage the chain interactively with/fallback(picker: arrow keys + enter, type to filter, ctrl+d removes last) or setfallbackModelsdirectly - Smart routing —
/routerules pick the model per turn: write a keyword (or/(regex)/) that matches your message, then choose its model or aprofile:; the first active match auto-routes that turn only - Prompt snippets —
/snstores named templates in your config: send a great prompt then/sn save deployto reuse it, or browse/insert with the/snpicker - Persistent todos —
/todokeeps a per-project task list in.bajajbot/todos.json; the agent reads it and can add/tick items itself via theupdate_todostool while working - Ollama auto-setup —
/ollamafinds your local Ollama server (http://localhost:11434/v1), creates a ready-to-use profile listing the installed models, and switches you to it in one shot - Command palette — press
⌃k(or/help) for a searchable command finder that filters by name and description and runs the selected command in place - Repo map +
/map— the agent's system prompt auto-includes a compact map of your project (directories, notable files, extension counts), so it navigates the tree without blind probing first;/mapshows you the same map - Session branching —
/branchforks the current chat into a diverging thread; the original stays intact, and/sessionsmarks forks (↳ fork of …) so you can switch between them - Non-interactive mode —
bajajbot -p "prompt"with piped stdin, for scripts and CI /usagedashboard +spendLimitUsdguardrail — tokens and estimated cost per session and across all chats/schedulecron prompts — register 5-field cron expressions (minute hour day-of-month month day-of-week) that run headless turns on their own sessions (add,rm,run, list)- Auto-generated session titles, first-run setup wizard that verifies your endpoint/key/model live, daily update check
- Markdown replies with syntax-highlighted code, mouse-wheel scrolling, drag-to-select copying
- Cross-platform: macOS, Linux, Windows
Quick start
Run without installing:
npx bajajbotOr install once:
npm install -g bajajbot
bajajbotOn first launch the setup wizard asks for:
- Provider — OpenRouter or a custom OpenAI-compatible endpoint
- Your API key
- API base URL
- Default model ID, for example
openai/gpt-oss-20b:free
It then verifies the endpoint, key and model against the live API before
saving. Configuration lives at ~/.bajajbot/config.json.
Command reference
CLI commands
| Command | What it does |
| --- | --- |
| bajajbot | Start a new interactive chat |
| bajajbot "fix the login bug" | New chat that auto-sends your text as the first message |
| bajajbot -c | Resume your most recent session instantly |
| bajajbot -c "run tests now" | Resume it and auto-send a follow-up message |
| bajajbot chat --resume <id> | Resume a specific saved chat |
| bajajbot sessions | Pick a saved chat from a terminal picker |
| bajajbot -p "prompt" | One-shot: run the prompt with agent tools, print the answer, exit |
| cat file \| bajajbot -p "explain" | Pipe stdin into a -p prompt |
| bajajbot usage | Print token & cost totals across all saved chats |
| bajajbot config init | Re-run the setup wizard |
| bajajbot config show | Show config (API key stays masked) |
| bajajbot config set-model <id> | Change the default model |
| bajajbot config set <key> <value> | Set an option (see table below) |
| bajajbot config unset <key> | Clear an option |
| bajajbot profile save <name> | Save current provider settings as a named profile |
| bajajbot profile use <name> | Switch to a saved profile |
| bajajbot profile list | List saved profiles |
| bajajbot profile remove <name> | Delete a saved profile |
| bajajbot logout | Delete config and all sessions |
| bajajbot --version / -h | Show version / help |
Launch flags
| Flag | Effect |
| --- | --- |
| (none) | Interactive chat |
| "text…" | Interactive chat that immediately sends your text |
| -c, --continue | Resume the newest session (combine with text to follow up) |
| -p, --print | Non-interactive one-shot mode; reads stdin when piped |
config set keys
| Key | Value | What it controls |
| --- | --- | --- |
| temperature | 0–2 (number) | Generation randomness override |
| maxTokens | positive integer | Cap on reply length |
| systemPrompt | text | Replace the built-in system prompt entirely |
| contextTokens | integer ≥ 1000 | Token budget before auto-compaction triggers (default 12000) |
| spendLimitUsd | number > 0 | Warn once when a session's estimated cost crosses this line |
| favoriteModels | comma-separated IDs | Models pinned ★ to the top of the /model picker |
| fallbackModels | comma-separated model-id | profile:<name> | Auto-failover chain for the current turn when the provider rate-limits, 5xxs, or is unreachable. A profile: entry switches provider/endpoint (e.g. your local Ollama). Order matters — first usable entry is tried first |
| checkpointLimit | integer ≥ 2 | Max git snapshots kept per project; when full, the chain restarts and old ones are reclaimed by git GC (default 300) |
| theme | theme name | UI colorway — one of ember (default), ocean, matrix, rose, violet, mono. Also switchable live with /theme |
| webSearch | object | Backend for the agent's web_search tool: { "provider": "duckduckgo" \| "brave" \| "tavily" \| "searxng", "apiKey": "...", "searxUrl": "..." } — default is keyless DuckDuckGo; Brave/Tavily need a free API key, SearXNG your instance URL |
Example:
bajajbot config set favoriteModels "openai/gpt-oss-20b:free, anthropic/claude-sonnet-4.5"
bajajbot config set spendLimitUsd 5
bajajbot config set theme ocean
bajajbot config unset temperatureSlash commands (inside chat)
| Command | Argument | What it does |
| --- | --- | --- |
| /model | optional <id> | With an ID: switch model now. Without: open a searchable picker — type to filter, recently-used models at top, ctrl+f toggles ★ favorites, Enter chooses, or type any unlisted ID into the + row |
| /skills | — | Browse every installed skill (project + global). ↑↓ select, Enter runs it immediately, esc closes |
| /checkpoints | — | Browse automatic git snapshots of your project. Enter arms a restore, enter again confirms |
| /changes | — | List files the agent created/edited/deleted this session (A/M/D color-coded) |
| /commit | — | Round up the whole working tree (git add -A), model writes a conventional message, press y to commit (n regenerates, ⌃e edits the subject, esc cancels). Requires git user.name/user.email |
| /theme | — | Pick a UI colorway (arrow keys, live preview swatches); saved to your config |
| /usage | — | Requests, tokens and estimated cost across all saved chats, with per-model breakdown |
| /schedule | — | List scheduled prompts · add <name> "<cron: minute hour dom month dow>" "<prompt>", rm <name>, run <name> |
| /btw <question> | required | Instant side question — answered in 1–2 sentences even mid-task, never enters the chat history |
| /compare <question> | required | Ask two models the same question side by side — pick the winner to keep (1 = A, 2 = B, esc = discard both) |
| /subagent <task1>, <task2>, … | required | Launch parallel background research agents — any number of tasks separated by commas, pipes, or new lines; live chips while they run, single esc cancels, finished reports fold into the chat |
| /fallback | /fallback <id> | /fallback clear | optional | Interactive picker for the auto-failover chain (models + saved profiles; enter adds, ctrl+d removes last, esc done), or add a single model ID directly, or clear the chain |
| /route | /route add "pat" <model> | /route clear | optional | Smart routing picker: toggle rules on/off, ⌃d deletes, a adds (pat = keyword or /regex/, then pick the model/profile). First match routes that turn; add/clear work without the picker |
| /sn | /sn <name> | /sn save <name> | /sn add <name> <text> | /sn rm <name> | optional | Prompt snippets: picker inserts into your input (type filters, ⌃d deletes, a adds), <name> inserts, save stores your last sent prompt, add stores inline text (\n = newline), rm removes one |
| /todo | /todo add <text> | /todo clear | optional | Persistent per-project todos: picker toggles (↵/space), deletes (⌃d), clears done (c) and adds (a); the agent updates the same list via the update_todos tool |
| /ollama | optional | Detect a running local Ollama, create the ollama profile (http://localhost:11434/v1), list installed models, and switch to the first one |
| /map | — | Print the same compact project map the agent sees (directories, notable files, extension counts) — never enters the chat history |
| /copy | — | Copy the last assistant reply to the clipboard |
| /retry | — | Regenerate the last assistant reply |
| /undo | — | Remove the last exchange and revert its file changes |
| /export | optional json | Save the chat to bajajbot-<session>.md (or .json) |
| /search <text> | required | Find text in this chat and jump between matches |
| /sessions | — | Resume a saved chat from an overlay; forks (see /branch) are marked ↳ fork of … |
| /branch | — | Fork the current chat into a diverging thread — copies messages, plan and usage; the original stays intact, and /sessions switches between the two |
| /profile | — | Switch a saved provider profile |
| /new | — | Start a fresh chat (plan board resets too) |
| /logout | — | Delete all config and sessions |
| /help | — | Open the command palette — type to filter by name or description, enter runs the command (⌃k does the same from anywhere) |
Tip: type / and use Tab / arrows — every command autocompletes.
Keyboard shortcuts
Enter Send message · confirm · run selected picker row
Esc Interrupt streaming / close dialogs / deny action / cancel armed restore
↑ / ↓ Input history, or move inside pickers & autocomplete
Tab Autocomplete slash commands and @file paths
PgUp / PgDn Scroll chat history (mouse wheel works too)
Home / End Jump to top / return to latest
Ctrl+C Exit (shows the resume command for the session)
y / n Allow / deny a risky tool confirmation
f Pin or unpin ★ the highlighted model inside /modelWhile the assistant is streaming you can keep typing — press Enter to queue messages; they send automatically when the reply finishes.
How features work
Agent tools
The assistant can call these tools on your project:
| Tool | What it does | Confirmation |
| --- | --- | --- |
| read_file | Read a text file | No |
| list_dir | List a directory | No |
| search_files | Regex-search file contents across the tree (skips node_modules/.git/binaries, smart-case) | No |
| write_file | Create or overwrite a file | Yes — diff shown |
| edit_file | Replace an exact snippet in a file | Yes — diff shown |
| delete_path | Permanently delete a file or directory | Yes |
| run_command | Run a shell command (bash/cmd) | Yes |
| fetch_url | Fetch a web page or API endpoint | Yes |
| list_skills / load_skill | Discover and follow skill playbooks | No |
| set_plan | Maintain the live task plan board | No |
Every risky action shows a confirmation prompt — y allows, n/Esc denies.
Edits preview a colorized unified diff before you approve. Paths accept
relative, absolute, and ~/… forms; writing outside the project is allowed
but always confirmed. The last exchange's changes can be reverted with
/undo (deleted directories up to 500 files / 1 MB restorable).
Plan board
Ask for anything multi-step ("add dark mode to this app") and the agent calls
set_plan with its steps. The board above your input shows:
plan 1/3
✓ inspect current theming
▸ add theme toggle state
○ wire stylesIt updates live while streaming, persists with the session (survives resume),
and clears on /new. In -p print mode plans are simply skipped from output.
File & image mentions (@path)
Prefix any path with @ in your message:
explain what @src/tools/fs.ts does
refactor both @src/ui/App.tsx and @bin/bajajbot.ts
what does this error screen show? @error.png- Typing
@opens a live path autocomplete (debounced, cached); Tab completes step by step through folders - Only tokens resolving to existing files attach — stray
@mentionsare ignored - Text files travel as fenced code blocks (60k char cap each); the chat display stays short
- Images (
.png.jpg.jpeg.gif.webp) are sent as real vision parts, base64 inline, 4 MB cap each — needs a vision-capable model via/model
Project instructions (BAJAJBOT.md)
Teach bajajbot your project's rules once — it applies them to every reply:
# BAJAJBOT.md
- Package manager: pnpm only, never npm
- Never edit /legacy — generated code
- Run `pnpm lint` after any edit
- Commit style: conventional commitsSave it as BAJAJBOT.md in the project root (or .bajajbot/BAJAJBOT.md).
Global rules live in ~/.bajajbot/BAJAJBOT.md and apply everywhere (project
rules are appended after global ones). Contents are re-read on every message,
so edits apply immediately; a startup note confirms when a project file is
picked up. 8k character budget, truncated safely.
Persistent memory
The agent remembers across sessions. When it learns something durable — your
editor preference, the deploy target, "tests always run with vitest" — it
saves a fact with its memory tool, and every future session starts with
those facts already in context. Facts live in ~/.bajajbot/memory.md
(200-fact cap, newest win, duplicates ignored). Browse what it knows with
/memory; the agent can remove entries on request ("forget the fly.io
fact").
Skills
A skill is a markdown playbook:
---
description: Ship the app to production
---
# Deploy
1. Run `npm test`
2. `npm run build`
3. `npm run deploy` and watch the health checkWhere skills are loaded from (first match wins on name conflicts):
<project>/.bajajbot/skills/*.mdand<project>/.claude/skills/~/.bajajbot/skills/*.md- Agent-standard folders:
~/.claude/skills/<name>/SKILL.md,~/.agents/skills/,~/.codex/skills/
The agent sees names + descriptions in its system prompt and loads full
instructions with load_skill when your request matches. Use /skills to
browse everything installed and run one immediately.
Git checkpoints & session changes
After every reply BajajBot snapshots the whole working tree to the hidden
ref refs/bajajbot/checkpoints using git plumbing only (a temporary index) —
your branch, staging area, stash and commit history are never touched. Works
even in repos with zero commits; silently skips non-git directories.
/checkpointslists snapshots newest-first with your prompt as the label; restoring overwrites files with their snapshot contents (files created after the snapshot are left alone)/changesdiffs the first vs latest snapshot to list exactly what the agent did this session- Snapshots are a rolling window: once
checkpointLimit(default 300) is reached, the chain restarts and git's garbage collection reclaims the oldest ones — no unbounded growth
Usage tracking & cost guardrails
- Every reply records requests/prompt/reply tokens and estimated cost onto the session (OpenRouter pricing)
/usage(in chat) andbajajbot usage(CLI) roll totals up across all saved chats with a top-models breakdownconfig set spendLimitUsd <n>warns once per session when accumulated cost crosses the line
Context meter & auto-compaction
The status bar shows how full the model's context budget is: dim normally,
yellow at ≥70%, red at ≥90%. Past the budget (config set contextTokens,
default 12000), older turns are AI-summarized into a single bridge message and
the conversation continues seamlessly — you'll see ✓ Compacted N older
message(s).
Rate limits & errors
Free models throttle fast. On 429/5xx BajajBot retries automatically (backoff
- provider
Retry-After, up to 3 tries, abortable with Esc) and shows⚠ rate limited — retrying in 5s (attempt 1/3)in the status bar. Errors come back in plain English: bad key → "runbajajbot config init", out of credit (402), unknown model (404), etc.
Copying messages
- Drag with the left mouse button over chat text — highlights while dragging, copies on release (OSC 52, works over SSH; falls back to
pbcopy/wl-copy/xclip/clip) /copycopies the last assistant reply without touching the mouse- Hold Shift while dragging for your terminal's native selection
Providers
| Provider | Base URL example | Model example |
| --- | --- | --- |
| OpenRouter | https://openrouter.ai/api/v1 | openai/gpt-oss-20b:free |
| Ollama | http://localhost:11434/v1 | llama3.2 |
| vLLM / LM Studio | Your server's /v1 endpoint | Your served model ID |
Any OpenAI-compatible /v1 endpoint works.
Data on disk
Everything lives under ~/.bajajbot/ (Windows: %USERPROFILE%\.bajajbot):
~/.bajajbot/
├── config.json settings, profiles, favorites (0600 permissions)
├── sessions/*.json every chat: messages, plan, usage totals
├── skills/ your global skills (*.md)
└── last-update-check marker for the daily npm update checkNothing is synced anywhere; messages go only to the endpoint you configure.
Troubleshooting
- "API key rejected (401)" — run
bajajbot config initand paste a fresh key - Rate limited constantly — free models allow only a few requests per minute/day; wait or switch models with
/model - Config corrupted (e.g. stray characters edited into
config.json) — BajajBot tells you the exact fix: repair the file or delete it and re-runbajajbot config init - Image mention fails — switch to a vision-capable model with
/model - Checkpoints empty — they need a git project and at least two replies
Upgrading
Installed from npm:
npm update -g bajajbot
npm install -g bajajbot@latest # or pin explicitly
npx bajajbot@latest # always newest without installingBajajBot also checks npm once a day and prints a one-line notice at startup when a newer version exists.
From a local clone:
git pull && npm install && npm run build && npm install -g .
bajajbot --version # verify what's runningDevelopment
Requires Node.js 18+.
git clone <your-repository-url>
cd bajajbot
npm install
npm run build # type-check + compile to dist/
npm test # build + run the test suite
npm run dev # run from source with tsx
npm run stream # one-shot prompt without the TUIProject layout
bin/bajajbot.ts CLI entry (commander): -p, -c, positional prompts
src/config/ Config types, constants, load/save (~/.bajajbot)
src/provider/ OpenAI-compatible client (SSE streaming), retries, model list
src/tools/ Agent tools: fs, search, shell, web, skills, plan, git checkpoints
src/session/ Session model, history storage, compaction, usage aggregation
src/commands/ CLI commands (chat, config, sessions, usage, print mode)
src/ui/ Ink components: App, pickers, overlays, plan board, markdown
src/util/ Attachments, diffs, update checks, small helpers
test/ node:test suitesPublish to npm
npm login
npm version patch # bumps version and creates a git tag
npm run build
npm test
npm pack --dry-run # inspect the package contents
npm publishLicense
Choose and add a license before publishing.
Author
Sahil Bajaj — [email protected]
