{"id":"36371467-4a36-4469-a709-9466f22d55a8","slug":"carlos","kind":"mcp","name":"carlos","summary":"BYOK coding and research agent. Obsidian-compatible markdown wiki as a baked-in memory system. Isolate work from life using frames.","owner":"georgebuilds","repoUrl":"https://github.com/georgebuilds/carlos","license":"GPL-3.0","licenseTier":"strong-copyleft","trust":"community","stars":3,"match":null,"fewStars":true,"format":"mcp","createdAt":"2026-06-05T23:08:48.000Z","addedAt":"2026-10-21T09:05:03.757Z","logoUrl":"https://avatars.githubusercontent.com/u/126706069?u=1ff4aeb46ed5af7a02495381d16ff04bd5ded5b4&v=4","linkOnly":false,"collection":null,"skillPath":null,"categories":["files-documents","developer-tools","memory-knowledge"],"tags":["ai-agent","anthropic","bubbletea","claude-code","coding-agent","golang","llm","obsidian"],"runtime":"go","local":true,"cloudCapable":false,"cloudCapability":"unknown","cloudReadyOnPlatform":false,"needsApiKey":false,"reviewed":false,"syncedAt":"2026-10-23T00:05:03.066Z","sample":false,"url":"https://conduits.dev/tools/carlos","language":"Go","transports":["stdio"],"install":{},"requirements":{"env":[],"upstreamMayCharge":false},"tools":null,"readme":"<p align=\"center\">\n  <img src=\"docs/branding/carlos-portrait.png\" alt=\"carlos\" width=\"160\">\n</p>\n\n# carlos\n\n<p align=\"center\">\n  <a href=\"https://codecov.io/gh/georgebuilds/carlos\"><img src=\"https://codecov.io/gh/georgebuilds/carlos/graph/badge.svg?branch=main\" alt=\"coverage\"></a>\n</p>\n\nA pure-Go TUI agent. Single binary around 25 MB. No CGO. Cross-compiled for darwin + linux × amd64 + arm64.\n\nMarketing copy and feature tour live at [georgebuilds.github.io/carlos](https://georgebuilds.github.io/carlos/). This README is for getting carlos running and for Go developers who want to contribute.\n\n---\n\n## Quick start\n\n### Install\n\n```\nbrew install georgebuilds/tap/carlos\ncarlos\n```\n\nOr grab a tarball from [Releases](https://github.com/georgebuilds/carlos/releases) and drop `carlos` into your `$PATH`.\n\n### First run\n\nOnboarding takes ~30 seconds:\n\n1. Your name\n2. A provider (Anthropic, OpenAI, OpenRouter, Ollama, or Gemini) and an API key\n3. A model from a curated dropdown (OpenRouter shows live pricing)\n4. Whether to enable the background daemon (scheduled runs, gateway delivery)\n5. Optional Obsidian vault path\n\n<p align=\"center\">\n  <img src=\"docs/branding/screenshots/onboarding-name.png\" alt=\"carlos onboarding step 1: 'What should I call you?' with 'Boss' typed in\" width=\"640\">\n</p>\n\nEverything lands in `~/.carlos/config.yaml` (mode 0600). Re-enter any single screen later with `carlos onboard --only providers` (or `models`, `daemon`, `gateway`, etc.).\n\nAfter onboarding you're in the chat TUI. Type a question. carlos answers, calls tools when needed (prompting for the risky ones), and keeps the transcript in a SQLite event log at `~/.carlos/state.db`.\n\n<p align=\"center\">\n  <img src=\"docs/branding/screenshots/chat-greeting.png\" alt=\"carlos chat TUI on first open, greeting 'Hey Boss - what are we working on?'\" width=\"640\">\n</p>\n\n### Keys worth knowing\n\n| Key | What |\n|---|---|\n| `Ctrl+F` | open the frame switcher |\n| `/help` | full slash-command list |\n| `!<cmd>` | run a shell command in your context |\n| `/agents` | open the sub-agent manage view |\n| `/whoami` | current frame, mode, provider, model |\n| `/permissions` | layered approval state + audit log |\n| `/mcp` | list configured MCP servers and their tools |\n\n#### Demo: the user-shell\n\nA `!`-prefixed line runs in your context without leaving the chat. Enter runs it in the foreground; `Ctrl+Z` pushes a running job to the background; `Ctrl+J` opens the jobs overlay (`j`/`k` to navigate, `d` to cancel, `Esc` to close). The slash variants are `/shell <cmd>`, `/bg`, and `/jobs`. A background job can also outlive the session entirely: `carlos run \"<cmd>\"` hands it to the daemon, and `carlos jobs` / `carlos attach <id>` / `carlos logs <id>` / `carlos stop <id>` drive it from anywhere.\n\n<!-- Demo GIF: record on a real terminal with `vhs demos/usershell-jobs.tape`\n     (it writes docs/branding/screenshots/usershell-jobs.gif), then uncomment:\n<p align=\"center\">\n  <img src=\"docs/branding/screenshots/usershell-jobs.gif\" alt=\"carlos user-shell: !ls -la runs in the foreground, !sleep moves to the background, and Ctrl+J opens the jobs overlay\" width=\"720\">\n</p>\n-->\n\nThe recording is scripted in [`demos/usershell-jobs.tape`](demos/usershell-jobs.tape); regenerate it with `vhs demos/usershell-jobs.tape` (requires [charmbracelet/vhs](https://github.com/charmbracelet/vhs)).\n\n### CLI verbs adjacent to the chat\n\n```\ncarlos please \"<prompt>\"         # one-shot, no TUI\ncarlos research \"<question>\"     # multi-phase deep research\ncarlos memory search <query>     # FTS5 over conversation summaries\ncarlos schedule list|add|rm      # cron + natural language\ncarlos gateway add               # wizard to configure ntfy / Telegram / Signal\ncarlos gateway test <channel>    # verify ntfy / Telegram wiring\ncarlos daemon enable|disable     # background service\n```\n\nAll accept `-f <frame>` (or `--frame`) to scope to a specific frame. `carlos please` takes a single positional prompt; multi-word prompts must be quoted (a single hyphenated token like `say-hello` works without quotes).\n\n`carlos please` shows a live 3-row bordered status panel while it runs (current tool, streaming-text preview, tool counter + provider/model); the assistant's final reply prints below the panel on completion.\n\n`carlos research` shows a live phase tracker (decompose, search, fetch, read, synthesize, verify) and writes a cited report under `~/.carlos/frames/<frame>/research/`:\n\n<p align=\"center\">\n  <img src=\"docs/branding/screenshots/research-done.png\" alt=\"carlos research finished: 1m6s elapsed, all six phases checked, saved to ~/.carlos/frames/personal/research/\" width=\"720\">\n</p>\n\n---\n\n## Contributing\n\n### Prerequisites\n\n- Go toolchain version pinned by `go.mod` (currently `1.26.3`).\n- `git` on `$PATH` (the sub-agent sandbox uses `git worktree`).\n- No CGO, no system libraries.\n\n### Build and test\n\n```\ngit clone https://github.com/georgebuilds/carlos\ncd carlos\ngo test ./...\ngo build ./cmd/carlos\n./carlos\n```\n\nCross-compile checks are cheap; run them when touching anything that imports OS-specific paths:\n\n```\nGOOS=linux  GOARCH=arm64  go build ./cmd/carlos\nGOOS=darwin GOARCH=amd64  go build ./cmd/carlos\n```\n\n### Test discipline\n\n- `go test ./...` is the floor. Current count is ~5300 tests across 46 packages.\n- `go vet ./...` must be clean.\n- New code aims for 80%+ coverage on touched packages.\n- The sub-agent + daemon + event log paths have integration tests; if you touch any of them, run `go test -race ./internal/agent/... ./internal/daemon/...` at least once before pushing.\n\n### Repository layout\n\n```\ncmd/carlos/         main TUI binary + daemon entry points\ninternal/\n  agent/            tool-use loop, event log, supervision, layered approval\n  config/           ~/.carlos/config.yaml schema + onboarding state\n  daemon/           background scheduler (UDS + launchd / systemd)\n  farewell/         bordered exit-panel + brew-update probe\n  frame/            per-session frames (personal + N user-defined)\n  gateway/          chat-surface adapters (ntfy, Telegram, Signal stub)\n  mcp/              Model Context Protocol client + tool adapter\n  memory/           SQLite FTS5 + summarizer\n  miniyaml/         hand-rolled YAML for frontmatter\n  notes/            Obsidian vault index + cache (Goldmark + miniyaml)\n  projectctx/       per-project context loader (walks AGENTS.md / CLAUDE.md)\n  providers/        anthropic, openai, openrouter, ollama, gemini\n  research/         decompose → search → fetch → read → synthesize → verify\n  sandbox/          local + git-worktree execution\n  schedule/         cron + natural-language grammar\n  skills/           skill format, loader, inducer, judge, replay-eval\n  theme/            light / dark / NO_COLOR / configurable accent\n  tools/            every registered tool (notes_*, web_*, code_search, etc.)\n  tui/              bubbletea chat / manage / onboarding / slash registry\n  usershell/        `!` prefix shell driver, jobs overlay, history\n  workspace/        trusted-workspaces store + read-only bash classifier\nskills/             bundled starter skills (calendar/, ...)\ndocs/               GitHub Pages site + llms.txt\n```\n\n### Where to look when adding a feature\n\n| You want to | Look here |\n|---|---|\n| Add a tool | `internal/tools/`, register in `tools.go` |\n| Add a slash command | `internal/tui/slash/slash.go` Builtins + handler in `internal/tui/chat/` |\n| Wire an MCP server | `mcp_servers:` block in `~/.carlos/config.yaml`; client + adapter live in `internal/mcp/` |\n| Add a provider | `internal/providers/<name>/`, satisfy the `Provider` interface |\n| Add a frame field | `internal/frame/frame.go`, then sysprompt + render helpers |\n| Change permission rules | `internal/agent/policy.go` (`LayeredApprover`) |\n| Add an event type | `internal/agent/eventlog_sqlite.go` + state machine |\n| Add an onboarding screen | `internal/tui/onboarding/screen_*.go` + flow wiring |\n\n### House conventions\n\n- Single immutable event log is the source of truth. The projection replays from it.\n- Atomic writes for any file containing user state: `temp + fsync + rename`. See `internal/config/config.go:Save` for the canonical recipe.\n- File modes: `0700` directories, `0600` secret-bearing files (`config.yaml`, `state.db`, `trusted-workspaces.json`, artifact blobs), `0644` elsewhere.\n- Prefer editing existing files to creating new ones.\n- Default to no comments; add one only when the WHY is non-obvious.\n\n### Release flow\n\nA `v*` tag push fires `.github/workflows/release.yml` which runs goreleaser to build the four-arch tarballs, drafts a GitHub release, and bumps `georgebuilds/homebrew-tap/Formula/carlos.rb`. Publish the draft when ready (`gh release edit v0.X.Y --draft=false`).\n\n---\n\n## License\n\nGPL-3.0-or-later. See [LICENSE](./LICENSE).\n"}