An open-source, self-hosted agent manager, inspired by Google Antigravity.
Point an agent (Claude, GPT, Gemini, Grok, Perplexity, OpenRouter, or local Ollama — or let Ursa
route each turn to the best of them) at a folder and watch it plan, run tools, and produce
reviewable diffs — with a full agent-loop spine: rules, skills, workflows, hooks, plugins,
memory, and sandboxing, all on your machine.
Quick Start · Meet Ursa · Meet Ursus · Features · The .agents Spine · Architecture
Agent-manager tools like Google Antigravity are compelling but closed — you don't control the runtime, can't see how the agent loop actually works, and can't run it against your own infrastructure. BearCode is what you get if you decide that spine should be yours: same repo, same model keys, same threat model, fully inspectable.
It takes inspiration from Antigravity's core idea — a .agents/ directory as the durable,
file-based contract between you and the agent — instead of hiding that contract behind a SaaS. Rules,
skills, and workflows live as plain files your agent reads; hooks fire on tool-lifecycle events;
plugins bundle all of the above from a git marketplace; every run is sandboxed with a macOS
Seatbelt profile so a run_command call can't touch what it shouldn't. The agent runtime itself is
codenamed ursa.
Open a folder --> Agent reads .agents/ --> You chat / it edits --> Hooks + Sandbox gate every tool call --> Review the diff
- Open a project folder. The folder is the project — no separate project abstraction, no
import step. Settings, trust, and
.agents/config are all keyed to the path. - The agent loads its spine: project + global rules, available skills, saved workflows,
registered MCP connectors, and installed plugins, all sourced from
.agents/. - You converse. The agent reasons, edits files, runs commands, browses the web, and reports back — with live diffs, a review panel, and full conversation history.
- Every tool call is gated. PreToolUse/PostToolUse hooks can observe, block, or inject. Shell commands run inside a per-project macOS Seatbelt sandbox unless explicitly trusted.
- You review and merge. Worktree mode isolates risky changes on a branch with a built-in merge/conflict resolver; nothing lands until you say so.
Stop picking models. Pick Ursa.
Ursa is BearCode's cross-provider model router — the top entry in the model picker. Select it once, and every turn a fast classifier reads your message and routes it to the best model for the job, across providers:
| Role | When your message is… | Ursa routes to |
|---|---|---|
| 🏛️ Architect | planning, deciding, or designing before building | Claude Opus 4.8 |
| 🔨 Coder | anything whose deliverable is code or files — any size | GPT-5.6 Sol |
| 🔍 Reviewer | review, critique, or verification of existing work | Claude Sonnet 5 |
| 🔎 Verifier | fact-checks and current-info lookups against the live web | Sonar Pro |
| ⚡ Grunt | quick, routine, mechanical asks | GPT-5.6 Luna |
One conversation can flow through all five — plan with Opus, build with GPT, review with Sonnet, verify with Sonar — without you touching the picker again.
How it's built:
- Curated, not configurable. Like the orchestrators in Perplexity and Cursor, the role → model assignments are product decisions maintained in code — Settings → Ursa is just an enable toggle plus a live check that the required provider API keys are present.
- Degrades gracefully. Roles whose provider has no key are skipped; if the classifier itself fails, Ursa falls back to the first eligible role instead of erroring your turn.
- Crash-safe. The resolved model is persisted per turn, so resuming a conversation never re-rolls the routing mid-task.
- Transparent. Every assistant turn records which role ran it (hover an assistant message for the badge), and the composer picks up a slow-rotating aura in BearCode blue so you always know Ursa is at the wheel.
- Subagents route too. While Ursa drives the turn, the researcher subagent rides the Reviewer's model and the browser subagent rides the Grunt's — no separate picker, same key-availability fallback.
- Pipeline mode. When your message is really several jobs in one ("plan it, then build it, then have someone review it"), the classifier can propose a short sequential pipeline — 2 to 4 role-tagged steps, each running on its own role's model, one after another. Ursa always asks first: you see the full plan before anything runs, and nothing executes until you approve. Say no and the turn just falls back to the normal single-role path — no pipeline, no partial work.
Modes. Every Ursa conversation is also in one of three modes, picked per-conversation from the composer (next to the model picker, where the effort selector lives for non-Ursa models):
- Code — the default. Every turn is classified fresh and routed to whichever role fits it best, exactly as described above (the classifier can propose a pipeline here too).
- Council — three models (GPT-5.6 Sol, Gemini 3.1 Pro, Grok 4.5) answer your question independently (no agent tools, but each with live server-side web search), anonymously peer-review each other's answers, and Fable 5 chairs the panel — reading every answer and review to synthesize the final response you see.
- Deep Research — a three-step pipeline: Sonar Pro searches the live web for facts and sources, Claude Opus 4.8 analyzes the findings for gaps and follow-ups, and Claude Sonnet 5 writes the final citation-backed report. Requires a Perplexity API key.
Everything Ursa does — without the frontier price tag.
Ursus is Ursa's sibling router, sitting right below it in the model picker. Same mechanism, same modes, same pipelines, same subagent routing — the only difference is which models fill the seats. Ursus stays entirely on OpenRouter and local Ollama, so no frontier-lab API key is required:
| Role | When your message is… | Ursus routes to |
|---|---|---|
| 🏛️ Architect | planning, deciding, or designing before building | Ornith-1.0 35B (local) |
| 🔨 Coder | anything whose deliverable is code or files — any size | Kimi K3 |
| 🔍 Reviewer | review, critique, or verification of existing work | GLM 5.2 |
| 🔎 Verifier | fact-checks and current-info lookups against the live web | DeepSeek V4 Pro |
| ⚡ Grunt | quick, routine, mechanical asks | MiniMax M3 |
Everything described under Meet Ursa — curated roles, graceful degradation, crash-safe per-turn persistence, role badges, subagent routing, and consent-gated pipelines — applies identically here. The composer picks up the same slow-rotating aura, in Ursus's light blue.
Modes work the same way, with Ursus's own models:
- Code — the default; every turn classified fresh and routed to the best-fitting role.
- Council — Kimi K3, GLM 5.2, and MiniMax M3 answer independently and anonymously peer-review each other, with DeepSeek V4 Pro chairing the synthesis.
- Deep Research — DeepSeek V4 Pro searches the live web (via OpenRouter's web-search server tool), Ornith-1.0 analyzes the findings, and GLM 5.2 writes the citation-backed report. Requires an OpenRouter API key.
Note. Ursus trades frontier-model quality for cost and local control. In side-by-side testing it is noticeably more prone to asserting unverified specifics than Ursa, and less inclined to check its own work — turn Web Search on for anything fact-sensitive, and prefer Ursa when accuracy matters more than spend.
Requirements. An OpenRouter API key covers four of the five roles. The Architect additionally
needs Ollama running locally with ornith:35b pulled; without it that role
is skipped and the other four still route normally. Enable Ursus in Settings → Ursus.
- Ursa dynamic model routing: a cross-provider orchestrator entry in the model picker that classifies each turn and routes it to the right model for the job — see Meet Ursa
- Ursus routing: the same router, the same three modes, restricted to OpenRouter + local Ollama models for a no-frontier-key setup — see Meet Ursus
- Multi-provider model support: Anthropic, OpenAI, Google, xAI, Perplexity, OpenRouter, and local Ollama — switch mid-conversation, set per-project defaults, add custom models and context windows. Includes Grok 4.20 Multi-Agent, where the effort picker maps to the model's parallel agent count (up to 16)
- Web Search toggle: per-conversation server-side web search (under the effort picker, next to
Thinking) for Anthropic, OpenAI, and xAI models — Grok gets both
web_searchandx_search. Off by default (searches are billed per use); Perplexity models are always-on by nature. Results land as inline citation chips plus a Sources list on the turn - LangGraph.js + Deep Agents orchestrator running alongside the legacy
ursaengine behind a feature flag, so the runtime can evolve without breaking existing conversations - Live diffs and a review panel for every file the agent touches, plus Monaco-powered code and diff viewers
- Context usage & cost tracking: real token counts per turn, a per-model cost breakdown, and live LiteLLM price sync
- Voice input: OpenAI Whisper (cloud) or fully local/offline speech-to-text
- Sandboxed browser tool: a
WebContentsView+ Playwright-CDP browser the agent can drive directly, gated by the same trust/consent model as everything else
- Rules: project + global markdown instructions the agent always has in context
- Skills:
SKILL.md-folder capabilities the agent activates on demand or via@skillmention, plus a/learnflow to capture new skills from a conversation - Workflows: saved, repeatable multi-step procedures
- Hooks:
hooks.json-configuredPreToolUse/PostToolUsecommand handlers that observe, block, or inject at tool-lifecycle boundaries — JSON stdin/stdout contract, global + per-project config, trust-gated before anything runs - Memory: durable, file-based agent memory with a secure-by-default load policy
- Plugins: git-marketplace bundles that install rules, skills, MCP connectors, and hooks in one shot — shallow-clone install, an inert review card before anything activates, folder-URL parsing, plugin-provided MCP servers untrusted by default
- MCP connector manager: discover, enable, and trust Model Context Protocol servers, including full OAuth (loopback + system-browser flows)
- GitHub / Bitbucket integrations: device-code + PAT for GitHub, app-password for Bitbucket
- Smithery registry browsing for one-click MCP install alongside local discovery
- Per-project Sandbox Mode: macOS Seatbelt (SBPL) isolation for
run_command— deny-default, environment scrubbing, kernel-enforced, with an explicitunsandboxed()escape hatch that requires approval - Project trust model: outside-access prompts, a trust banner for anything touching paths outside the project, and consent gates on hook execution
- Secrets vault: provider keys stored in a vault, never logged, never written to
.agents/
- Worktree mode: isolate risky agent work on its own git branch/worktree, with grouping and a built-in merge + conflict resolver
- Full conversation history, pin/archive, rename, and per-conversation model, effort/mode, thinking, and web-search picking
- Appearance system: Dark / Light / System / Custom themes, four bundled extras, all token-driven
- A shared UI primitive system (
Popover,Menu,EmptyState,Loading,ErrorCard,FieldHint,Hint) — every dropdown, empty state, and form hint in the app is one of these, never hand-rolled. See CLAUDE.md for the full "use this, never that" table. - A full motion system: transform/opacity-only animation,
prefers-reduced-motionfallbacks everywhere, FLIP-based sidebar transitions,@starting-styleenter/exit animations
| Layer | Technology |
|---|---|
| Shell | Electron 39 · electron-vite · electron-builder (macOS-first) |
| UI | React 19 · TypeScript strict · Zustand · Monaco Editor |
| Agent runtime | LangChain.js · LangGraph.js · deepagents (sole engine — the earlier Vercel AI SDK-based loop was retired) |
| Model providers | @langchain/anthropic · @langchain/openai · @langchain/google-genai · @langchain/ollama · xAI · OpenRouter · Perplexity |
| Browser tool | Playwright · Electron WebContentsView + CDP |
| Storage | better-sqlite3 (conversations, settings, trust) |
| Documents | pdf-lib · unpdf · mammoth · docx · exceljs |
| Sandboxing | macOS Seatbelt (SBPL) via sandbox-exec |
| Tests | Vitest · Testing Library |
+-------------------+
| Renderer (React) |
| Zustand store |
+---------+---------+
| typed IPC (BearcodeApi)
+---------+---------+
| Main (Node) |
| orchestrator / |
| ursa engine |
+---------+---------+
|
+---------+---------+---------+---------+---------+
| | | | | |
+----+---+ +---+----+ +--+-----+ +-+------+ +-+------+ +---+----+
|agentsDir| | mcp | | plugins| | hooks | | sandbox| | db |
| rules/ | | connect| | market | | Pre/ | | Seatbelt| | sqlite|
| skills/ | | -ors + | | -place | | Post- | | isolate | | conv/ |
| workflow| | OAuth | | bundles| | ToolUse| | run_cmd | | trust |
+---------+ +--------+ +--------+ +--------+ +---------+ +-------+
The renderer never talks to a provider, the filesystem, or a shell directly — every capability is
exposed through the typed bearcode:* IPC surface, and every write into .agents/ or a project
folder is path-jailed in the main process.
Prerequisites:
- macOS
- Node.js 20+
- API keys for whichever model providers you want (Anthropic, OpenAI, Google, xAI, Perplexity, OpenRouter) — or Ollama running locally for a fully offline setup
Setup:
# Clone
git clone https://github.com/umzcio/BearCode.git
cd BearCode
# Install dependencies
npm install
# Launch in dev mode
npm run devOn first launch, open Settings → Providers and add your API key(s), then open a folder to start your first project.
npm run typecheck # tsc --noEmit, node + web projects
npm test # Vitest
npm run lint # eslint --cache .npm run build:macBearCode/
├── src/
│ ├── main/ # Electron main process (Node)
│ │ ├── agentsDir/ # rules/skills/workflows parsing + trust
│ │ ├── hooks/ # hooks.json loader, runner, PreToolUse/PostToolUse wrap
│ │ ├── mcp/ # MCP connector discovery, OAuth, registry
│ │ ├── plugins/ # git-marketplace install, manifest validation
│ │ ├── skills/ # skill state + enable/disable
│ │ ├── orchestrator/ # LangGraph engine + sandbox + tool implementations
│ │ ├── worktree/ # git worktree mode + merge/conflict resolver
│ │ ├── db/ # sqlite: conversations, trust, project settings
│ │ └── ipc.ts # the full bearcode:* IPC surface
│ ├── preload/ # typed IPC bridge (BearcodeApi)
│ └── renderer/
│ └── src/
│ ├── components/
│ │ ├── ui/ # shared primitives: Popover, Menu, EmptyState, ...
│ │ ├── Settings/ # Providers, Models, Plugins, Hooks, MCP, Skills, Rules
│ │ ├── ProjectSettings/
│ │ └── Sidebar/, History/, Browser/, Composer/, ...
│ ├── lib/ # anchorRect, usePopoverPosition, validators, useAnimatedUnmount
│ └── styles/tokens.css # motion + design tokens
└── electron-builder.yml
Out of scope for v1, on the path for future versions:
- Sidecars: long-running background agent processes (deferred in favor of shipping the core loop first)
- Discoverable skills catalog: a browse/install experience for community skills, beyond the current plugin-bundled skills
- Domain network allowlisting: a proxy-based allowlist for sandboxed
run_commandnetwork access (currently sandbox network policy is coarse-grained) - Docker sandbox backend: an alternative to Seatbelt for non-macOS platforms
- Per-project connectors & skills UI: surfacing project-scoped MCP connectors and skills directly in Project Settings
- Windows / Linux support: the app currently targets macOS only
See CONTRIBUTING.md for local dev setup, the build/lint/test gate, and PR guidelines.
MIT — open source, self-host freely.
"The agent should read the same files you do."