brito-cli 0.7.4 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,259 +1,298 @@
1
- # Brito
2
-
3
- **English** · [Português](README.pt-BR.md)
4
-
5
- > A coding agent for your terminal (`brito-cli`) and your desktop (a native app) that knows your codebase as a **graph** and learns your project's procedures as **skills you review**.
6
-
7
- Brito is an agent for software development. Use it in the terminal (`brito-cli` on npm) or as a desktop app (an executable for macOS, Windows and Linux): same agent, same graph, same skills. Instead of grepping and reading files blindly, it keeps a **knowledge graph of your code** (symbols, who calls whom, who imports whom) and answers questions like *"what breaks if I change this?"* straight from the graph, in a fraction of a second. It also keeps **memory notes** and **skills**: reusable procedures learned from your own work, which only become active after **you** approve them.
8
-
9
- ![Brito answering a question with the code graph](docs/images/answer-with-graph.png)
10
-
11
- *A real session on a small SvelteKit project: one question, two graph calls (0.1 s and 0.0 s), and an answer that already includes the `.svelte` components depending on the file. The status bar shows the real cost of the turn.*
12
-
13
- ## Highlights
14
-
15
- > **Upgrading to 0.6:** the graph engine changed from Kùzu (discontinued) to LadybugDB. The graph is rebuilt automatically on first use; your old `.brito/graph.kuzu` is kept. Brito asks once whether to copy your notes (memory) to the new graph, or run `brito migrar-notas` any time. Tests run in CI on macOS, Linux and Windows (use 0.6.1 or later on Windows/Linux). See the [CHANGELOG](CHANGELOG.md).
16
-
17
- - **Graph-first exploration.** `graph_search`, `graph_context`, `graph_callers`, `graph_callees` and `graph_impact` answer "where is it, who uses it, what breaks" without reading whole files. The graph is embedded ([LadybugDB](https://github.com/LadybugDB/ladybug), fork mantido do Kùzu), local and incremental.
18
- - **Wide coverage.** TypeScript/JavaScript, Python and the script blocks of `.svelte`, `.vue` and `.astro` components. Import aliases (`tsconfig` paths, `package.json` imports, SvelteKit's `$lib`) become real edges. Files ignored by `.gitignore` stay out.
19
- - **Skills that learn on their own, on probation.** After a task that tripped or was corrected, Brito reflects and creates a skill *in trial* without interrupting you. A skill proves itself by use: 3 clean uses promote it, 2 stumbles archive it (recoverable). Anything risky, or any change to a skill you approved, still waits for your `/skills approve`. `BRITO_SKILLS=ask` restores approval-for-everything; `off` disables learning.
20
- - **Safety rails for what gets learned.** A lint rejects secrets, credentials embedded in URLs, `curl | sh` and prompt-injection phrasing, and **warns about destructive commands** (see below).
21
- - **Permission modes.** manual, auto-edits, plan and "everything allowed" (`Shift+Tab` cycles them). Autonomous skills do not depend on the mode: they are created in trial and judged by results.
22
- - **Two backends, one interface.** Use an Anthropic API key, or your Claude Code subscription through the `claude` CLI. Brito never reads or sends your subscription token.
23
- - **Terminal or desktop app.** `npm i -g brito-cli` gives you the `brito` command; the desktop app is a native executable with a window (projects and sessions in a sidebar, chat, permission prompts), no Node or terminal needed. See [Install](#install).
24
- - **Images.** Drag an image file into the prompt (or paste its path) and it is attached to the turn: PNG, JPEG, GIF or WebP, up to 5 MB.
25
- - **Subagents.** `explore`, `plan` and `general` run in isolated contexts (read-only ones in parallel); add your own in `.brito/agents/*.md`.
26
- - **MCP server.** `brito mcp-serve` exposes the graph, memory and skills to other MCP clients such as Claude Code. The query tools are marked `alwaysLoad`, so they are not hidden behind tool search.
27
-
28
- ## How it works
29
-
30
- ![Indexing once, then answering from the graph instead of grep and file reads](docs/images/graph-vs-grep.svg)
31
-
32
- *The graph is built once and updated incrementally; a question like "what breaks if I change this?" becomes one or two graph calls.*
33
-
34
- ```mermaid
35
- flowchart LR
36
- code["Your project<br/>.ts · .js · .py · .java · .kt · .go · .rb · .php · .cs · .rs · .svelte · .vue · .astro"] -->|"tree-sitter<br/>incremental"| cg[("Code graph<br/>symbols · calls · imports")]
37
- cg <-->|"graph_search · graph_callers<br/>graph_impact · graph_context"| agent{{"Brito agent"}}
38
- mem[("Memory<br/>decisions · conventions")] <-->|"recall / remember"| agent
39
- agent -->|"after a complex task"| learn["Reflection"]
40
- learn -->|"creates"| trial["Skill in trial"]
41
- trial -->|"3 clean uses"| skills[("Skills<br/>.brito/skills")]
42
- trial -->|"2 stumbles or 21 idle days"| trash["Archived (.trash)"]
43
- learn -->|"risky or changes yours"| pending["Pending<br/>/skills approve"]
44
- pending --> skills
45
- skills -->|"skill_load"| agent
46
- trial -->|"skill_load"| agent
47
- ```
48
-
49
- - **Code graph**: functions, classes, methods and components as nodes; `CALLS` and `IMPORTS` as edges. It re-parses only files whose hash changed and updates itself after edits.
50
- - **Memory**: durable notes (decisions, conventions, bugs found) linked to files and symbols, retrieved with `recall`.
51
- - **Skills**: step-by-step procedures for *your* project (commands, order, traps, how to verify). The agent loads one with `skill_load` before a task it covers.
52
- - **Journal**: Brito remembers across sessions which tasks repeated, which is the best hint that a procedure is general and worth saving.
53
-
54
- ### Architecture at a glance
55
-
56
- ![Brito architecture: context, permissions, tools and subagents around the model](docs/images/architecture.svg)
57
-
58
- *Everything the model sees or can do is one of eight components, grouped by role. The mono-spaced text is the real file or command; the pill says when it fires.*
59
-
60
- ## Skills that earn their place
61
-
62
- ![Skill lifecycle: task, reflection, trial or pending, active or archived](docs/images/skill-lifecycle.svg)
63
-
64
- *The two paths a skill can take. Safe ones prove themselves in trial; risky ones wait for your approval.*
65
-
66
- ![Reviewing a pending skill, with a destructive-command warning](docs/images/skills-review.png)
67
-
68
- 0. **Autonomous path (default).** The reflection saves a new skill as *trial*, marked "(em teste)" in the index. Each turn that loads it counts as a win (no error-then-fix, no user correction) or a loss. 3 wins (and at most 1 loss per 3 wins) promote it; 2 losses without more wins, or 21 days unused, archive it to `.brito/skills/.trash`. Brito prints one line per promotion or archive. Limits: at most 3 new automatic skills a day, project scope only, and a weekly automatic consolidation that only touches automatic skills.
69
- 1. **Review path.** Skills with destructive commands, and changes to skills you approved, appear in `/skills pending`, flagged when they contain destructive commands.
70
- 2. `/skills approve <name>` shows the **whole body** and the lint warnings, then asks for confirmation. That confirmation is required even in "everything allowed" mode.
71
- 3. Approved skills are versioned (`history/`), ranked by use, and flagged when the files they cite no longer exist. `/skills consolidate` merges duplicates and prunes unused ones.
72
- 4. A skill can be project-scoped or **global** (valid in every project); `/skills promote` moves one to global.
73
-
74
- The lint **rejects** secrets/tokens, absolute user paths, credentials in URLs (`user:password@host`), `curl | sh`, and instructions to override rules or skip approval. It **warns** (without blocking) about commands that destroy data: removing database or data files, `DROP`/`TRUNCATE`, `DELETE` without `WHERE`, migration resets, `git reset --hard`, force-push, Docker volume removal. A skill is a standing instruction, so a step that was only safe in the state of one moment must not silently become the default.
75
-
76
- ## Install
77
-
78
- ### Terminal (`brito-cli`)
79
-
80
- Requires Node >= 20. Developed on macOS; Linux should work. On Windows use `npm i -g brito-cli` (the `install.sh` script needs bash); install Git for Windows so the `bash` tool runs bash commands, otherwise it falls back to `cmd.exe` (override with `BRITO_SHELL`).
81
-
82
- ```bash
83
- # from npm (the command is `brito`)
84
- npm i -g brito-cli
85
-
86
- # or one line
87
- curl -fsSL https://raw.githubusercontent.com/wilsonbrito/brito/main/install.sh | bash
88
-
89
- # or straight from GitHub
90
- npm i -g github:wilsonbrito/brito
91
-
92
- # or cloning
93
- git clone https://github.com/wilsonbrito/brito && cd brito
94
- npm install && npm run build && npm link
95
- ```
96
-
97
- Pick a backend:
98
-
99
- ```bash
100
- export ANTHROPIC_API_KEY=sk-ant-... # Anthropic API
101
- # or: install Claude Code, run `claude` and /login — Brito will use your subscription
102
- ```
103
-
104
- ### Desktop app (executable)
105
-
106
- The same agent in a window: projects and sessions in a sidebar, chat with markdown, collapsible tool calls, permission prompts, and pickers for model, effort and permission mode. It needs neither Node nor a terminal.
107
-
108
- ![Brito desktop app answering a question with the code graph](docs/images/desktop-app.png)
109
-
110
- *The desktop app on a small project: one question, one graph call (the collapsed "ran 1 command" line), and the answer as a table. The sidebar groups sessions by project; the footer shows the backend, the folder, the context size and the cost.*
111
-
112
- Download it from the [Releases page](https://github.com/wilsonbrito/brito/releases):
113
-
114
- | System | File |
115
- |---|---|
116
- | macOS | `Brito-<version>-macos-arm64.dmg` (Apple Silicon) or `-x64.dmg` (Intel): open it and drag Brito to Applications |
117
- | Windows | `Brito-<version>-windows-x64-setup.exe` |
118
- | Linux | `Brito-<version>-linux-x64.tar.gz`: extract it and run `./install.sh` (adds Brito to the applications menu) |
119
-
120
- The builds are not signed with an Apple Developer ID or a Windows certificate, so macOS ("unidentified developer": right-click, then Open) and Windows SmartScreen warn on the first launch. macOS is the platform exercised the most; the Windows and Linux builds come from CI and have had less testing.
121
-
122
- Like the terminal version, it uses `ANTHROPIC_API_KEY` when your shell exports it, otherwise your Claude Code subscription (`claude`, then `/login`). Opened from the Finder, the app reads your login shell to find them.
123
-
124
- To build it yourself: `npm run desktop` (development), `npm run desktop:app` (macOS: installs `/Applications/Brito.app`) or `npm run desktop:dmg`.
125
-
126
- ## Quick start
127
-
128
- ```bash
129
- cd your-project
130
- brito # opens the REPL
131
- brito "who calls parseConfig?" # single prompt, no REPL
132
- brito index # (re)index the graph; it is also kept up to date automatically
133
- brito query "MATCH (c:Symbol {kind:'component'})-[:CALLS]->(f:Symbol) RETURN c.file, f.name LIMIT 5"
134
- ```
135
-
136
- A real `brito index` on the sample project above:
137
-
138
- ```
139
- OK: 20 arquivos, 66 símbolos, 54 chamadas, 17 imports | +0 ~0 -0 =20 (28ms)
140
- ```
141
-
142
- ![Brito start screen](docs/images/startup.png)
143
-
144
- ### Inside the REPL
145
-
146
- | Command | What it does |
147
- |---|---|
148
- | `/help` | list commands |
149
- | `/model`, `/effort`, `/reasoning` | choose model, reasoning effort and thinking (session, global or once) |
150
- | `/fallback` | shows the main model and the fallback (qwen), and whether the switch already happened |
151
- | `/modo` or `Shift+Tab` | switch permission mode: manual → auto-edits → plan → bypass ("everything allowed") |
152
- | `/skills` | list skills · `pending` · `approve <name>` · `reject <name>` · `consolidate` · `rm <name>` · `promote <name>` |
153
- | `/learn` | extract skills from the last turn now |
154
- | `/agents`, `/tools`, `/index`, `/context` | inspect subagents, tools, the index and the context window |
155
- | `!command` | run a shell command directly, without calling the model |
156
- | `/clear`, `/exit` | clear the conversation, quit |
157
-
158
- ## What the graph indexes
159
-
160
- - **Languages:** TypeScript/JavaScript (`.ts .tsx .mts .cts .js .jsx .mjs .cjs`), Python (`.py`), backend languages — Java (`.java`), Kotlin (`.kt`), Go (`.go`), Ruby (`.rb`), PHP (`.php`), C# (`.cs`), Rust (`.rs`) — and the `.svelte`, `.vue` and `.astro` components. In components Brito reads the script block(s) (and Astro's frontmatter) and records calls made from the template to functions the script declares or imports; each component becomes a `component` symbol.
161
- - **Scope:** inside a git repository, only what git considers part of the project (tracked + untracked-but-not-ignored), so anything in `.gitignore` stays out. Outside git, or with `BRITO_INDEX_IGNORED=1`, it indexes by glob (still skipping `node_modules`, `dist`, `build`, `target`, `vendor`, `obj`, `.gradle`, `.venv`, `.brito`).
162
- - **Imports:** relative and aliased. Resolves `paths`/`baseUrl` from `tsconfig.json`/`jsconfig.json` (following relative `extends`, like `.svelte-kit/tsconfig.json`), `package.json` `imports` (`#internal/*`) and SvelteKit's `$lib`. Configuration applies per file (nearest config), so monorepos work; editing a tsconfig re-indexes the affected files.
163
- - **Backend languages:** the graph holds classes/interfaces/structs/traits/enums/modules, functions and methods (`Class.method`), calls and imports. Imports name a package, not a path, so Brito matches them against the end of your files' paths (`com.acme.Repo` ↔ `src/main/java/com/acme/Repo.java`; PHP PSR-4 namespaces; Rust `use crate::…`; Ruby `require`/`require_relative`; Go packages through the `go.mod` module path). External packages (`java.util`, `serde`, `github.com/gin-gonic/gin`) never match and create no edges. There is no type inference: a call like `userRepository.save()` is linked by matching the receiver name to a type in the project (`UserRepository`), `this`/`self`/receivers resolve to the enclosing class, and a bare call inside a class tries the class's own methods first.
164
- - **Not yet:** `extends` by package (`@tsconfig/node20`), sibling-workspace `exports`, and function references without a call in a template (`onclick={fn}`). Calls are resolved statically with name-based fallbacks, so dynamic dispatch and reflection are not captured.
165
-
166
- ## Databases and other sensitive resources
167
-
168
- Brito has **no database drivers and connects to nothing on its own**. When it needs to touch a database, it uses your project's own tooling through the shell, under the permission mode you chose. Because every project is different (a local file, a remote server, a container), declare the sensitive parts in `BRITO.md` (or `CLAUDE.md` / `AGENTS.md`), which is read into the system prompt:
169
-
170
- ```markdown
171
- ## Protected resources
172
- - Database: local SQLite file `local.db` (never commit, never recreate).
173
- Test destructive changes on a copy: `cp local.db /tmp/test.db` and set `DATABASE_URL`.
174
- Schema changes: additive only, back up first (`cp local.db backups/pre-change.db`).
175
- - Staging Postgres: connection string is in `$STAGING_DATABASE_URL` (read-only role). Never touch production.
176
- ```
177
-
178
- - Credentials never belong in skills or notes: the lint rejects them. Cite the **name** of the environment variable instead.
179
- - Prefer read-only roles and non-production environments when you give an agent database access.
180
- - A proposed skill that contains a destructive command is highlighted at review time, so you decide whether it needs a guard (backup, copy, confirmation).
181
-
182
- ## OpenAI-compatible endpoint (e.g. Qwen on OCI)
183
-
184
- > Full step-by-step (install, key, profile, and how to give people access to the repository, in Portuguese): [docs/GUIA-QWEN.md](docs/GUIA-QWEN.md).
185
-
186
- Besides Claude, Brito runs on any model served through the OpenAI **Chat Completions** API (vLLM, OCI Generative AI, LiteLLM, Ollama…) with tool calling. Add a profile to `~/.brito/config.json`:
187
-
188
- ```json
189
- {
190
- "providers": {
191
- "qwen": {
192
- "type": "openai",
193
- "label": "Qwen 27B (OCI)",
194
- "baseURL": "https://inference.generativeai.<region>.oci.oraclecloud.com/openai/v1",
195
- "model": "<model id; on OCI, the dedicated endpoint OCID>",
196
- "apiKeyEnv": "BRITO_QWEN_API_KEY",
197
- "contextWindow": 262144,
198
- "vision": false,
199
- "thinkingToggle": true
200
- }
201
- }
202
- }
203
- ```
204
-
205
- The key is **not** stored in the config: put it in the environment variable named by `apiKeyEnv`. Then:
206
-
207
- ```bash
208
- brito --model qwen # this session
209
- /model qwen --global # inside the REPL: make it the default
210
- ```
211
-
212
- With a profile selected, **everything** goes to the endpoint: main agent, subagents (`explore` stops using Haiku), context summaries and skill learning; Brito starts without `ANTHROPIC_API_KEY` and without the `claude` CLI. `/reasoning none` turns the model's reasoning off (much faster answers on Qwen). `thinkingToggle: true` only for servers that accept `chat_template_kwargs` (vLLM/Qwen); without it `/reasoning none` has no effect, but no unknown parameter is sent. Images are only sent with `"vision": true`. Deliberate exception: `BRITO_EXPLORE_MODEL` still decides the `explore` subagent; a `BRITO_LEARN_MODEL` pointing at Claude is ignored while a profile is active. A broken profile in the config never falls back to Claude: Brito warns and stops. `/effort` stays exclusive to `claude` CLI mode, and a profile does not run inside the `claude` CLI (`/model` tells you to reopen with `--model`).
213
-
214
- ### Fallback to Qwen
215
-
216
- With Claude as the main model (API or `claude` CLI), the `qwen` profile is the automatic fallback — always that one, no new config key. If Claude fails because of a **subscription limit, rate limit, credit, authentication, overload or network** error, Brito warns and redoes the request on Qwen with the conversation so far (tools that already ran stay in the history, so they are not repeated). In `claude` CLI mode the whole engine switches to Brito's own loop.
217
-
218
- - The switch happens once per session and never reverts on its own: `/model <claude>` goes back to Claude (and the fallback can trigger again later).
219
- - It does not switch on Ctrl+C or on content errors (invalid request, `max_tokens`, broken tool).
220
- - Without `ANTHROPIC_API_KEY` and without the `claude` CLI, Brito opens straight on Qwen, with a warning. If the fallback is not ready, the usual error includes why (e.g. `BRITO_QWEN_API_KEY` is missing). An invalid `qwen` profile is still an error, never a silent fallback.
221
- - `/fallback` shows the state. In the desktop app, send `/fallback` as a message; the status bar shows Qwen while the fallback is active.
222
-
223
- ## Configuration
224
-
225
- `BRITO_MODEL`, `BRITO_EFFORT`, `BRITO_EXPLORE_MODEL`, `BRITO_LEARN_MODEL`, `BRITO_HOME` (where global skills and history live), `BRITO_CONFIG`, `BRITO_COLOR`, `BRITO_BANNER` (`compact` or `full`; default: full screen on windows of 95+ columns and 28+ rows), `BRITO_INDEX_IGNORED`, `BRITO_SKILL_MIN_TOOLS` (how long a turn must be to trigger reflection when nothing else does), `BRITO_SKILLS` (`auto` default, `ask`, `off`), `BRITO_SHELL` (shell used by the `bash` tool; on Windows defaults to Git Bash when installed).
226
-
227
- Project data lives in `.brito/` (graph, project skills, agents) and global data in `~/.brito`. The graph, memory and skills stay on your machine; as with any coding agent, the code the model reads is sent to the model provider you configured.
228
-
229
- ## Limitations
230
-
231
- - Early software (v0.5.0), one maintainer.
232
- - The desktop app is new: a single window (no tabs yet), and with an API key (no `claude` CLI) the model does not resume a conversation after you reopen the app, although the screen shows it.
233
- - **The interface and the agent's default language are Brazilian Portuguese.** Translating them is a welcome contribution.
234
- - Skill learning is a heuristic: it proposes, you decide. Expect some proposals to be rejected.
235
-
236
- ## Development
237
-
238
- ```bash
239
- git clone https://github.com/wilsonbrito/brito && cd brito
240
- npm install
241
- npm run dev # runs via tsx
242
- npm run typecheck
243
- npm test # 190+ tests, including a real MCP server and a real REPL
244
- ```
245
-
246
- | Path | What |
247
- |---|---|
248
- | `src/graph/` | indexer (tree-sitter), `.svelte/.vue/.astro` support, import aliases, Ladybug (Kùzu) store |
249
- | `src/skills/` | store, lint, reflection, journal, consolidation |
250
- | `src/agent/` | agent loop, prompts, subagents, `claude` CLI backend |
251
- | `src/tools/` | graph, memory, skills, filesystem and shell tools |
252
- | `src/mcp/` | MCP server |
253
- | `src/repl.ts`, `src/ui/` | terminal interface |
254
- | `src/desktop/` | `brito gui-serve`: the backend the desktop window talks to (JSON over stdio) |
255
- | `desktop/` | Electron window and packaging (`package.mjs`); `npm run bundle` builds the single-file backend it uses |
256
-
257
- ## License
258
-
259
- [PolyForm Noncommercial 1.0.0](LICENSE): free to use, study and modify for any noncommercial purpose (personal use, research, education, hobby, nonprofits). Commercial use is not permitted. This is source-available, not OSI open source. Need a commercial license? Open an issue.
1
+ # Brito
2
+
3
+ **English** · [Português](README.pt-BR.md)
4
+
5
+ > A coding agent for your terminal (`brito-cli`) and your desktop (a native app) that knows your codebase as a **graph** and learns your project's procedures as **skills you review**.
6
+
7
+ Brito is an agent for software development. Use it in the terminal (`brito-cli` on npm) or as a desktop app (an executable for macOS, Windows and Linux): same agent, same graph, same skills. Instead of grepping and reading files blindly, it keeps a **knowledge graph of your code** (symbols, who calls whom, who imports whom) and answers questions like *"what breaks if I change this?"* straight from the graph, in a fraction of a second. It also keeps **memory notes** and **skills**: reusable procedures learned from your own work, which only become active after **you** approve them.
8
+
9
+ ![Brito answering a question with the code graph](docs/images/answer-with-graph.png)
10
+
11
+ *A real session on a small SvelteKit project: one question, two graph calls (0.1 s and 0.0 s), and an answer that already includes the `.svelte` components depending on the file. The status bar shows the real cost of the turn.*
12
+
13
+ ## Highlights
14
+
15
+ > **Upgrading to 0.6:** the graph engine changed from Kùzu (discontinued) to LadybugDB. The graph is rebuilt automatically on first use; your old `.brito/graph.kuzu` is kept. Brito asks once whether to copy your notes (memory) to the new graph, or run `brito migrar-notas` any time. Tests run in CI on macOS, Linux and Windows (use 0.6.1 or later on Windows/Linux). See the [CHANGELOG](CHANGELOG.md).
16
+
17
+ - **Graph-first exploration.** `graph_search`, `graph_context`, `graph_callers`, `graph_callees` and `graph_impact` answer "where is it, who uses it, what breaks" without reading whole files. The graph is embedded ([LadybugDB](https://github.com/LadybugDB/ladybug), fork mantido do Kùzu), local and incremental.
18
+ - **Wide coverage.** TypeScript/JavaScript, Python and the script blocks of `.svelte`, `.vue` and `.astro` components. Import aliases (`tsconfig` paths, `package.json` imports, SvelteKit's `$lib`) become real edges. Files ignored by `.gitignore` stay out.
19
+ - **Skills that learn on their own, on probation.** After a task that tripped or was corrected, Brito reflects and creates a skill *in trial* without interrupting you. A skill proves itself by use: 3 clean uses promote it, 2 stumbles archive it (recoverable). Anything risky, or any change to a skill you approved, still waits for your `/skills approve`. `BRITO_SKILLS=ask` restores approval-for-everything; `off` disables learning.
20
+ - **Safety rails for what gets learned.** A lint rejects secrets, credentials embedded in URLs, `curl | sh` and prompt-injection phrasing, and **warns about destructive commands** (see below).
21
+ - **Permission modes and rules.** manual, auto-edits, plan and "everything allowed" (`Shift+Tab` cycles them), plus `allow`/`deny` rules per command or path (see [Permission rules](#permission-rules)). Editing a file requires having read it in the session, unchanged since. Autonomous skills do not depend on the mode: they are created in trial and judged by results.
22
+ - **Two backends, one interface.** Use an Anthropic API key, or your Claude Code subscription through the `claude` CLI. Brito never reads or sends your subscription token.
23
+ - **Terminal or desktop app.** `npm i -g brito-cli` gives you the `brito` command; the desktop app is a native executable with a window (projects and sessions in a sidebar, chat, permission prompts), no Node or terminal needed. See [Install](#install).
24
+ - **Images.** Drag an image file into the prompt (or paste its path) and it is attached to the turn: PNG, JPEG, GIF or WebP, up to 5 MB.
25
+ - **Subagents.** `explore`, `plan` and `general` run in isolated contexts (read-only ones in parallel); add your own in `.brito/agents/*.md`.
26
+ - **MCP server.** `brito mcp-serve` exposes the graph, memory and skills to other MCP clients such as Claude Code. The query tools are marked `alwaysLoad`, so they are not hidden behind tool search.
27
+
28
+ ## How it works
29
+
30
+ ![Indexing once, then answering from the graph instead of grep and file reads](docs/images/graph-vs-grep.svg)
31
+
32
+ *The graph is built once and updated incrementally; a question like "what breaks if I change this?" becomes one or two graph calls.*
33
+
34
+ ```mermaid
35
+ flowchart LR
36
+ code["Your project<br/>.ts · .js · .py · .java · .kt · .go · .rb · .php · .cs · .rs · .svelte · .vue · .astro"] -->|"tree-sitter<br/>incremental"| cg[("Code graph<br/>symbols · calls · imports")]
37
+ cg <-->|"graph_search · graph_callers<br/>graph_impact · graph_context"| agent{{"Brito agent"}}
38
+ mem[("Memory<br/>decisions · conventions")] <-->|"recall / remember"| agent
39
+ agent -->|"after a complex task"| learn["Reflection"]
40
+ learn -->|"creates"| trial["Skill in trial"]
41
+ trial -->|"3 clean uses"| skills[("Skills<br/>.brito/skills")]
42
+ trial -->|"2 stumbles or 21 idle days"| trash["Archived (.trash)"]
43
+ learn -->|"risky or changes yours"| pending["Pending<br/>/skills approve"]
44
+ pending --> skills
45
+ skills -->|"skill_load"| agent
46
+ trial -->|"skill_load"| agent
47
+ ```
48
+
49
+ - **Code graph**: functions, classes, methods and components as nodes; `CALLS` and `IMPORTS` as edges. It re-parses only files whose hash changed and updates itself after edits.
50
+ - **Memory**: durable notes (decisions, conventions, bugs found) linked to files and symbols, retrieved with `recall`.
51
+ - **Skills**: step-by-step procedures for *your* project (commands, order, traps, how to verify). The agent loads one with `skill_load` before a task it covers.
52
+ - **Journal**: Brito remembers across sessions which tasks repeated, which is the best hint that a procedure is general and worth saving.
53
+
54
+ ### Architecture at a glance
55
+
56
+ ![Brito architecture: context, permissions, tools and subagents around the model](docs/images/architecture.svg)
57
+
58
+ *Everything the model sees or can do is one of eight components, grouped by role. The mono-spaced text is the real file or command; the pill says when it fires.*
59
+
60
+ ## Skills that earn their place
61
+
62
+ ![Skill lifecycle: task, reflection, trial or pending, active or archived](docs/images/skill-lifecycle.svg)
63
+
64
+ *The two paths a skill can take. Safe ones prove themselves in trial; risky ones wait for your approval.*
65
+
66
+ ![Reviewing a pending skill, with a destructive-command warning](docs/images/skills-review.png)
67
+
68
+ 0. **Autonomous path (default).** The reflection saves a new skill as *trial*, marked "(em teste)" in the index. Each turn that loads it counts as a win (no error-then-fix, no user correction) or a loss. 3 wins (and at most 1 loss per 3 wins) promote it; 2 losses without more wins, or 21 days unused, archive it to `.brito/skills/.trash`. Brito prints one line per promotion or archive. Limits: at most 3 new automatic skills a day, project scope only, and a weekly automatic consolidation that only touches automatic skills.
69
+ 1. **Review path.** Skills with destructive commands, and changes to skills you approved, appear in `/skills pending`, flagged when they contain destructive commands.
70
+ 2. `/skills approve <name>` shows the **whole body** and the lint warnings, then asks for confirmation. That confirmation is required even in "everything allowed" mode.
71
+ 3. Approved skills are versioned (`history/`), ranked by use, and flagged when the files they cite no longer exist. `/skills consolidate` merges duplicates and prunes unused ones.
72
+ 4. A skill can be project-scoped or **global** (valid in every project); `/skills promote` moves one to global.
73
+
74
+ The lint **rejects** secrets/tokens, absolute user paths, credentials in URLs (`user:password@host`), `curl | sh`, and instructions to override rules or skip approval. It **warns** (without blocking) about commands that destroy data: removing database or data files, `DROP`/`TRUNCATE`, `DELETE` without `WHERE`, migration resets, `git reset --hard`, force-push, Docker volume removal. A skill is a standing instruction, so a step that was only safe in the state of one moment must not silently become the default.
75
+
76
+ ## Local model (optional)
77
+
78
+ `brito slm pull` downloads a small local model (Qwen3-4B-Instruct-2507 Q4_K_M, Apache-2.0) to `~/.brito/models` through the optional `node-llama-cpp` dependency. `brito slm` shows the status and `brito slm rm` deletes it. Once downloaded it is used for:
79
+
80
+ - **Skill learning**: the reflection runs locally with grammar-constrained JSON and falls back to the usual model on any failure.
81
+ - **`digest` tool**: a scout and refiner for long texts. The local model picks the blocks most related to your objective and proposes excerpts; code then checks every quote against the source and drops what is not there, so the main model gets a small markdown draft with verified quotes and page numbers.
82
+
83
+ - **Fallback when Claude runs out**: chain Claude → `qwen` profile → local SLM, with the full agent loop and tools (same permissions). It is temporary: after a window (the reset time reported by the error, else 10 min, or 60 min for quota/auth; `BRITO_FALLBACK_MINUTES` overrides) the next turn tries Claude again. `/fallback` shows when. A 4B model errs more with tools: use it to keep going, not for big tasks. `BRITO_SLM_FALLBACK=off` removes it from the chain; `BRITO_SLM_CTX` sets its context.
84
+
85
+ `BRITO_SLM=off` disables it; `BRITO_SLM_MODEL` points to another GGUF (`hf:` URI or file path).
86
+
87
+ ## Install
88
+
89
+ ### Terminal (`brito-cli`)
90
+
91
+ Requires Node >= 20. Developed on macOS; Linux should work. On Windows use `npm i -g brito-cli` (the `install.sh` script needs bash); install Git for Windows so the `bash` tool runs bash commands, otherwise it falls back to `cmd.exe` (override with `BRITO_SHELL`).
92
+
93
+ ```bash
94
+ # from npm (the command is `brito`)
95
+ npm i -g brito-cli
96
+
97
+ # or one line
98
+ curl -fsSL https://raw.githubusercontent.com/wilsonbrito/brito/main/install.sh | bash
99
+
100
+ # or straight from GitHub
101
+ npm i -g github:wilsonbrito/brito
102
+
103
+ # or cloning
104
+ git clone https://github.com/wilsonbrito/brito && cd brito
105
+ npm install && npm run build && npm link
106
+ ```
107
+
108
+ Pick a backend:
109
+
110
+ ```bash
111
+ export ANTHROPIC_API_KEY=sk-ant-... # Anthropic API
112
+ # or: install Claude Code, run `claude` and /login — Brito will use your subscription
113
+ ```
114
+
115
+ ### Desktop app (executable)
116
+
117
+ The same agent in a window: projects and sessions in a sidebar, chat with markdown, collapsible tool calls, permission prompts, and pickers for model, effort and permission mode. It needs neither Node nor a terminal.
118
+
119
+ ![Brito desktop app answering a question with the code graph](docs/images/desktop-app.png)
120
+
121
+ *The desktop app on a small project: one question, one graph call (the collapsed "ran 1 command" line), and the answer as a table. The sidebar groups sessions by project; the footer shows the backend, the folder, the context size and the cost.*
122
+
123
+ Download it from the [Releases page](https://github.com/wilsonbrito/brito/releases):
124
+
125
+ | System | File |
126
+ |---|---|
127
+ | macOS | `Brito-<version>-macos-arm64.dmg` (Apple Silicon) or `-x64.dmg` (Intel): open it and drag Brito to Applications |
128
+ | Windows | `Brito-<version>-windows-x64-setup.exe` |
129
+ | Linux | `Brito-<version>-linux-x64.tar.gz`: extract it and run `./install.sh` (adds Brito to the applications menu) |
130
+
131
+ The builds are not signed with an Apple Developer ID or a Windows certificate, so macOS ("unidentified developer": right-click, then Open) and Windows SmartScreen warn on the first launch. macOS is the platform exercised the most; the Windows and Linux builds come from CI and have had less testing.
132
+
133
+ Like the terminal version, it uses `ANTHROPIC_API_KEY` when your shell exports it, otherwise your Claude Code subscription (`claude`, then `/login`). Opened from the Finder, the app reads your login shell to find them.
134
+
135
+ To build it yourself: `npm run desktop` (development), `npm run desktop:app` (macOS: installs `/Applications/Brito.app`) or `npm run desktop:dmg`.
136
+
137
+ ## Quick start
138
+
139
+ ```bash
140
+ cd your-project
141
+ brito # opens the REPL
142
+ brito "who calls parseConfig?" # single prompt, no REPL
143
+ brito index # (re)index the graph; it is also kept up to date automatically
144
+ brito -c # resume the most recent session in this project
145
+ brito sessions # list saved sessions; resume one with brito --resume <id>
146
+ brito slm pull # (optional) download the local model used by digest and skill learning
147
+ brito query "MATCH (c:Symbol {kind:'component'})-[:CALLS]->(f:Symbol) RETURN c.file, f.name LIMIT 5"
148
+ ```
149
+
150
+ A real `brito index` on the sample project above:
151
+
152
+ ```
153
+ OK: 20 arquivos, 66 símbolos, 54 chamadas, 17 imports | +0 ~0 -0 =20 (28ms)
154
+ ```
155
+
156
+ ![Brito start screen](docs/images/startup.png)
157
+
158
+ ### Inside the REPL
159
+
160
+ | Command | What it does |
161
+ |---|---|
162
+ | `/help` | list commands |
163
+ | `/model`, `/effort`, `/reasoning` | choose model, reasoning effort and thinking (session, global or once) |
164
+ | `/fallback` | shows the main model and the fallback (qwen), and whether the switch already happened |
165
+ | `/modo` or `Shift+Tab` | switch permission mode: manual → auto-edits → plan → bypass ("everything allowed") |
166
+ | `/skills` | list skills · `pending` · `approve <name>` · `reject <name>` · `consolidate` · `rm <name>` · `promote <name>` |
167
+ | `/permissions` | list permission rules · `allow <rule>` · `deny <rule>` |
168
+ | `/learn` | extract skills from the last turn now |
169
+ | `/grill-me`, `/grill-with-docs`, `/wayfinder`, `/grill-diff` | built-in manual skills: interview you until the idea is firm (`--um` = one question per message), also save decisions with `remember`, map big work and delegate, question the current diff |
170
+ | `/skills suggest <task>` | rank skills (built-ins included) by relevance to a task |
171
+ | `/agents`, `/tools`, `/index`, `/context` | inspect subagents, tools, the index and the context window |
172
+ | `!command` | run a shell command directly, without calling the model |
173
+ | `/todos` | show the session's task list (the agent keeps it with `todo_write` on multi-step tasks) |
174
+ | `/sessions` | list this project's saved sessions |
175
+ | `/clear`, `/exit` | start another conversation (the previous one stays saved), quit |
176
+
177
+ ## What the graph indexes
178
+
179
+ - **Languages:** TypeScript/JavaScript (`.ts .tsx .mts .cts .js .jsx .mjs .cjs`), Python (`.py`), backend languages — Java (`.java`), Kotlin (`.kt`), Go (`.go`), Ruby (`.rb`), PHP (`.php`), C# (`.cs`), Rust (`.rs`) — and the `.svelte`, `.vue` and `.astro` components. In components Brito reads the script block(s) (and Astro's frontmatter) and records calls made from the template to functions the script declares or imports; each component becomes a `component` symbol.
180
+ - **Scope:** inside a git repository, only what git considers part of the project (tracked + untracked-but-not-ignored), so anything in `.gitignore` stays out. Outside git, or with `BRITO_INDEX_IGNORED=1`, it indexes by glob (still skipping `node_modules`, `dist`, `build`, `target`, `vendor`, `obj`, `.gradle`, `.venv`, `.brito`).
181
+ - **Imports:** relative and aliased. Resolves `paths`/`baseUrl` from `tsconfig.json`/`jsconfig.json` (following relative `extends`, like `.svelte-kit/tsconfig.json`), `package.json` `imports` (`#internal/*`) and SvelteKit's `$lib`. Configuration applies per file (nearest config), so monorepos work; editing a tsconfig re-indexes the affected files.
182
+ - **Backend languages:** the graph holds classes/interfaces/structs/traits/enums/modules, functions and methods (`Class.method`), calls and imports. Imports name a package, not a path, so Brito matches them against the end of your files' paths (`com.acme.Repo` ↔ `src/main/java/com/acme/Repo.java`; PHP PSR-4 namespaces; Rust `use crate::…`; Ruby `require`/`require_relative`; Go packages through the `go.mod` module path). External packages (`java.util`, `serde`, `github.com/gin-gonic/gin`) never match and create no edges. There is no type inference: a call like `userRepository.save()` is linked by matching the receiver name to a type in the project (`UserRepository`), `this`/`self`/receivers resolve to the enclosing class, and a bare call inside a class tries the class's own methods first.
183
+ - **Not yet:** `extends` by package (`@tsconfig/node20`), sibling-workspace `exports`, and function references without a call in a template (`onclick={fn}`). Calls are resolved statically with name-based fallbacks, so dynamic dispatch and reflection are not captured.
184
+
185
+ ## Permission rules
186
+
187
+ To stop approving the same command every time (without resorting to "everything allowed"), declare rules in `.brito/settings.json` (per project, can be committed), `.brito/settings.local.json` (just you) or `~/.brito/settings.json` (all projects). The lists add up.
188
+
189
+ ```json
190
+ {
191
+ "permissions": {
192
+ "allow": ["bash(npm test:*)", "bash(npm run typecheck)", "bash(git status:*)", "edit_file(src/**)"],
193
+ "deny": ["bash(git push:*)", "bash(rm -rf*)", "read_file(.env*)"]
194
+ }
195
+ }
196
+ ```
197
+
198
+ - `tool` matches any use; `tool(pattern)` narrows it. In `bash`, `*` matches anything and a trailing `:*` matches the prefix alone or followed by arguments (`git status:*` allows `git status --short`, not `git statusx`). In paths, `*` does not cross directories and `**` does.
199
+ - **`allow` skips the prompt** in manual and auto-edits modes. Plan mode still blocks.
200
+ - **`deny` always blocks**, even in "everything allowed".
201
+ - A compound command is allowed only if **every piece** (`&&`, `||`, `;`, `|`) matches a rule: `bash(npm test*)` does not allow `npm test && rm -rf ~`. Commands with `$(...)`, backticks or redirection to a file are never allowed by a rule; `2>&1` and `> /dev/null` are fine.
202
+ - The rules also apply to the `claude` CLI's Bash, Edit and Write when Brito runs on your subscription.
203
+ - `/permissions` lists the rules; `/permissions allow bash(npm test:*)` writes to `.brito/settings.json`.
204
+
205
+ ## Databases and other sensitive resources
206
+
207
+ Brito has **no database drivers and connects to nothing on its own**. When it needs to touch a database, it uses your project's own tooling through the shell, under the permission mode you chose. Because every project is different (a local file, a remote server, a container), declare the sensitive parts in `BRITO.md` (or `CLAUDE.md` / `AGENTS.md`), which is read into the system prompt:
208
+
209
+ ```markdown
210
+ ## Protected resources
211
+ - Database: local SQLite file `local.db` (never commit, never recreate).
212
+ Test destructive changes on a copy: `cp local.db /tmp/test.db` and set `DATABASE_URL`.
213
+ Schema changes: additive only, back up first (`cp local.db backups/pre-change.db`).
214
+ - Staging Postgres: connection string is in `$STAGING_DATABASE_URL` (read-only role). Never touch production.
215
+ ```
216
+
217
+ - Credentials never belong in skills or notes: the lint rejects them. Cite the **name** of the environment variable instead.
218
+ - Prefer read-only roles and non-production environments when you give an agent database access.
219
+ - A proposed skill that contains a destructive command is highlighted at review time, so you decide whether it needs a guard (backup, copy, confirmation).
220
+
221
+ ## OpenAI-compatible endpoint (e.g. Qwen on OCI)
222
+
223
+ > Full step-by-step (install, key, profile, and how to give people access to the repository, in Portuguese): [docs/GUIA-QWEN.md](docs/GUIA-QWEN.md).
224
+
225
+ Besides Claude, Brito runs on any model served through the OpenAI **Chat Completions** API (vLLM, OCI Generative AI, LiteLLM, Ollama…) with tool calling. Add a profile to `~/.brito/config.json`:
226
+
227
+ ```json
228
+ {
229
+ "providers": {
230
+ "qwen": {
231
+ "type": "openai",
232
+ "label": "Qwen 27B (OCI)",
233
+ "baseURL": "https://inference.generativeai.<region>.oci.oraclecloud.com/openai/v1",
234
+ "model": "<model id; on OCI, the dedicated endpoint OCID>",
235
+ "apiKeyEnv": "BRITO_QWEN_API_KEY",
236
+ "contextWindow": 262144,
237
+ "vision": false,
238
+ "thinkingToggle": true
239
+ }
240
+ }
241
+ }
242
+ ```
243
+
244
+ The key is **not** stored in the config: put it in the environment variable named by `apiKeyEnv`. Then:
245
+
246
+ ```bash
247
+ brito --model qwen # this session
248
+ /model qwen --global # inside the REPL: make it the default
249
+ ```
250
+
251
+ With a profile selected, **everything** goes to the endpoint: main agent, subagents (`explore` stops using Haiku), context summaries and skill learning; Brito starts without `ANTHROPIC_API_KEY` and without the `claude` CLI. `/reasoning none` turns the model's reasoning off (much faster answers on Qwen). `thinkingToggle: true` only for servers that accept `chat_template_kwargs` (vLLM/Qwen); without it `/reasoning none` has no effect, but no unknown parameter is sent. Images are only sent with `"vision": true`. Deliberate exception: `BRITO_EXPLORE_MODEL` still decides the `explore` subagent; a `BRITO_LEARN_MODEL` pointing at Claude is ignored while a profile is active. A broken profile in the config never falls back to Claude: Brito warns and stops. `/effort` stays exclusive to `claude` CLI mode, and a profile does not run inside the `claude` CLI (`/model` tells you to reopen with `--model`).
252
+
253
+ ### Fallback to Qwen
254
+
255
+ With Claude as the main model (API or `claude` CLI), the `qwen` profile is the automatic fallback — always that one, no new config key. If Claude fails because of a **subscription limit, rate limit, credit, authentication, overload or network** error, Brito warns and redoes the request on Qwen with the conversation so far (tools that already ran stay in the history, so they are not repeated). In `claude` CLI mode the whole engine switches to Brito's own loop.
256
+
257
+ - The switch happens once per session and never reverts on its own: `/model <claude>` goes back to Claude (and the fallback can trigger again later).
258
+ - It does not switch on Ctrl+C or on content errors (invalid request, `max_tokens`, broken tool).
259
+ - Without `ANTHROPIC_API_KEY` and without the `claude` CLI, Brito opens straight on Qwen, with a warning. If the fallback is not ready, the usual error includes why (e.g. `BRITO_QWEN_API_KEY` is missing). An invalid `qwen` profile is still an error, never a silent fallback.
260
+ - `/fallback` shows the state. In the desktop app, send `/fallback` as a message; the status bar shows Qwen while the fallback is active.
261
+
262
+ ## Configuration
263
+
264
+ `BRITO_MODEL`, `BRITO_EFFORT`, `BRITO_EXPLORE_MODEL`, `BRITO_LEARN_MODEL`, `BRITO_HOME` (where global skills and history live), `BRITO_CONFIG`, `BRITO_COLOR`, `BRITO_BANNER` (`compact` or `full`; default: full screen on windows of 95+ columns and 28+ rows), `BRITO_INDEX_IGNORED`, `BRITO_SKILL_MIN_TOOLS` (how long a turn must be to trigger reflection when nothing else does), `BRITO_SKILLS` (`auto` default, `ask`, `off`), `BRITO_SHELL` (shell used by the `bash` tool; on Windows defaults to Git Bash when installed).
265
+
266
+ Project data lives in `.brito/` (graph, project skills, agents) and global data in `~/.brito`. The graph, memory and skills stay on your machine; as with any coding agent, the code the model reads is sent to the model provider you configured.
267
+
268
+ ## Limitations
269
+
270
+ - Early software (v0.5.0), one maintainer.
271
+ - The desktop app is new: a single window (no tabs yet). API-mode conversations from before this version are not resumed when you reopen the app (new ones are, from `.brito/sessions`).
272
+ - **The interface and the agent's default language are Brazilian Portuguese.** Translating them is a welcome contribution.
273
+ - Skill learning is a heuristic: it proposes, you decide. Expect some proposals to be rejected.
274
+
275
+ ## Development
276
+
277
+ ```bash
278
+ git clone https://github.com/wilsonbrito/brito && cd brito
279
+ npm install
280
+ npm run dev # runs via tsx
281
+ npm run typecheck
282
+ npm test # 190+ tests, including a real MCP server and a real REPL
283
+ ```
284
+
285
+ | Path | What |
286
+ |---|---|
287
+ | `src/graph/` | indexer (tree-sitter), `.svelte/.vue/.astro` support, import aliases, Ladybug (Kùzu) store |
288
+ | `src/skills/` | store, lint, reflection, journal, consolidation |
289
+ | `src/agent/` | agent loop, prompts, subagents, `claude` CLI backend |
290
+ | `src/tools/` | graph, memory, skills, filesystem and shell tools |
291
+ | `src/mcp/` | MCP server |
292
+ | `src/repl.ts`, `src/ui/` | terminal interface |
293
+ | `src/desktop/` | `brito gui-serve`: the backend the desktop window talks to (JSON over stdio) |
294
+ | `desktop/` | Electron window and packaging (`package.mjs`); `npm run bundle` builds the single-file backend it uses |
295
+
296
+ ## License
297
+
298
+ [PolyForm Noncommercial 1.0.0](LICENSE): free to use, study and modify for any noncommercial purpose (personal use, research, education, hobby, nonprofits). Commercial use is not permitted. This is source-available, not OSI open source. Need a commercial license? Open an issue.