@cam5/baby-bird 0.1.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 +205 -0
- package/dist/chunk-RWSCST2I.js +1753 -0
- package/dist/chunk-RWSCST2I.js.map +1 -0
- package/dist/cli.js +326 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +648 -0
- package/dist/index.js +107 -0
- package/dist/index.js.map +1 -0
- package/package.json +62 -0
package/README.md
ADDED
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
# baby-bird 🐣
|
|
2
|
+
|
|
3
|
+
Guided **code tours** for git changes, on the command line.
|
|
4
|
+
|
|
5
|
+
`bb` looks at a change (a branch, a range, or your working tree), asks an LLM to organize it into an ordered set of sections, and renders the result in your terminal: each section has a title, a description of *why* and *what*, the files it touches with `+/-` counts, and excerpts pulled from the real diff. Tours are cached by content, so the model runs once per change.
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
🐣 Add a shell-command LLM provider with presets
|
|
9
|
+
feat/llm-presets vs main (merge-base 4e2a1c9) · base from pull request
|
|
10
|
+
PR #12: Add LLM presets https://github.com/you/repo/pull/12
|
|
11
|
+
6 files · +412 -18 · 4 sections · claude-sonnet, generated just now
|
|
12
|
+
|
|
13
|
+
Presets let people pick a model and effort level without hand-writing a
|
|
14
|
+
command line, while still allowing a fully custom invocation ...
|
|
15
|
+
|
|
16
|
+
Contents
|
|
17
|
+
1. The preset table and how it resolves 2 files · +96 -4
|
|
18
|
+
2. Running any CLI as the model 1 file · +93 -0
|
|
19
|
+
3. Config cascade: user, project, env, flags 2 files · +120 -14
|
|
20
|
+
4. Tests 1 file · +103 -0
|
|
21
|
+
|
|
22
|
+
────────────────────────────────────────────────────────────────────
|
|
23
|
+
1. The preset table and how it resolves (1/4)
|
|
24
|
+
2 files · +96 -4
|
|
25
|
+
|
|
26
|
+
Presets are named argv templates. Resolution is: an explicit
|
|
27
|
+
`llm.command` wins, otherwise the named preset (user-defined
|
|
28
|
+
presets shadow built-ins), then `llm.args` are appended ...
|
|
29
|
+
|
|
30
|
+
src/core/config.ts
|
|
31
|
+
src/index.ts
|
|
32
|
+
|
|
33
|
+
src/core/config.ts:24 The built-in presets, all targeting the Claude Code CLI
|
|
34
|
+
22 24 │ const CLAUDE_BASE = ['claude', '-p', '--bare', ...
|
|
35
|
+
25 │+export const BUILTIN_PRESETS = Object.freeze({
|
|
36
|
+
...
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Install
|
|
40
|
+
|
|
41
|
+
```sh
|
|
42
|
+
pnpm add -g @cam5/baby-bird # or: npm i -g @cam5/baby-bird
|
|
43
|
+
bb --help
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Requirements: Node 22+, git, and some CLI that can answer a prompt (by default the [Claude Code](https://claude.com/claude-code) CLI, `claude`).
|
|
47
|
+
|
|
48
|
+
## Usage
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
bb tour the current branch
|
|
52
|
+
bb main..feature tour an explicit range
|
|
53
|
+
bb main...feature same, from the merge-base
|
|
54
|
+
bb HEAD~3 tour the last three commits
|
|
55
|
+
bb release/2.0 what HEAD adds on top of release/2.0 (merge-base semantics)
|
|
56
|
+
bb --working uncommitted changes (tracked + untracked)
|
|
57
|
+
bb --staged what you are about to commit
|
|
58
|
+
bb --section 2 render only the second section
|
|
59
|
+
bb --json | jq machine-readable tour
|
|
60
|
+
bb --dump-prompt print the prompt instead of calling the model
|
|
61
|
+
bb --refresh regenerate even if a cached tour exists
|
|
62
|
+
bb --preset claude-sonnet
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### What does bare `bb` tour?
|
|
66
|
+
|
|
67
|
+
1. If the working tree has uncommitted changes: those.
|
|
68
|
+
2. Else, if the code host knows a pull request for this branch (`gh pr view`): the branch against the PR's base, and the PR title/body are fed to the model.
|
|
69
|
+
3. Else, the branch against its nearest ancestor branch (the local branch whose merge-base is closest to `HEAD`).
|
|
70
|
+
4. Else, the branch against the default branch (`origin/HEAD`, or `main`/`master`/`trunk`).
|
|
71
|
+
|
|
72
|
+
The header of every tour says which one was used.
|
|
73
|
+
|
|
74
|
+
## Configuration
|
|
75
|
+
|
|
76
|
+
Config is JSON, merged in this order (later wins; objects merge, arrays replace):
|
|
77
|
+
|
|
78
|
+
1. built-in defaults
|
|
79
|
+
2. `$XDG_CONFIG_HOME/baby-bird/config.json` (default `~/.config/baby-bird/config.json`)
|
|
80
|
+
3. `<repo>/.baby-bird/config.json` (create one with `bb init`)
|
|
81
|
+
4. environment: `BB_PRESET`, `BB_LLM_COMMAND`, `BB_CODEHOST`, `BB_CACHE_DIR`, `BB_NO_CACHE`, `NO_COLOR`
|
|
82
|
+
5. flags: `--preset`, `--color/--no-color`, `--no-cache`, `--no-pager`
|
|
83
|
+
|
|
84
|
+
`bb config` shows every layer, what it contributed, the resolved LLM command, and all presets.
|
|
85
|
+
|
|
86
|
+
All keys, with defaults:
|
|
87
|
+
|
|
88
|
+
```jsonc
|
|
89
|
+
{
|
|
90
|
+
"llm": {
|
|
91
|
+
"preset": "claude", // which preset to run (built-in or from "presets")
|
|
92
|
+
"presets": {}, // your own presets; same names shadow built-ins
|
|
93
|
+
"args": [], // extra argv appended to the preset's command
|
|
94
|
+
"command": null, // a whole custom invocation; when set, "preset" is ignored
|
|
95
|
+
"promptVia": null, // "stdin" (default) or "arg" (replace {prompt} in argv)
|
|
96
|
+
"timeoutMs": 180000,
|
|
97
|
+
"maxPromptBytes": 200000, // larger diffs are truncated, biggest files first
|
|
98
|
+
"env": {} // extra environment for the command
|
|
99
|
+
},
|
|
100
|
+
"codehost": { "provider": "gh" }, // "gh" or "none"
|
|
101
|
+
"git": {
|
|
102
|
+
"defaultBranch": null, // auto-detect
|
|
103
|
+
"exclude": ["**/pnpm-lock.yaml", "**/package-lock.json", "**/yarn.lock", "**/Cargo.lock",
|
|
104
|
+
"**/*.min.*", "**/dist/**", "**/*.snap", "**/*.map"]
|
|
105
|
+
},
|
|
106
|
+
"render": { "color": "auto", "pager": "auto", "maxExcerptLines": 60, "width": null },
|
|
107
|
+
"cache": { "enabled": true, "dir": null } // default $XDG_CACHE_HOME/baby-bird
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### LLM presets
|
|
112
|
+
|
|
113
|
+
The model is just a command: the prompt goes in on stdin, the answer comes out on stdout. Built-in presets:
|
|
114
|
+
|
|
115
|
+
| preset | runs |
|
|
116
|
+
|---|---|
|
|
117
|
+
| `claude` (default) | `claude -p --no-session-persistence --setting-sources "" --tools ""` |
|
|
118
|
+
| `claude-sonnet` | the above plus `--model sonnet --effort high` |
|
|
119
|
+
| `claude-opus` | the above plus `--model opus --effort high` |
|
|
120
|
+
| `claude-fable` | the above plus `--model fable --effort high` |
|
|
121
|
+
| `claude-haiku` | the above plus `--model haiku` |
|
|
122
|
+
| `llm` | `llm` ([Simon Willison's CLI](https://llm.datasette.io/)) |
|
|
123
|
+
|
|
124
|
+
Add flags to a preset, define your own, or replace the command entirely:
|
|
125
|
+
|
|
126
|
+
```jsonc
|
|
127
|
+
{
|
|
128
|
+
"llm": {
|
|
129
|
+
"preset": "claude-sonnet",
|
|
130
|
+
"args": ["--fallback-model", "haiku"],
|
|
131
|
+
"presets": {
|
|
132
|
+
"local": { "command": ["ollama", "run", "qwen2.5-coder:14b"] },
|
|
133
|
+
"gemini": { "command": ["gemini", "-p", "{prompt}"], "promptVia": "arg" }
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
```sh
|
|
140
|
+
bb --preset local
|
|
141
|
+
BB_LLM_COMMAND='llm -m gpt-4.1' bb
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
The effective command is part of the cache key, so switching presets regenerates the tour instead of reusing another model's.
|
|
145
|
+
|
|
146
|
+
### Code host
|
|
147
|
+
|
|
148
|
+
With `codehost.provider` set to `gh` (the default), `bb` uses the `gh` CLI to find the current branch's pull request. Its base branch decides what to compare against and its title and body are included in the prompt. Nothing else is read, and no tokens are handled by `bb`. If `gh` is missing or not logged in, the lookup is silently skipped. Set the provider to `none` to turn it off.
|
|
149
|
+
|
|
150
|
+
### Cache
|
|
151
|
+
|
|
152
|
+
Tours are stored as JSON under `$XDG_CACHE_HOME/baby-bird/tours/` (default `~/.cache/baby-bird/tours/`), keyed by a hash of the exact prompt (which encodes the diff content, PR text, commit subjects, and prompt version) plus the LLM command.
|
|
153
|
+
|
|
154
|
+
```
|
|
155
|
+
bb cache ls # what is cached
|
|
156
|
+
bb cache clear
|
|
157
|
+
bb cache path
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## How a tour is built
|
|
161
|
+
|
|
162
|
+
1. Resolve what to compare (see above) and collect the unified diff, commit subjects, and PR text.
|
|
163
|
+
2. Assemble the prompt: rules, the output contract, a file table, and the diff with every hunk labeled `[F3.H2]`. Over-budget prompts are shortened biggest-file-first.
|
|
164
|
+
3. Run the LLM command. The model returns sections that *reference* hunks by id; it never reproduces code. If the reply isn't valid JSON for the schema, one repair round-trip is attempted.
|
|
165
|
+
4. Materialize: excerpts are sliced from the real diff, counts are computed locally, and any file the model did not mention lands in a final "Other changes" section.
|
|
166
|
+
5. Cache and render.
|
|
167
|
+
|
|
168
|
+
`bb --dump-prompt` prints step 2's output, which is the fastest way to iterate on the prompt (`src/core/prompt/template.ts`).
|
|
169
|
+
|
|
170
|
+
## Using it as a library
|
|
171
|
+
|
|
172
|
+
The CLI is one consumer of a small core. `import { generateTour, CliRenderer, type Tour } from '@cam5/baby-bird'` gives you the same pipeline for a TUI, a web view, or a bot; a `Tour` is plain JSON (sections, stats, excerpts) with no git or LLM dependencies.
|
|
173
|
+
|
|
174
|
+
## Development
|
|
175
|
+
|
|
176
|
+
```sh
|
|
177
|
+
pnpm install
|
|
178
|
+
pnpm dev -- --help # run from source
|
|
179
|
+
pnpm test # vitest: unit + integration (uses temp git repos and a fake LLM)
|
|
180
|
+
pnpm typecheck
|
|
181
|
+
pnpm build # dist/ via tsup
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## Releasing
|
|
185
|
+
|
|
186
|
+
Releases are cut by pushing a version tag. The `release` workflow checks that the tag matches `package.json`, runs typecheck, tests and build, publishes to npm with provenance (via npm trusted publishing, so no token is stored), and creates a GitHub Release with generated notes.
|
|
187
|
+
|
|
188
|
+
```sh
|
|
189
|
+
npm version patch # or minor / major: bumps package.json, commits, tags vX.Y.Z
|
|
190
|
+
git push --follow-tags
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## Exit codes
|
|
194
|
+
|
|
195
|
+
| code | meaning |
|
|
196
|
+
|---|---|
|
|
197
|
+
| 0 | ok |
|
|
198
|
+
| 2 | usage or configuration error |
|
|
199
|
+
| 3 | not a git repository, or nothing to tour |
|
|
200
|
+
| 4 | the LLM command failed to run |
|
|
201
|
+
| 5 | the model's output was unusable even after a repair attempt |
|
|
202
|
+
|
|
203
|
+
## License
|
|
204
|
+
|
|
205
|
+
MIT
|