ReviewOS

also looking at this

stacks/buddy

docs: replace the claims the source does not support

#1400
Merged glennmichael123 wants to merge docs/correct-unsupported-claims into main
32 files +1660 -1772

Review threads live on the whole diff, not on one commit, so none are shown here - a thread's line means something in the branch's final form, and painting it into an intermediate step would put it on code it is not about.

CLAUDE.mdmodified+12-12
Changes to CLAUDE.md
@@ -955,17 +955,17 @@ Choose from several carefully crafted presets with smart recommendations:
955955
956956#### 📝 Step 7: Enhanced Configuration Generation
957957
958- Creates `buddy.config.json` with repository-specific settings
958- Creates `buddy.config.ts` with repository-specific settings
959959- **Project-aware defaults** - Configuration optimized for detected project type
960960- **Ecosystem integration** - Includes detected package managers and dependency files
961961- Includes sensible defaults and customization options
962962
963963**�� Step 8: Workflow Generation & Validation**
964964
965- Generates three core GitHub Actions workflows:
966 - `buddy-dashboard.yml` - Dependency Dashboard Management
967 - `buddy-check.yml` - Auto-rebase PR checker
968 - `buddy-update.yml` - Scheduled dependency updates
965- Generates two GitHub Actions workflows:
966 - `buddy.yml` - Unified workflow: rebase checks, scheduled updates and the dashboard
967 - `buddy-security.yml` - Security audit, kept separate so it triggers on its own path filters
968- Removes the stale `buddy-check.yml`, `buddy-update.yml`, `buddy-dashboard.yml` and `gh-audit.yml` if an earlier version left them behind
969969- **YAML validation** - Ensures generated workflows are syntactically correct
970970- **Security best practices** - Validates token usage and permissions
971971- **Workflow testing** - Verifies generated workflows meet requirements
@@ -1018,7 +1018,7 @@ buddy update-check --dry-run
10181018buddy update-check --verbose
10191019
10201020# Get help
1021buddy help
1021buddy --help
10221022```
10231023
10241024### Configuration
@@ -1281,7 +1281,7 @@ All Buddy pull requests include a rebase checkbox at the bottom:
12811281### Using the Rebase Feature
12821282
128312831. **Check the box**: In any Buddy PR, check the rebase checkbox
12842. **Automatic detection**: The rebase workflow runs every minute to detect checked boxes
12842. **Automatic detection**: Editing the PR body fires the workflow, which detects the checked box
128512853. **Updates applied**: The PR is automatically updated with the latest dependency versions
128612864. **Checkbox unchecked**: After successful rebase, the checkbox is automatically unchecked
12871287
@@ -1302,9 +1302,9 @@ buddy update-check --verbose
13021302
13031303### Automated Rebase Workflow
13041304
1305Buddy includes a pre-built GitHub Actions workflow (`.github/workflows/buddy-check.yml`) that:
1305Buddy includes a pre-built GitHub Actions workflow (`.github/workflows/buddy.yml`) that:
13061306
1307- **�� Runs every minute**: Automatically checks for rebase requests
1307- **�� Event-driven**: Triggers on `pull_request: [edited]` and `issues: [edited]`, so ticking a checkbox runs it immediately — no polling
13081308- **�� Scans all PRs**: Finds Buddy PRs with checked rebase boxes
13091309- **�� Updates dependencies**: Re-scans for latest versions and updates files
13101310- **�� Updates PR content**: Refreshes PR title, body, and file changes
@@ -1346,9 +1346,9 @@ buddy dashboard --title "My Dependencies"
13461346
13471347### Automated Dashboard Updates
13481348
1349Buddy includes a pre-built GitHub workflow (`.github/workflows/buddy-dashboard.yml`) that automatically updates your dependency dashboard:
1349Buddy includes a pre-built GitHub workflow (`.github/workflows/buddy.yml`) that automatically updates your dependency dashboard:
13501350
1351- **�� Scheduled**: Runs Monday, Wednesday, Friday at 9 AM UTC
1351- **�� Scheduled**: Every 2 hours, 15 minutes after the dependency update run (cron `15 */2 * * *`)
13521352- **��️ Manual**: Trigger from Actions tab with custom options
13531353- **�� Auto-Pin**: Keeps dashboard pinned by default
13541354- **�� Dry-Run**: Preview mode available
@@ -1423,7 +1423,7 @@ Buddy automatically detects and updates the following dependency file formats:
14231423- **.github/workflows/*.yml** - GitHub Actions workflow files
14241424- **.github/workflows/*.yaml** - Alternative YAML extension
14251425
1426All dependency files are parsed using the `ts-pkgx` library to ensure compatibility with the pkgx registry ecosystem while maintaining support for tools like Launchpad that reuse the same registry format. GitHub Actions are detected by parsing `uses:` statements in workflow files and checking for updates via the GitHub releases API.
1426All dependency files are parsed using the `ts-pantry` library to ensure compatibility with the pkgx registry ecosystem while maintaining support for tools like Launchpad that reuse the same registry format. GitHub Actions are detected by parsing `uses:` statements in workflow files and checking for updates via the GitHub releases API.
14271427
14281428### Pull Request Format
14291429
README.mdmodified+19-19
Changes to README.md
@@ -26,7 +26,7 @@ Neither half requires the other. Run the reviewer with no dependency workflows,
2626
2727- **Inline Findings**: _Anchored to changed lines, describing the failure rather than a style preference_
2828- **Incremental by Default**: _A second push gets new findings, not the ones you already read_
29- **Conversational**: _`@buddy review`, `full-review`, `summary`, `resolve`, `pause`, `resume`, `plan`, `remember` — or just ask a question_
29- **Conversational**: _`@buddy review`, `full-review`, `summary`, `pause`, `resume`, `rebase`, `remember` — or just ask a question_
3030- **Local Review**: _`buddy review` reads your working tree, so problems are found before the PR exists_
3131- **Works Without a Key**: _`--light` runs secret scanning, actionlint, shellcheck, hadolint, markdownlint and syntax checks with no model and no network_
3232- **Merge Gates**: _Title format, description quality, linked issue and dependency policy published as a check run_
@@ -206,17 +206,17 @@ Choose from several carefully crafted presets with smart recommendations:
206206
207207#### 📝 Step 7: Enhanced Configuration Generation
208208
209- Creates `buddy.config.json` with repository-specific settings
209- Creates `buddy.config.ts` with repository-specific settings
210210- **Project-aware defaults** - Configuration optimized for detected project type
211211- **Ecosystem integration** - Includes detected package managers and dependency files
212212- Includes sensible defaults and customization options
213213
214214**�� Step 8: Workflow Generation & Validation**
215215
216- Generates three core GitHub Actions workflows:
217 - `buddy-dashboard.yml` - Dependency Dashboard Management
218 - `buddy-check.yml` - Auto-rebase PR checker
219 - `buddy-update.yml` - Scheduled dependency updates
216- Generates two GitHub Actions workflows:
217 - `buddy.yml` - Unified workflow (rebase checks, dependency updates, dashboard management)
218 - `buddy-security.yml` - Security audit, kept separate so it can trigger on its own path filters
219- Removes stale `buddy-check.yml`, `buddy-update.yml` and `buddy-dashboard.yml` files from earlier versions
220220- **YAML validation** - Ensures generated workflows are syntactically correct
221221- **Security best practices** - Validates token usage and permissions
222222- **Workflow testing** - Verifies generated workflows meet requirements
@@ -269,7 +269,7 @@ buddy update-check --dry-run
269269buddy update-check --verbose
270270
271271# Get help
272buddy help
272buddy --help
273273```
274274
275275### Configuration
@@ -532,7 +532,7 @@ All Buddy pull requests include a rebase checkbox at the bottom:
532532### Using the Rebase Feature
533533
5345341. **Check the box**: In any Buddy PR, check the rebase checkbox
5352. **Automatic detection**: The rebase workflow runs every minute to detect checked boxes
5352. **Automatic detection**: Editing the PR body fires the workflow, which detects the checked box
5365363. **Updates applied**: The PR is automatically updated with the latest dependency versions
5375374. **Checkbox unchecked**: After successful rebase, the checkbox is automatically unchecked
538538
@@ -553,9 +553,9 @@ buddy update-check --verbose
553553
554554### Automated Rebase Workflow
555555
556Buddy includes a pre-built GitHub Actions workflow (`.github/workflows/buddy-check.yml`) that:
556Buddy includes a pre-built GitHub Actions workflow (`.github/workflows/buddy.yml`) that:
557557
558- **�� Runs every minute**: Automatically checks for rebase requests
558- **�� Event-driven**: Triggers on `pull_request: [edited]` and `issues: [edited]`, so ticking a checkbox runs it immediately — no polling
559559- **�� Scans all PRs**: Finds Buddy PRs with checked rebase boxes
560560- **�� Updates dependencies**: Re-scans for latest versions and updates files
561561- **�� Updates PR content**: Refreshes PR title, body, and file changes
@@ -598,9 +598,9 @@ buddy dashboard --title "My Dependencies"
598598
599599### Automated Dashboard Updates
600600
601Buddy includes a pre-built GitHub workflow (`.github/workflows/buddy-dashboard.yml`) that automatically updates your dependency dashboard:
601The unified workflow (`.github/workflows/buddy.yml`) automatically updates your dependency dashboard:
602602
603- **�� Scheduled**: Runs Monday, Wednesday, Friday at 9 AM UTC
603- **�� Scheduled**: Runs every 2 hours, 15 minutes after the dependency update run
604604- **��️ Manual**: Trigger from Actions tab with custom options
605605- **�� Auto-Pin**: Keeps dashboard pinned by default
606606- **�� Dry-Run**: Preview mode available
@@ -684,7 +684,7 @@ Detected anywhere in the tree, in all three naming conventions:
684684- `<prefix>.dockerfile` - e.g. `docker/api.dockerfile`, common in monorepos
685685- `Containerfile`, `<prefix>.containerfile` - the OCI/Podman spelling
686686
687All dependency files are parsed using the `ts-pkgx` library to ensure compatibility with the pkgx registry ecosystem while maintaining support for tools like Launchpad that reuse the same registry format. GitHub Actions are detected by parsing `uses:` statements in workflow files and checking for updates via the GitHub releases API.
687All dependency files are parsed using the `ts-pantry` library to ensure compatibility with the pkgx registry ecosystem while maintaining support for tools like Launchpad that reuse the same registry format. GitHub Actions are detected by parsing `uses:` statements in workflow files and checking for updates via the GitHub releases API.
688688
689689### Pull Request Format
690690
@@ -748,8 +748,8 @@ Each table is followed by detailed release notes, changelogs, and package statis
748748
749749- **`all`**: Update all dependencies regardless of semver impact
750750- **`major`**: Only major version updates
751- **`minor`**: Major and minor updates (no patch-only)
752- **`patch`**: All updates (major, minor, and patch)
751- **`minor`**: Minor and patch updates (no majors)
752- **`patch`**: Only patch updates
753753
754754## Auto-Merge Configuration
755755
@@ -1033,7 +1033,7 @@ bun run build
10331033
10341034## Changelog
10351035
1036Please see our [releases](https://github.com/stacksjs/stacks/releases) page for more information on what has changed recently.
1036Please see our [releases](https://github.com/stacksjs/buddy/releases) page for more information on what has changed recently.
10371037
10381038## Contributing
10391039
@@ -1043,7 +1043,7 @@ Please see the [Contributing Guide](https://github.com/stacksjs/contributing) fo
10431043
10441044For help, discussion about best practices, or any other conversation that would benefit from being searchable:
10451045
1046[Discussions on GitHub](https://github.com/stacksjs/stacks/discussions)
1046[Discussions on GitHub](https://github.com/stacksjs/buddy/discussions)
10471047
10481048For casual chit-chat with others using this package:
10491049
@@ -1078,8 +1078,8 @@ The MIT License (MIT). Please see [LICENSE](LICENSE.md) for more information.
10781078Made with ��
10791079
10801080<!-- Badges -->
1081[npm-version-src]: https://img.shields.io/npm/v/buddy?style=flat-square
1082[npm-version-href]: https://npmjs.com/package/buddy
1081[npm-version-src]: https://img.shields.io/npm/v/%40buddysh%2Fbuddy?style=flat-square
1082[npm-version-href]: https://npmjs.com/package/%40buddysh%2Fbuddy
10831083[github-actions-src]: https://img.shields.io/github/actions/workflow/status/stacksjs/buddy/ci.yml?style=flat-square&branch=main
10841084[github-actions-href]: https://github.com/stacksjs/buddy/actions?query=workflow%3Aci
10851085
docs/advanced/migration.mdmodified+2-3
Changes to docs/advanced/migration.md
@@ -191,9 +191,8 @@ Buddy automatically generates optimized GitHub Actions workflows:
191191buddy setup
192192
193193# Generated files
194# .github/workflows/buddy-dashboard.yml
195# .github/workflows/buddy-check.yml
196# .github/workflows/buddy-update.yml
194# .github/workflows/buddy.yml — checks, updates and the dashboard
195# .github/workflows/buddy-security.yml — the security audit
197196```
198197
199198### Removing Old Configurations
docs/advanced/migration/dependabot.mdmodified+2-3
Changes to docs/advanced/migration/dependabot.md
@@ -376,9 +376,8 @@ buddy dashboard
376376
377377Check generated GitHub Actions:
378378
379- `.github/workflows/buddy-dashboard.yml`
380- `.github/workflows/buddy-check.yml`
381- `.github/workflows/buddy-update.yml`
379- `.github/workflows/buddy.yml` — the unified workflow: rebase checks, dependency updates and the dashboard
380- `.github/workflows/buddy-security.yml` — the security audit, kept separate so it triggers on its own path filters
382381
383382### 6. Monitor and Adjust
384383
docs/advanced/migration/renovate.mdmodified+2-3
Changes to docs/advanced/migration/renovate.md
@@ -360,9 +360,8 @@ buddy update --dry-run
360360
361361Check the generated GitHub Actions workflows:
362362
363- `.github/workflows/buddy-dashboard.yml`
364- `.github/workflows/buddy-check.yml`
365- `.github/workflows/buddy-update.yml`
363- `.github/workflows/buddy.yml` — the unified workflow: rebase checks, dependency updates and the dashboard
364- `.github/workflows/buddy-security.yml` — the security audit, kept separate so it triggers on its own path filters
366365
367366### 5. Gradual Transition
368367
docs/api/buddy.mdmodified+46-29
Changes to docs/api/buddy.md
@@ -52,13 +52,11 @@ interface BuddyMethods {
5252
5353```typescript
5454interface UpdateScanResult {
55 totalPackages: number
5556 updates: PackageUpdate[]
5657 groups: UpdateGroup[]
57 metadata: {
58 scanTime: Date
59 strategy: string
60 packageCount: number
61 }
58 scannedAt: Date
59 duration: number
6260}
6361```
6462
@@ -101,7 +99,8 @@ if (scanResult.updates.length > 0) {
10199
102100### run()
103101
104Runs the complete update process (scan + create PRs).
102Runs the complete update process: scans, then creates pull requests when
103`pullRequest` is configured.
105104
106105```typescript
107106interface BuddyRunMethod {
@@ -224,6 +223,7 @@ Main configuration interface:
224223interface BuddyConfig {
225224 verbose?: boolean
226225 repository?: {
226 /** Only 'github' is implemented; the others are rejected at validation */
227227 provider: 'github' | 'gitlab' | 'bitbucket'
228228 owner: string
229229 name: string
@@ -231,7 +231,9 @@ interface BuddyConfig {
231231 token?: string
232232 }
233233 packages?: {
234 /** 'all': every update · 'major': majors only · 'minor': minors and patches · 'patch': patches only */
234235 strategy: 'major' | 'minor' | 'patch' | 'all'
236 /** Package names, matched exactly */
235237 ignore?: string[]
236238 pin?: Record<string, string>
237239 groups?: PackageGroup[]
@@ -266,11 +268,15 @@ interface PackageUpdate {
266268 currentVersion: string
267269 newVersion: string
268270 updateType: 'major' | 'minor' | 'patch'
269 dependencyType: 'dependencies' | 'devDependencies' | 'peerDependencies' | 'optionalDependencies'
270 repository?: string
271 /** 'dependencies' | 'devDependencies' | 'github-actions' | 'docker-image' | … */
272 dependencyType: Dependency['type']
273 /** Manifest the dependency was found in */
274 file: string
275 metadata?: PackageMetadata
276 releaseNotesUrl?: string
277 changelogUrl?: string
271278 homepage?: string
272 description?: string
273 changelog?: string
279 securityAdvisories?: SecurityAdvisory[]
274280}
275281```
276282
@@ -281,9 +287,10 @@ Groups related package updates:
281287```typescript
282288interface UpdateGroup {
283289 name: string
284 title: string
285290 updates: PackageUpdate[]
286 strategy: string
291 updateType: 'major' | 'minor' | 'patch'
292 title: string
293 body: string
287294}
288295```
289296
@@ -293,42 +300,48 @@ Result of scanning for updates:
293300
294301```typescript
295302interface UpdateScanResult {
303 totalPackages: number
296304 updates: PackageUpdate[]
297305 groups: UpdateGroup[]
298 metadata: {
299 scanTime: Date
300 strategy: string
301 packageCount: number
302 ignoredCount: number
303 }
306 scannedAt: Date
307 duration: number
304308}
305309```
306310
307311## Error Handling
308312
309The Buddy class throws errors for various failure scenarios:
310
311313### Configuration Errors
312314
315The constructor does not validate. A missing `repository` is reported when it
316is needed — `createPullRequests()` logs `Repository configuration required for
317PR creation` and returns without opening anything — so check the configuration
318before you rely on it:
319
313320```typescript
314try {
315 const buddy = new Buddy(invalidConfig)
316}
317catch (error) {
318 if (error.message.includes('Repository configuration required')) {
319 // Handle missing repository config
320 }
321}
321import { Buddy, formatConfigIssues, validateConfig } from '@buddysh/buddy'
322
323const issues = validateConfig(config)
324if (issues.length > 0)
325 throw new Error(formatConfigIssues(issues))
326
327if (!config.repository?.owner || !config.repository?.name)
328 throw new Error('repository.owner and repository.name are required to open pull requests')
329
330const buddy = new Buddy(config)
322331```
323332
324333### GitHub Token Errors
325334
335When no token can be resolved — neither `repository.token`, nor `GITHUB_TOKEN`,
336nor `BUDDY_TOKEN` — creating the provider throws `No token for github. Set one
337of: GITHUB_TOKEN, BUDDY_TOKEN.`
338
326339```typescript
327340try {
328341 await buddy.createPullRequests(scanResult)
329342}
330343catch (error) {
331 if (error.message.includes('GITHUB_TOKEN')) {
344 if (error.message.includes('No token for')) {
332345 // Handle missing or invalid GitHub token
333346 }
334347}
@@ -407,6 +420,10 @@ async function updateDependencies() {
407420 },
408421 packages: {
409422 strategy: process.env.UPDATE_STRATEGY as any || 'patch'
423 },
424 // `run()` only opens pull requests when `pullRequest` is configured
425 pullRequest: {
426 labels: ['dependencies']
410427 }
411428 })
412429
docs/api/configuration.mdmodified+527-558
Changes to docs/api/configuration.md
@@ -2,772 +2,745 @@
22
33TypeScript interfaces and types for buddy configuration.
44
5Everything on this page comes from `BuddyConfig` in `src/types.ts` and
6`PackageRule` in `src/rules/engine.ts`. A config file — `buddy.config.ts`,
7`buddy.config.js` or `buddy.config.json` — is merged over the packaged
8defaults and validated before any network or git work happens.
9
510## Core Configuration
611
712### `BuddyConfig`
813
9Main configuration interface for buddy.
14Every key is optional, and every section is inert until you set it.
1015
1116```typescript
1217interface BuddyConfig {
13 /** Repository configuration */
14 repository?: RepositoryConfig
15
16 /** Package management settings */
17 packages?: PackageConfig
18
19 /** Pull request configuration */
20 pullRequest?: PullRequestConfig
21
22 /** Scheduling configuration */
23 schedule?: ScheduleConfig
18 verbose?: boolean
19 logLevel?: LogLevel
20 repository?: RepositorySettings
21 registries?: RegistrySettings
22 security?: SecuritySettings
23 schedule?: ScheduleSettings
24 packages?: PackageSettings
25 gates?: GateSettings
26 issues?: IssueSettings
27 reports?: ReportSettings
28 analysis?: AnalysisSettings
29 ai?: AiSettings
30 notifications?: NotificationSettings
31 maxPRsPerRun?: number
32 pullRequest?: PullRequestSettings
33 releaseNotes?: ReleaseNotesSettings
34 workflows?: WorkflowSettings
35 dashboard?: DashboardSettings
36}
37
38type BuddyOptions = Partial<BuddyConfig>
39```
2440
25 /** Release notes configuration */
26 releaseNotes?: ReleaseNotesConfig
41The nested type names above are for reading convenience; in source they are
42inline object types on `BuddyConfig`. Each is described below, in declaration
43order.
2744
28 /** Git provider settings */
29 git?: GitProviderConfig
45## Logging
3046
31 /** Registry configuration */
32 registries?: RegistryConfig[]
47```typescript
48interface BuddyConfig {
49 /** Enable verbose logging. Equivalent to `logLevel: 'debug'`. */
50 verbose?: boolean
3351
34 /** Global settings */
35 global?: GlobalConfig
52 /** How much output to emit. Overrides `verbose` when both are set. */
53 logLevel?: LogLevel
3654}
37```
3855
39## Repository Configuration
56type LogLevel = 'silent' | 'error' | 'warn' | 'info' | 'debug'
57```
4058
41### `RepositoryConfig`
59Use `'silent'` when embedding buddy in another tool that owns its own output.
60`logLevel` can also be set with the `BUDDY_LOG_LEVEL` environment variable.
61The packaged defaults set `verbose: true`.
4262
43Repository-specific settings.
63## Repository
4464
4565```typescript
46interface RepositoryConfig {
66interface RepositorySettings {
67 /** Git provider */
68 provider: GitProviderName
69
4770 /** Repository owner/organization */
4871 owner: string
4972
5073 /** Repository name */
5174 name: string
5275
53 /** Default branch */
54 defaultBranch?: string
55
56 /** Repository URL */
57 url?: string
58
59 /** Clone configuration */
60 clone?: {
61 depth?: number
62 sparse?: boolean
63 submodules?: boolean
64 }
65}
66```
67
68## Package Configuration
69
70### `PackageConfig`
71
72Package management and update configuration.
73
74```typescript
75interface PackageConfig {
76 /** Update strategy */
77 strategy?: UpdateStrategy
78
79 /** Package manager to use */
80 manager?: PackageManager
81
82 /** Packages to ignore */
83 ignore?: string[]
84
85 /** Package groups */
86 groups?: PackageGroup[]
76 /** Base branch for PRs */
77 baseBranch?: string
8778
88 /** Workspace configuration */
89 workspaces?: WorkspaceConfig
79 /** Access token for API operations */
80 token?: string
9081
91 /** Version constraints */
92 constraints?: Record<string, string>
82 /** REST API base URL */
83 apiUrl?: string
9384
94 /** Include/exclude patterns */
95 include?: string[]
96 exclude?: string[]
85 /** Web base URL used for links in PR bodies and the dashboard */
86 serverUrl?: string
9787}
9888```
9989
100### `UpdateStrategy`
90Only `github` is implemented. `gitlab` and `bitbucket` type-check but are
91rejected at validation with a link to the issue tracking them, so a config
92typo cannot reach a workflow run.
10193
102Available update strategies.
94`apiUrl` defaults to `GITHUB_API_URL` when set — GitHub Actions exports it on
95both github.com and Enterprise Server runners — otherwise
96`https://api.github.com`. Set it explicitly for GitHub Enterprise Server, for
97example `https://github.acme.com/api/v3`. `serverUrl` defaults to
98`GITHUB_SERVER_URL`, otherwise `https://github.com`.
10399
104```typescript
105type UpdateStrategy = 'patch' | 'minor' | 'major' | 'all'
106```
100## Registries
107101
108### `PackageManager`
109
110Supported package managers.
102Package registry endpoints, for private or self-hosted mirrors.
111103
112104```typescript
113type PackageManager = 'bun' | 'npm' | 'yarn' | 'pnpm' | 'auto'
114```
105interface RegistrySettings {
106 /** npm registry base URL (default: `.npmrc` `registry=`, else registry.npmjs.org) */
107 npm?: string
115108
116### `PackageGroup`
109 /** Per-scope npm registry overrides, keyed by scope including the `@` */
110 npmScopes?: Record<string, string>
117111
118Package grouping configuration.
112 /** Composer/Packagist base URL (default: packagist.org) */
113 composer?: string
119114
120```typescript
121interface PackageGroup {
122 /** Group name */
123 name: string
124
125 /** Packages in group */
126 packages: string[]
127
128 /** Group-specific strategy */
129 strategy?: UpdateStrategy
130
131 /** Group labels */
132 labels?: string[]
133
134 /** Group reviewers */
135 reviewers?: string[]
136
137 /** Auto-merge for group */
138 autoMerge?: boolean
139
140 /** Group description */
141 description?: string
115 /** Per-host container registry credentials, keyed by host */
116 docker?: Record<string, {
117 username?: string
118 /** Environment variable holding the password */
119 passwordEnv?: string
120 /** Environment variable holding a pre-issued bearer token */
121 tokenEnv?: string
122 }>
142123}
143124```
144125
145### `WorkspaceConfig`
126Docker secrets are referenced by environment variable name, never inlined, so
127a registry can be committed to the repository without committing the
128credential that reaches it. `ghcr.io` falls back to `GITHUB_TOKEN`
129automatically, so private GHCR images work in Actions with no config.
146130
147Monorepo workspace configuration.
131## Security
148132
149133```typescript
150interface WorkspaceConfig {
151 /** Auto-detect workspaces */
152 autoDetect?: boolean
153
154 /** Workspace patterns */
155 patterns?: string[]
156
157 /** Workspace-specific configs */
158 configs?: Record<string, WorkspacePackageConfig>
159
160 /** Coordination settings */
161 coordination?: WorkspaceCoordination
162}
134interface SecuritySettings {
135 /** Query the OSV.dev advisory database (default: true) */
136 enabled?: boolean
163137
164interface WorkspacePackageConfig extends PackageConfig {
165 /** Workspace path */
166 path?: string
138 /** Move advisory-resolving updates to the front of the queue (default: true) */
139 prioritize?: boolean
167140
168 /** Downstream workspaces */
169 downstream?: string[]
141 /** Label name associated with advisory-resolving PRs (default: `security`) */
142 label?: string
170143
171 /** Requires testing */
172 requiresTesting?: boolean
144 /** Minimum severity to act on (default: `low`, i.e. everything) */
145 minimumSeverity?: VulnerabilitySeverity
173146}
174147
175interface WorkspaceCoordination {
176 /** Align shared dependencies */
177 alignSharedDeps?: boolean
178
179 /** Shared dependency groups */
180 sharedGroups?: Record<string, SharedGroupConfig>
181
182 /** Update ordering */
183 updateOrder?: string[]
184}
148type VulnerabilitySeverity = 'low' | 'moderate' | 'high' | 'critical'
185149```
186150
187## Pull Request Configuration
188
189### `PullRequestConfig`
151Disable `enabled` for fully offline runs. `prioritize` is what lets a security
152update survive the `maxPRsPerRun` cap. `label` is the label name that
153auto-merge's `security-only` condition looks for on a pull request.
190154
191Pull request generation settings.
155## Schedule
192156
193157```typescript
194interface PullRequestConfig {
195 /** PR title template */
196 title?: string
197
198 /** PR body template */
199 body?: string
200
201 /** PR labels */
202 labels?: LabelConfig
203
204 /** Assignees */
205 assignees?: AssigneeConfig
206
207 /** Reviewers */
208 reviewers?: ReviewerConfig
209
210 /** Auto-merge settings */
211 autoMerge?: AutoMergeConfig
212
213 /** Draft PR settings */
214 draft?: boolean
158interface ScheduleSettings {
159 /** Cron expression for scheduled runs */
160 cron?: string
215161
216 /** Branch naming */
217 branchNaming?: BranchNamingConfig
162 /** Time zone for scheduling */
163 timezone?: string
218164}
219165```
220166
221### `LabelConfig`
167Per-update scheduling windows live on `packages.rules[].schedule`, not here.
222168
223Label configuration for pull requests.
169## Packages
224170
225171```typescript
226interface LabelConfig {
227 /** Static labels (always applied) */
228 static?: string[]
172interface PackageSettings {
173 /** Update strategy for dependencies */
174 strategy: 'major' | 'minor' | 'patch' | 'all'
229175
230 /** Dynamic labeling rules */
231 dynamic?: DynamicLabelConfig
176 /** Packages to ignore */
177 ignore?: string[]
232178
233 /** Pattern-based labels */
234 patterns?: Record<string, string[]>
179 /** File/directory paths to ignore using glob patterns */
180 ignorePaths?: string[]
235181
236 /** Conditional labels */
237 conditions?: LabelCondition[]
238}
182 /** Packages to pin to specific versions */
183 pin?: Record<string, string>
239184
240interface DynamicLabelConfig {
241 /** Enable dynamic labeling */
242 enabled?: boolean
185 /** Group related packages together */
186 groups?: PackageGroup[]
243187
244 /** Update type labels */
245 updateType?: Record<UpdateStrategy, string>
188 /** Include prerelease versions (alpha, beta, rc, etc.) */
189 includePrerelease?: boolean
246190
247 /** Ecosystem detection */
248 ecosystems?: Record<string, string[]>
191 /** Exclude major version updates (even if strategy allows them) */
192 excludeMajor?: boolean
249193
250 /** Custom rules */
251 rules?: LabelRule[]
252}
194 /** Respect "latest" and "*" version indicators (default: true) */
195 respectLatest?: boolean
253196
254interface LabelCondition {
255 /** Condition function */
256 when: (pr: PullRequestContext) => boolean
197 /** Minimum age in minutes a version must have before installation (default: 0) */
198 minimumReleaseAge?: number
257199
258 /** Labels to apply */
259 apply: string[]
260}
200 /** Package names exempt from the minimum release age */
201 minimumReleaseAgeExclude?: string[]
261202
262interface LabelRule {
263 /** Rule condition */
264 condition: string
203 /** Conditional rules applied to matching updates */
204 rules?: PackageRule[]
265205
266 /** Label to apply */
267 label: string
206 /** Report updates held back by a range declared elsewhere (default: true) */
207 detectResolutionDrift?: boolean
268208}
269209```
270210
271### `AssigneeConfig`
211A strategy names the greatest semver impact a run may propose, and admits
212everything gentler beneath it:
272213
273Assignee configuration.
214| `strategy` | Admits |
215|---|---|
216| `all` | major, minor and patch |
217| `major` | major only |
218| `minor` | minor and patch |
219| `patch` | patch only |
274220
275```typescript
276interface AssigneeConfig {
277 /** Static assignees */
278 static?: string[]
221`rules` are evaluated in order and later matches override earlier ones per
222field, so a broad rule can set a default and a narrow one refine it.
279223
280 /** Dynamic assignment rules */
281 rules?: AssigneeRule[]
224`detectResolutionDrift` surfaces packages held below their latest version by a
225range declared elsewhere in the dependency tree. These cannot be fixed by
226updating this repository — somebody has to widen a range in the dependant — so
227they are reported on the dashboard rather than turned into pull requests.
282228
283 /** Maximum assignees */
284 maxAssignees?: number
229### `PackageGroup`
285230
286 /** Require assignee */
287 requiresAssignee?: boolean
288}
231```typescript
232interface PackageGroup {
233 /** Group name */
234 name: string
289235
290interface AssigneeRule {
291 /** Rule condition */
292 condition: string
236 /** Package patterns to include */
237 patterns: string[]
293238
294 /** Assignees to assign */
295 assignees: string[]
239 /** Update strategy for this group */
240 strategy?: 'major' | 'minor' | 'patch' | 'all'
296241}
297242```
298243
299### `ReviewerConfig`
300
301Reviewer configuration.
244A group has exactly these three fields, and only decides batching — which
245packages share a pull request. Anything conditional belongs in
246`packages.rules`.
302247
303```typescript
304interface ReviewerConfig {
305 /** Default reviewers */
306 default?: string[]
248## Gates
307249
308 /** Package-based reviewers */
309 packageOwners?: Record<string, string[]>
250Pre-merge gates and post-merge actions.
310251
311 /** Team configuration */
312 teams?: Record<string, TeamConfig>
252```typescript
253interface GateSettings {
254 /** Require a conventional-commit pull request title */
255 titleFormat?: 'off' | 'warning' | 'error'
256
257 /** Require a description, optionally with named sections */
258 description?: {
259 mode: 'off' | 'warning' | 'error'
260 requireSections?: string[]
261 }
313262
314 /** Review requirements */
315 requirements?: ReviewRequirements
263 /** Block dependencies by licence, advisory or deprecation */
264 dependencyGate?: {
265 mode: 'off' | 'warning' | 'error'
266 licenseAllowlist?: string[]
267 blockVulnerable?: boolean
268 blockDeprecated?: boolean
269 /** Block base images whose release cycle no longer gets security fixes */
270 blockEol?: boolean
271 }
316272
317 /** Fallback reviewers */
318 fallback?: string[]
273 /** Check that a change addresses the issue it says it closes */
274 linkedIssue?: 'off' | 'warning' | 'error'
275
276 /** Repository-specific natural-language assertions */
277 custom?: Array<{
278 name: string
279 assertion: string
280 mode?: 'off' | 'warning' | 'error'
281 }>
282
283 /** What to do once a pull request merges */
284 postMerge?: {
285 changelog?: { enabled?: boolean, path?: string }
286 commentOnIssues?: boolean
287 refreshDashboard?: boolean
288 }
319289}
290```
320291
321interface TeamConfig {
322 /** Team members */
323 members: string[]
324
325 /** Packages owned by team */
326 packages: string[]
327
328 /** Required reviews from team */
329 requiredReviews?: number
330
331 /** Auto-assign to team */
332 autoAssign?: boolean
333}
292The deterministic gates need no AI. The assertion gates — `linkedIssue` and
293`custom` — degrade to a neutral result rather than a pass when no provider is
294configured, so a check that could not run never reads as one that succeeded.
334295
335interface ReviewRequirements {
336 /** Minimum required reviews */
337 required?: number
296## Issues
338297
339 /** Count team reviews */
340 teamReviews?: boolean
298```typescript
299interface IssueSettings {
300 /** Post the quick-links comment on new issues (default: false) */
301 quickLinks?: boolean
341302
342 /** Dismiss stale reviews */
343 dismissStale?: boolean
303 /** Include dependency context when the issue names a known package */
304 dependencyContext?: boolean
344305}
345306```
346307
347### `AutoMergeConfig`
308Both actions are opt-in checkboxes on the posted comment: an issue is a
309request for a conversation as often as for code, and a bot that opens a pull
310request against every new issue is one a maintainer turns off in a week.
311
312## Reports
348313
349Auto-merge configuration.
314Scheduled dependency-health and activity reports.
350315
351316```typescript
352interface AutoMergeConfig {
353 /** Enable auto-merge */
317interface ReportSettings {
318 /** Generate reports (default: false) */
354319 enabled?: boolean
355320
356 /** Required status checks */
357 requiredChecks?: string[]
358
359 /** Merge method */
360 method?: MergeMethod
361
362 /** Conditions for auto-merge */
363 conditions?: AutoMergeCondition[]
364
365 /** Delay before merge */
366 delay?: number
367}
321 /** Cron expression for the scheduled run */
322 schedule?: string
368323
369type MergeMethod = 'merge' | 'squash' | 'rebase'
324 /** Reporting window (default: `30d`) */
325 period?: '7d' | '30d' | '90d'
370326
371interface AutoMergeCondition {
372 /** Update type */
373 updateType?: UpdateStrategy
327 /** What the AI narrative should emphasise */
328 prompt?: string
374329
375 /** Package patterns */
376 packages?: string[]
330 /** Title of the report issue (default: `Dependency Report`) */
331 title?: string
377332
378 /** Labels required */
333 /** Labels applied to the report issue */
379334 labels?: string[]
380
381 /** Reviews required */
382 reviews?: number
383335}
384336```
385337
386### `BranchNamingConfig`
338The report is computed from scan results and pull request history, so it works
339with no AI provider. A configured provider adds a narrative around the
340numbers; it never produces them.
387341
388Branch naming configuration.
342## Analysis
389343
390344```typescript
391interface BranchNamingConfig {
392 /** Branch prefix */
393 prefix?: string
394
395 /** Include update type */
396 includeUpdateType?: boolean
397
398 /** Include package count */
399 includePackageCount?: boolean
400
401 /** Custom template */
402 template?: string
345interface AnalysisSettings {
346 /** Turn all analyzers off (default: true, they are cheap and local) */
347 enabled?: boolean
403348
404 /** Separator character */
405 separator?: string
349 /** Per-analyzer switches, keyed by name. Absent means enabled. */
350 tools?: Record<string, boolean>
406351}
407352```
408353
409## Schedule Configuration
354Recognised tool names are `secrets`, `github-actions`, `syntax`, `linter`,
355`actionlint`, `shellcheck`, `hadolint` and `markdownlint`. Analyzers run
356whether or not an AI provider is configured, so a repository with no key still
357gets secret scanning, workflow auditing and whatever external linters the
358runner has installed.
410359
411### `ScheduleConfig`
412
413Scheduling and automation settings.
360## AI
414361
415362```typescript
416interface ScheduleConfig {
417 /** Cron expression */
418 cron?: string
419
420 /** Timezone */
421 timezone?: string
422
423 /** Enable scheduling */
363interface AiSettings {
364 /** Turn all AI features off even when a key is present */
424365 enabled?: boolean
425366
426 /** Multiple schedules */
427 schedules?: NamedSchedule[]
367 /** Which provider to use */
368 provider?: 'anthropic' | 'openai' | 'google' | 'openrouter' | 'openai-compatible'
428369
429 /** Environment-based scheduling */
430 environments?: Record<string, EnvironmentSchedule>
370 /** Model alias or concrete ID */
371 model?: string
431372
432 /** Trigger-based updates */
433 triggers?: TriggerConfig
434}
373 /** Reasoning depth to request (default: provider default) */
374 effort?: 'low' | 'medium' | 'high'
435375
436interface NamedSchedule {
437 /** Schedule name */
438 name: string
376 /** Environment variable holding the API key, when not the provider default */
377 apiKeyEnv?: string
439378
440 /** Cron expression */
441 cron: string
379 /** Base URL override, for gateways and OpenAI-compatible endpoints */
380 baseUrl?: string
442381
443 /** Schedule-specific strategy */
444 strategy?: UpdateStrategy
382 /** Hard ceiling on output tokens generated per run */
383 maxTokensPerRun?: number
445384
446 /** Schedule labels */
447 labels?: string[]
385 majorUpgrades?: MajorUpgradeSettings
386 review?: ReviewSettings
387}
388```
448389
449 /** Schedule reviewers */
450 reviewers?: string[]
390Every AI-powered feature is off unless a provider key is available, and
391degrades to a no-op rather than failing the run — the dependency bot works
392exactly as before with no AI configured.
451393
452 /** Auto-merge for schedule */
453 autoMerge?: boolean
454}
394With `provider` omitted, the first provider with an available API key is
395chosen, in the order anthropic, openai, google, openrouter. Model aliases
396(`opus`, `sonnet`, `haiku`) resolve to current Anthropic models; every other
397provider needs a concrete ID. `BUDDY_MODEL` overrides `model` per run. Once
398`maxTokensPerRun` is reached, further requests fail rather than spending more.
455399
456interface EnvironmentSchedule extends NamedSchedule {
457 /** Environment name */
458 environment?: string
400### `ai.majorUpgrades`
459401
460 /** Require approval */
461 requireApproval?: boolean
462}
402```typescript
403interface MajorUpgradeSettings {
404 /** Analyse major updates (default: false — opt in, it costs tokens) */
405 enabled?: boolean
406
407 /** Attempt the migration rather than only analysing it (default: false) */
408 autoMigrate?: boolean
463409
464interface TriggerConfig {
465 /** Security triggers */
466 security?: SecurityTrigger
410 /** Open as a draft below this confidence (default: `high`) */
411 draftBelowConfidence?: 'high' | 'medium'
467412
468 /** Major release triggers */
469 majorRelease?: MajorReleaseTrigger
413 /** Maximum agent attempts per upgrade */
414 maxAttempts?: number
470415
471 /** Batch threshold triggers */
472 batchThreshold?: BatchThresholdTrigger
416 /** Globs limiting which packages are analysed; empty means all majors */
417 packages?: string[]
473418}
474419```
475420
476## Release Notes Configuration
477
478### `ReleaseNotesConfig`
421`autoMigrate` defaults off because a wrong migration is far more expensive
422than a missing one.
479423
480Release notes extraction and formatting.
424### `ai.review`
481425
482426```typescript
483interface ReleaseNotesConfig {
484 /** Data sources */
485 sources?: ReleaseNotesSource
427interface ReviewSettings {
428 /** Enable AI review (default: false until you opt in) */
429 enabled?: boolean
486430
487 /** Content formatting */
488 formatting?: ReleaseNotesFormatting
431 /** How thorough to be */
432 profile?: 'chill' | 'assertive'
489433
490 /** Template configuration */
491 template?: ReleaseNotesTemplate
434 /** Review draft pull requests too (default: false) */
435 drafts?: boolean
492436
493 /** Aggregation settings */
494 aggregation?: ReleaseNotesAggregation
437 /** Review automatically on open and push (default: true when enabled) */
438 autoReview?: boolean
495439
496 /** Caching configuration */
497 caching?: CacheConfig
498}
440 /** Skip pull requests whose title contains any of these, e.g. `wip` */
441 ignoreTitleKeywords?: string[]
499442
500interface ReleaseNotesSource {
501 /** GitHub releases */
502 githubReleases?: GitHubReleasesConfig
443 /** Skip pull requests opened by these users */
444 ignoreUsernames?: string[]
503445
504 /** Changelog files */
505 changelog?: ChangelogConfig
446 /** Request changes at this severity, or never (default: never) */
447 requestChangesOn?: 'never' | 'critical'
506448
507 /** NPM registry */
508 npmRegistry?: NpmRegistryConfig
449 /** Post only the summary and walkthrough, no inline findings */
450 summaryOnly?: boolean
509451
510 /** Git commits */
511 gitCommits?: GitCommitsConfig
512}
452 /** Gitignore-style path filters; `!` excludes */
453 pathFilters?: string[]
513454
514interface ReleaseNotesFormatting {
515 /** Markdown processing */
516 markdown?: MarkdownConfig
455 /** Guidance applied when reviewing files matching a glob */
456 pathInstructions?: Array<{ path: string, instructions: string }>
517457
518 /** Content filters */
519 filters?: ContentFilters
458 /** Convention files read from the base branch, or `false` to disable */
459 guidelineFiles?: string[] | false
520460
521 /** Content enhancement */
522 enhance?: ContentEnhancement
461 /** Global guidance prepended to every review */
462 instructions?: string
523463}
464```
524465
525interface ReleaseNotesTemplate {
526 /** Header template */
527 header?: string
528
529 /** Package section template */
530 packageSection?: string
466`chill` reports only confident defects; `assertive` also reports
467lower-confidence findings, marked so they can be filtered downstream.
468`pathFilters` apply on top of the built-in exclusions for lock files and build
469output. `guidelineFiles` defaults to the usual convention files — CLAUDE.md,
470AGENTS.md, .cursorrules and similar — and a list overrides those defaults.
531471
532 /** Footer template */
533 footer?: string
472## Notifications
534473
535 /** Empty state message */
536 empty?: string
474```typescript
475interface NotificationSettings {
476 slack?: { webhookEnv?: string, events?: string[] }
477 discord?: { webhookEnv?: string, events?: string[] }
537478
538 /** Error message */
539 error?: string
479 /** Signed JSON POSTs to your own endpoints */
480 webhooks?: Array<{ url: string, secretEnv?: string, events?: string[] }>
540481}
541482```
542483
543## Git Provider Configuration
544
545### `GitProviderConfig`
484Credentials are referenced by environment variable name, never inlined, so a
485destination can be committed without committing its credential.
546486
547Git provider settings.
487## Pull Requests
548488
549489```typescript
550interface GitProviderConfig {
551 /** Provider type */
552 provider: GitProvider
553
554 /** Provider-specific settings */
555 github?: GitHubConfig
556 gitlab?: GitLabConfig
557
558 /** Authentication */
559 auth?: AuthConfig
490interface BuddyConfig {
491 /** Maximum number of PRs to create per workflow run (default: 10) */
492 maxPRsPerRun?: number
560493
561 /** API configuration */
562 api?: ApiConfig
494 pullRequest?: PullRequestSettings
563495}
564496
565type GitProvider = 'github' | 'gitlab'
497interface PullRequestSettings {
498 /** Commit message format */
499 commitMessageFormat?: string
566500
567interface GitHubConfig {
568 /** GitHub API URL */
569 apiUrl?: string
501 /** PR title format */
502 titleFormat?: string
570503
571 /** GitHub Enterprise URL */
572 baseUrl?: string
573
574 /** App ID for GitHub App */
575 appId?: string
504 /** PR body template */
505 bodyTemplate?: string
576506
577 /** Installation ID */
578 installationId?: string
507 /** Auto-merge settings */
508 autoMerge?: {
509 enabled: boolean
510 strategy: 'merge' | 'squash' | 'rebase'
511 conditions?: string[]
512 requireGreenCI?: boolean
513 optOutLabel?: string
514 }
579515
580 /** Private key path */
581 privateKeyPath?: string
582}
516 /** Reviewers to assign */
517 reviewers?: string[]
583518
584interface GitLabConfig {
585 /** GitLab instance URL */
586 url?: string
519 /** GitHub teams to request review from, by team slug */
520 teamReviewers?: string[]
587521
588 /** Project ID */
589 projectId?: number
522 /** Assignees to assign */
523 assignees?: string[]
590524
591 /** Group ID */
592 groupId?: number
525 /** Labels to add */
526 labels?: string[]
593527}
528```
594529
595interface AuthConfig {
596 /** Personal access token */
597 token?: string
530`reviewers`, `assignees` and `labels` are plain string arrays. `teamReviewers`
531takes team slugs without the organisation prefix. Reviewers and assignees
532configured here are unioned with whatever the matching `packages.rules`
533contributed for the updates in the pull request.
598534
599 /** Token environment variable */
600 tokenEnv?: string
535The labels a generated pull request carries are derived from its update types
536and the ecosystems it touches — `dependencies`, `major`/`minor`/`patch`,
537`npm`, `composer`, `zig`, `system`, `github-actions`, plus the package name
538itself on a single-package PR — unioned with the `labels` effect of any
539matching `packages.rules`. Per-update labelling therefore belongs in
540`packages.rules[].labels`.
601541
602 /** OAuth configuration */
603 oauth?: OAuthConfig
604}
542### `pullRequest.autoMerge`
605543
606interface ApiConfig {
607 /** Request timeout */
608 timeout?: number
544`conditions` accepts `patch-only`, `minor-only`, `security-only` and `all`. A
545pull request qualifies when any listed condition accepts it. An empty or
546missing list means nothing auto-merges — the safe reading of a half-written
547config. Update types are read from the metadata manifest embedded in the PR
548body, not from its title, and a PR whose manifest is missing or truncated is
549never eligible.
609550
610 /** Retry attempts */
611 retries?: number
551`requireGreenCI` defaults to `true` and is only meaningful on repositories
552without branch protection, where buddy merges directly instead of handing the
553pull request to GitHub's own auto-merge queue. `optOutLabel` defaults to
554`no-auto-merge`; a pull request carrying it never merges unattended.
612555
613 /** Rate limiting */
614 rateLimit?: RateLimitConfig
615}
616```
556## Release Notes
617557
618## Registry Configuration
558```typescript
559interface ReleaseNotesSettings {
560 /** Enable release notes in PRs (default: true) */
561 enabled?: boolean
619562
620### `RegistryConfig`
563 /** Sanitize GitHub references (#123, issue/PR URLs) to prevent spam notifications (default: true) */
564 sanitizeReferences?: boolean
621565
622Package registry settings.
566 /** Maximum number of releases to show per package (default: 3) */
567 maxReleases?: number
623568
624```typescript
625interface RegistryConfig {
626 /** Registry name */
627 name: string
569 /** Maximum character length per release body (default: 1000) */
570 maxBodyLength?: number
628571
629 /** Registry URL */
630 url: string
572 /** Include compare links between versions (default: true) */
573 includeCompareLinks?: boolean
574}
575```
631576
632 /** Authentication token */
633 token?: string
577## Workflows
634578
635 /** Scope for scoped registries */
636 scope?: string
579```typescript
580interface WorkflowSettings {
581 /** Enable workflow generation */
582 enabled?: boolean
637583
638 /** Registry type */
639 type?: RegistryType
584 /** Output directory for workflows (default: `.github/workflows`) */
585 outputDir?: string
586
587 /** Workflow templates to generate */
588 templates?: {
589 comprehensive?: boolean
590 daily?: boolean
591 weekly?: boolean
592 monthly?: boolean
593 docker?: boolean
594 monorepo?: boolean
595 }
640596
641 /** Cache configuration */
642 cache?: CacheConfig
597 /** Custom workflow configurations */
598 custom?: Array<{
599 name: string
600 schedule: string
601 strategy?: 'major' | 'minor' | 'patch' | 'all'
602 autoMerge?: boolean
603 reviewers?: string[]
604 assignees?: string[]
605 labels?: string[]
606 }>
643607}
644
645type RegistryType = 'npm' | 'github' | 'private'
646608```
647609
648## Global Configuration
649
650### `GlobalConfig`
651
652Global settings and defaults.
610## Dashboard
653611
654612```typescript
655interface GlobalConfig {
656 /** Verbose logging */
657 verbose?: boolean
613interface DashboardSettings {
614 /** Enable dependency dashboard */
615 enabled?: boolean
616
617 /** Dashboard title (default: `Dependency Dashboard`) */
618 title?: string
658619
659 /** Dry run mode */
660 dryRun?: boolean
620 /** Dashboard body template */
621 bodyTemplate?: string
661622
662 /** Concurrency limit */
663 concurrency?: number
623 /** Labels to add to dashboard issue */
624 labels?: string[]
664625
665 /** Timeout settings */
666 timeout?: number
626 /** Assignees to assign to dashboard issue */
627 assignees?: string[]
667628
668 /** Error handling */
669 errorHandling?: ErrorHandlingConfig
629 /** Include package.json dependencies */
630 includePackageJson?: boolean
670631
671 /** Performance settings */
672 performance?: PerformanceConfig
673}
632 /** Include dependency files (deps.yaml, etc.) */
633 includeDependencyFiles?: boolean
674634
675interface ErrorHandlingConfig {
676 /** Retry configuration */
677 retry?: RetryConfig
635 /** Include GitHub Actions */
636 includeGitHubActions?: boolean
678637
679 /** Fallback strategies */
680 fallback?: FallbackConfig
638 /** Show open PRs section */
639 showOpenPRs?: boolean
681640
682 /** Error reporting */
683 reporting?: ErrorReportingConfig
684}
641 /** Show detected dependencies section */
642 showDetectedDependencies?: boolean
685643
686interface PerformanceConfig {
687 /** Caching strategy */
688 cache?: CacheStrategy
644 /** Show deprecated dependencies section */
645 showDeprecatedDependencies?: boolean
689646
690 /** Parallel processing */
691 parallel?: ParallelConfig
647 /** Issue number to update (if it exists) */
648 issueNumber?: number
692649
693 /** Memory management */
694 memory?: MemoryConfig
650 /** Pin the dashboard issue to the top of the issue list (default: false) */
651 pin?: boolean
695652}
696653```
697654
698## Utility Types
655GitHub allows at most three pinned issues per repository; when that limit is
656already reached the dashboard is still created, just unpinned.
699657
700### `PullRequestContext`
701
702Context object passed to conditional functions.
703
704```typescript
705interface PullRequestContext {
706 /** Packages being updated */
707 packages: PackageUpdate[]
658## Package Rules
708659
709 /** Update type */
710 updateType: UpdateStrategy
660### `PackageRule`
711661
712 /** Total package count */
713 packageCount: number
662The main extension point. Rules live on `packages.rules` and are the place for
663everything that varies per update.
714664
715 /** Has breaking changes */
716 hasBreakingChanges: boolean
717
718 /** Is security update */
719 isSecurityUpdate: boolean
720
721 /** Repository information */
722 repository: RepositoryContext
665```typescript
666interface PackageRule {
667 // Matchers — all present matchers must match (AND within a rule)
668 /** Package names or globs */
669 matchPackages?: string[]
670 matchEcosystems?: RuleEcosystem[]
671 matchDepTypes?: string[]
672 matchUpdateTypes?: Array<'major' | 'minor' | 'patch'>
673 /** Globs on the manifest path, for monorepo directories */
674 matchFiles?: string[]
675 /** Semver range the currently installed version must satisfy */
676 matchCurrentVersion?: string
677 /** Cron expression describing when these updates may be proposed */
678 schedule?: string
679 /** IANA time zone `schedule` is written in (default: the runner's) */
680 scheduleTimezone?: string
681
682 // Effects
683 /** `false` drops matching updates entirely */
684 enabled?: boolean
685 strategy?: 'major' | 'minor' | 'patch' | 'all'
686 groupName?: string
687 labels?: string[]
688 reviewers?: string[]
689 assignees?: string[]
690 autoMerge?: boolean
691 /** Minutes a version must have been published, overriding the global */
692 minimumReleaseAge?: number
693 /** Ordering within the per-run PR cap; higher goes first */
694 prPriority?: number
695 /** Attempt the migration for matching majors, overriding the global */
696 autoMigrate?: boolean
723697}
724698
725interface PackageUpdate {
726 /** Package name */
727 name: string
728
729 /** Current version */
730 currentVersion: string
731
732 /** Target version */
733 targetVersion: string
699type RuleEcosystem =
700 | 'npm' | 'composer' | 'github-actions' | 'docker' | 'pkgx'
701 | 'zig' | 'python' | 'rust' | 'go' | 'ruby'
702```
734703
735 /** Update type */
736 updateType: UpdateStrategy
704Matchers combine with AND, so a rule with several matchers is a conjunction. A
705rule with no matchers at all matches everything, which is why validation rejects
706it and asks for an explicit matcher rather than accepting silence. Write the
707deliberate catch-all as `matchPackages: ['**']`: a glob `*` stops at `/`, so it
708matches `react` but not `@types/node`.
737709
738 /** Has breaking changes */
739 hasBreakingChanges: boolean
710`matchCurrentVersion` lets a rule target a version series rather than a
711package — holding back everything still on `<2.0.0` while letting the rest
712through. Declared versions are stripped to their concrete floor first, so
713`^1.2.3` is tested as `1.2.3`.
740714
741 /** Is dev dependency */
742 isDevDependency: boolean
715`schedule` describes a window, not a firing minute: `0 0 * * 6,0` holds
716updates back on a weekday run and releases them on a weekend one.
743717
744 /** Release notes */
745 releaseNotes?: string
746}
747```
718### How effects combine
748719
749### Helper Types
720`labels`, `reviewers` and `assignees` accumulate across every matching rule.
721A package matching both a "security" and a "frontend" rule carries both sets,
722rather than whichever rule happened to be last.
750723
751724```typescript
752/** Deep partial type */
753type DeepPartial<T> = {
754 [P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P]
755}
756
757/** Configuration with environment overrides */
758type ConfigWithEnv<T> = T & {
759 env?: Record<string, DeepPartial<T>>
760}
761
762/** Conditional configuration */
763type ConditionalConfig<T> = T | ((context: any) => T)
725rules: [
726 { matchUpdateTypes: ['patch'], labels: ['patch-update'] },
727 { matchPackages: ['react*'], labels: ['frontend'], reviewers: ['ui-team'] },
728]
729// A patch update to react-dom carries both labels and the ui-team reviewer.
764730```
765731
766## Configuration Validation
732Every other effect — `enabled`, `strategy`, `groupName`, `autoMerge`,
733`minimumReleaseAge`, `prPriority`, `autoMigrate` — is a per-field override,
734and the last matching rule wins.
767735
768### `validateConfig`
736When several updates share one pull request, their resolved effects are merged
737for the group: labels, reviewers and assignees union; `prPriority` takes the
738maximum; `autoMerge` requires every update to have opted in, because one
739package that must not merge unattended has to hold back the whole PR;
740`autoMigrate` needs only one, because migrating what can be migrated leaves
741the rest unchanged.
769742
770Validate configuration object.
743## Configuration Validation
771744
772745```typescript
773746import { assertValidConfig, formatConfigIssues, validateConfig } from '@buddysh/buddy'
@@ -796,6 +769,10 @@ if (issues.length > 0)
796769 console.error(formatConfigIssues(issues))
797770```
798771
772`getConfig()` calls `assertValidConfig` for you, before any network or git
773work happens. A malformed strategy or a group with no patterns otherwise
774produces a run that silently does the wrong thing and reports success.
775
799776## Example Configurations
800777
801778### Basic Configuration
@@ -805,21 +782,18 @@ import type { BuddyConfig } from '@buddysh/buddy'
805782
806783const config: BuddyConfig = {
807784 repository: {
785 provider: 'github',
808786 owner: 'myorg',
809 name: 'myproject'
787 name: 'myproject',
788 token: process.env.GITHUB_TOKEN,
810789 },
811790 packages: {
812791 strategy: 'minor',
813 ignore: ['react']
792 ignore: ['react'],
814793 },
815794 pullRequest: {
816 labels: {
817 static: ['dependencies']
818 },
819 reviewers: {
820 default: ['team-lead']
821 }
822 }
795 reviewers: ['team-lead'],
796 },
823797}
824798
825799export default config
@@ -869,7 +843,6 @@ const config: BuddyConfig = {
869843 },
870844
871845 pullRequest: {
872 labels: ['dependencies'],
873846 reviewers: ['maintainer'],
874847 autoMerge: {
875848 enabled: true,
@@ -888,10 +861,6 @@ const config: BuddyConfig = {
888861export default config
889862```
890863
891Note the split between `groups` and `rules`. A `PackageGroup` has exactly
892three fields — `name`, `patterns` and `strategy` — and only decides batching.
893Anything conditional (labels, reviewers, assignees, auto-merge, release age,
894priority, scheduling windows) belongs in `packages.rules`. See
895[scheduling](/advanced/scheduling) for the full matcher and effect tables.
896
897See [Configuration Guide](/config) for detailed configuration examples and best practices.
864See [Configuration Guide](/config) for detailed configuration examples and
865best practices, and [scheduling](/advanced/scheduling) for the full matcher
866and effect tables.
docs/cli/overview.mdmodified+22-12
Changes to docs/cli/overview.md
@@ -59,6 +59,15 @@ buddy <command> [options] [arguments]
5959| [`compare`](/cli/package#compare) | Compare two versions of a package |
6060| [`search`](/cli/package#search) | Search for packages in the registry |
6161
62### 📊 Dashboard & Review
63
64| Command | Description |
65|---------|-------------|
66| [`dashboard`](/features/dependency-dashboard) | Create or update the dependency dashboard issue |
67| [`review`](/cli/review) | Review local changes, or a pull request |
68| [`security`](/features/workflow-security) | Static-analyse GitHub Actions workflows |
69| [`doctor`](/cli/review#diagnosing-setup) | Diagnose credentials, git state and analyzer tooling |
70
6271### ⏰ Automation & Scheduling
6372
6473| Command | Description |
@@ -67,14 +76,16 @@ buddy <command> [options] [arguments]
6776
6877## Global Options
6978
70All commands support these global options:
79Every command accepts these:
7180
7281```bash
73--verbose, -v Enable verbose logging
82--config <path> Path to a buddy config file
7483--help, -h Show help information
7584--version Show version information
7685```
7786
87Almost every command also takes `--verbose, -v` for detailed logging. Options are matched strictly: a flag a command does not declare is an error, not something quietly ignored.
88
7889## Examples
7990
8091### Quick Start
@@ -153,14 +164,14 @@ export default {
153164Buddy uses these environment variables:
154165
155166```bash
156# Required for GitHub operations
167# Required for GitHub operations. GH_TOKEN is accepted as an alias
157168GITHUB_TOKEN=ghp_xxxxxxxxxxxx
158169
159# Optional: Explicitly set GitHub token
160GH_TOKEN=ghp_xxxxxxxxxxxx
170# Optional: a PAT with 'repo' and 'workflow' scopes, used ahead of GITHUB_TOKEN
171BUDDY_TOKEN=ghp_xxxxxxxxxxxx
161172
162# Optional: Configure Bun
163BUN_CONFIG_DIR=/path/to/config
173# Optional: output level - silent, error, warn, info, debug
174BUDDY_LOG_LEVEL=debug
164175```
165176
166177## Exit Codes
@@ -168,8 +179,7 @@ BUN_CONFIG_DIR=/path/to/config
168179Buddy uses standard exit codes:
169180
170181- **0**: Success
171- **1**: General error (configuration, network, etc.)
172- **2**: Command not found or invalid arguments
182- **1**: Any failure — configuration, network, an unknown command, or an option the command does not accept
173183
174184## Debugging
175185
@@ -252,8 +262,8 @@ done
252262## Performance Tips
253263
2542641. **Use specific strategies**: `--strategy patch` is faster than `all`
2552. **Filter packages**: Use `--packages` for targeted updates
2563. **Enable caching**: Set `BUN_CONFIG_NO_CACHE=false`
2652. **Filter packages**: Use `buddy scan --packages` to check a short list
2663. **Skip the noise**: Leave `--verbose` off unless you are debugging
2572674. **Parallel execution**: Run multiple commands in parallel for monorepos
258268
259269## Getting Help
@@ -271,7 +281,7 @@ buddy update --help
271281
272282### Documentation
273283
274- **Full Documentation**: [<https://buddy.sh/doc>s](https://buddy.sh/docs)
284- **Full Documentation**: [buddy.sh/docs](https://buddy.sh/docs)
275285- **Configuration Guide**: [/config](/config)
276286- **GitHub Setup**: [/features/github-actions](/features/github-actions)
277287
docs/cli/package.mdmodified+100-351
Changes to docs/cli/package.md
@@ -1,6 +1,6 @@
11# Package Commands
22
3CLI commands for package analysis, management, and information retrieval.
3CLI commands for package analysis and information retrieval.
44
55## Package Information
66
@@ -12,467 +12,216 @@ Get comprehensive information about a package:
1212# Basic package info
1313buddy info react
1414
15# Detailed information
16buddy info react --detailed
17
18# Include dependencies
19buddy info react --include-deps
20
21# Show version history
22buddy info react --versions --limit 10
15# Info for a specific dist-tag
16buddy info typescript@latest
2317
2418# Output as JSON
2519buddy info react --json
20
21# Verbose output
22buddy info react --verbose
2623```
2724
25Without `--json`, the command prints the description, homepage, repository,
26license, author, keywords, dependency counts and the number of published
27versions.
28
2829**Options:**
2930
30- `--detailed` - Show extended package information
31- `--include-deps` - Include dependency tree
32- `--versions` - Show available versions
33- `--limit <number>` - Limit version results
3431- `--json` - Output as JSON
32- `--verbose, -v` - Enable verbose logging
3533
3634### `versions` - Available Versions
3735
38List all available versions for a package:
36List available versions for a package:
3937
4038```bash
41# All versions
39# Most recent versions (10 by default)
4240buddy versions typescript
4341
44# Latest 10 versions
45buddy versions typescript --limit 10
42# Latest 5 versions
43buddy versions typescript --latest 5
44```
4645
47# Include pre-releases
48buddy versions typescript --include-pre
46The output shows the total number of published versions, the latest version, and
47the most recent versions in descending order.
4948
50# Filter by tag
51buddy versions typescript --tag latest
49**Options:**
5250
53# Show release dates
54buddy versions typescript --with-dates
55```
51- `--latest <count>` - Show only the latest N versions (default: `10`)
52- `--verbose, -v` - Enable verbose logging
5653
5754### `latest` - Latest Version
5855
5956Get the latest version of a package:
6057
6158```bash
62# Latest stable version
59# Latest version
6360buddy latest vue
6461
65# Latest including pre-releases
66buddy latest vue --include-pre
67
68# Latest for specific tag
69buddy latest vue --tag next
62# Works with scoped packages
63buddy latest @types/node
7064```
7165
66**Options:**
67
68- `--verbose, -v` - Enable verbose logging
69
7270## Package Analysis
7371
7472### `deps` - Dependency Analysis
7573
76Analyze package dependencies:
74Show the dependencies a package declares:
7775
7876```bash
79# Direct dependencies
77# Production dependencies
8078buddy deps react
8179
82# Full dependency tree
83buddy deps react --tree
84
85# Specific depth
86buddy deps react --depth 2
80# Dev dependencies
81buddy deps react --dev
8782
88# Include dev dependencies
89buddy deps react --include-dev
83# Peer dependencies
84buddy deps react --peer
9085
91# Show outdated dependencies
92buddy deps react --outdated
93
94# Export dependency graph
95buddy deps react --graph --output deps.json
86# Every dependency type
87buddy deps react --all
9688```
9789
9890**Options:**
9991
100- `--tree` - Show full dependency tree
101- `--depth <number>` - Limit tree depth
102- `--include-dev` - Include devDependencies
103- `--outdated` - Show outdated dependencies
104- `--graph` - Generate dependency graph
105- `--output <file>` - Save output to file
92- `--dev` - Show devDependencies
93- `--peer` - Show peerDependencies
94- `--all` - Show all dependency types
95- `--verbose, -v` - Enable verbose logging
10696
10797### `check` - Package Updates
10898
109Check for available updates:
99Check named packages for available updates. At least one package name is
100required:
110101
111102```bash
112# Check all packages
113buddy check
114
115103# Check specific packages
116104buddy check react vue typescript
117105
118# Check with strategy
119buddy check --strategy minor
120
121# Check security updates only
122buddy check --security-only
123
124# Check by pattern
125buddy check --pattern "@types/*"
106# Check with a strategy
107buddy check react --strategy minor
126108
127# Show changelogs
128buddy check --with-changelog
129
130# Group by update type
131buddy check --group-by-type
109# Verbose output
110buddy check react typescript --verbose
132111```
133112
134**Options:**
135
136- `--strategy <type>` - Update strategy (patch|minor|major|all)
137- `--security-only` - Security updates only
138- `--pattern <pattern>` - Package name pattern
139- `--with-changelog` - Include changelog information
140- `--group-by-type` - Group results by update type
141
142### `outdated` - Outdated Packages
143
144List packages that have updates available:
145
146```bash
147# All outdated packages
148buddy outdated
149
150# Outdated with severity
151buddy outdated --severity
152
153# Outdated dev dependencies
154buddy outdated --dev-only
113Each update is reported as `name: current → new (type)`.
155114
156# Outdated production dependencies
157buddy outdated --prod-only
115**Options:**
158116
159# Table format
160buddy outdated --table
117- `--strategy <type>` - Update strategy: `major|minor|patch|all` (default: `all`)
118- `--verbose, -v` - Enable verbose logging
161119
162# JSON output
163buddy outdated --json
164```
120To check every dependency in the project rather than a fixed list, use
121[`buddy scan`](/cli/update), which also accepts `--pattern "@types/*"` for
122glob matching.
165123
166124## Package Search
167125
168126### `search` - Package Search
169127
170Search for packages in registries:
128Search for packages in the registry:
171129
172130```bash
173131# Basic search
174132buddy search "state management"
175133
176134# Limit results
177buddy search "testing" --limit 20
178
179# Search by keywords
180buddy search --keywords "typescript,testing"
181
182# Search by maintainer
183buddy search --maintainer "facebook"
184
185# Include deprecated packages
186buddy search "react" --include-deprecated
187
188# Sort by popularity
189buddy search "ui components" --sort popularity
135buddy search "test framework" --limit 5
190136```
191137
192138**Options:**
193139
194- `--limit <number>` - Limit search results
195- `--keywords <keywords>` - Search by keywords (comma-separated)
196- `--maintainer <name>` - Filter by maintainer
197- `--include-deprecated` - Include deprecated packages
198- `--sort <field>` - Sort by field (popularity|quality|maintenance)
140- `--limit <count>` - Limit number of results (default: `10`)
141- `--verbose, -v` - Enable verbose logging
199142
200143### `exists` - Package Existence
201144
202Check if a package exists:
145Check whether a package exists in the registry:
203146
204147```bash
205# Check if package exists
206buddy exists @types/unknown-package
148# Check if a package exists
149buddy exists react
207150
208# Check multiple packages
209buddy exists react vue angular
210
211# Check with version
212buddy exists react@18.0.0
213
214# Silent mode (exit code only)
215buddy exists react --silent
151# Check a name you expect to be free
152buddy exists nonexistent-package-xyz
216153```
217154
218## Package Comparison
219
220### `compare` - Version Comparison
221
222Compare package versions:
155The command exits `0` when the package exists and `1` when it does not, so it
156can be used directly in shell conditionals:
223157
224158```bash
225# Compare two versions
226buddy compare react 17.0.0 18.0.0
227
228# Compare with current
229buddy compare react --current 17.0.0 --target 18.0.0
230
231# Show breaking changes
232buddy compare react 17.0.0 18.0.0 --breaking-changes
233
234# Include changelog
235buddy compare react 17.0.0 18.0.0 --changelog
236
237# Detailed comparison
238buddy compare react 17.0.0 18.0.0 --detailed
159if buddy exists my-new-package-name; then
160 echo "name is taken"
161fi
239162```
240163
241### `diff` - Package Differences
242
243Show differences between package versions:
244
245```bash
246# Show package.json differences
247buddy diff react 17.0.0 18.0.0
248
249# Show dependency differences
250buddy diff react 17.0.0 18.0.0 --deps
251
252# Show size differences
253buddy diff react 17.0.0 18.0.0 --size
254
255# Show vulnerability differences
256buddy diff react 17.0.0 18.0.0 --vulnerabilities
257```
258
259## Registry Operations
260
261### `registry` - Registry Management
262
263Manage package registries:
264
265```bash
266# List configured registries
267buddy registry list
268
269# Add new registry
270buddy registry add --name company --url https://npm.company.com
271
272# Set default registry
273buddy registry default company
274
275# Test registry connection
276buddy registry test company
277
278# Remove registry
279buddy registry remove company
280```
281
282### `whoami` - Registry Authentication
283
284Check registry authentication:
285
286```bash
287# Check current user
288buddy whoami
289
290# Check for specific registry
291buddy whoami --registry npm
292
293# Check all registries
294buddy whoami --all
295```
296
297## Package Validation
298
299### `validate` - Package Validation
300
301Validate package configurations:
302
303```bash
304# Validate package.json
305buddy validate
306
307# Validate dependencies
308buddy validate --deps
309
310# Check for security issues
311buddy validate --security
312
313# Check licenses
314buddy validate --licenses
315
316# Validate workspace packages
317buddy validate --workspaces
318```
319
320### `audit` - Security Audit
321
322Perform security audit:
323
324```bash
325# Basic audit
326buddy audit
327
328# Audit with fix suggestions
329buddy audit --fix
330
331# Audit specific severity
332buddy audit --severity high
333
334# Audit production only
335buddy audit --production
336
337# Generate audit report
338buddy audit --report --output audit-report.json
339```
340
341## Package Management
342
343### `install` - Install Packages
344
345Install or update packages:
346
347```bash
348# Install package
349buddy install lodash
350
351# Install with version
352buddy install lodash@4.17.21
353
354# Install as dev dependency
355buddy install --dev @types/lodash
356
357# Install globally
358buddy install --global typescript
359
360# Install from specific registry
361buddy install lodash --registry company
362```
363
364### `uninstall` - Remove Packages
365
366Remove packages:
367
368```bash
369# Remove package
370buddy uninstall lodash
371
372# Remove dev dependency
373buddy uninstall --dev @types/lodash
374
375# Remove global package
376buddy uninstall --global typescript
164**Options:**
377165
378# Remove and update dependencies
379buddy uninstall lodash --update-deps
380```
166- `--verbose, -v` - Enable verbose logging
381167
382## Workspace Operations
168## Package Comparison
383169
384### `workspace` - Workspace Commands
170### `compare` - Version Comparison
385171
386Manage monorepo workspaces:
172Compare two versions of a package:
387173
388174```bash
389# List workspaces
390buddy workspace list
391
392# Show workspace info
393buddy workspace info packages/ui
394
395# Check workspace dependencies
396buddy workspace deps packages/ui
397
398# Update workspace
399buddy workspace update packages/ui
175# Compare two versions
176buddy compare react 17.0.0 18.0.0
400177
401# Validate workspace
402buddy workspace validate packages/ui
178# Compare across a major boundary
179buddy compare typescript 4.9.0 5.0.0
403180```
404181
405## Output Formats
406
407All package commands support multiple output formats:
408
409```bash
410# JSON output
411buddy info react --json
412
413# Table format
414buddy outdated --table
415
416# YAML output
417buddy check --yaml
182Both versions are positional and required. The output reports the update type
183(`major`, `minor` or `patch`), how many published versions sit between the two,
184and which of them is newer.
418185
419# CSV format
420buddy outdated --csv
186**Options:**
421187
422# Custom format
423buddy info react --format "{name}@{version}"
424```
188- `--verbose, -v` - Enable verbose logging
425189
426190## Configuration
427191
428Package commands respect global configuration:
192`--config` is a global option, so it works on every command:
429193
430194```bash
431# Use specific config file
432buddy check --config custom-config.ts
433
434# Override registry
435buddy info react --registry https://npm.company.com
436
437# Override strategy
438buddy check --strategy major
439
440# Debug mode
441buddy check --debug
442
443# Verbose output
444buddy check --verbose
195# Use a specific config file
196buddy check react --config custom-config.ts
445197```
446198
199`check` reads `packages.strategy` from the configuration file and `--strategy`
200overrides it for that run. The registry lookup commands (`info`, `versions`,
201`latest`, `deps`, `compare`, `search`, `exists`) query the registry directly and
202take no configuration beyond the flags listed above.
203
447204## Examples
448205
449### Daily Package Health Check
206### Investigating a package before adding it
450207
451208```bash
452# Comprehensive package health check
453buddy outdated --table && \
454buddy audit --severity high && \
455buddy validate --deps
209buddy exists fast-glob && \
210buddy info fast-glob && \
211buddy deps fast-glob --all
456212```
457213
458### Security-Focused Analysis
214### Planning an upgrade
459215
460216```bash
461# Check for security updates
462buddy check --security-only --with-changelog
217# See what versions are available
218buddy versions typescript --latest 20
463219
464# Audit for vulnerabilities
465buddy audit --production --report
466```
467
468### Monorepo Package Management
469
470```bash
471# Check all workspaces
472buddy workspace list | xargs -I {} buddy check --workspace {}
220# Understand the jump
221buddy compare typescript 5.8.2 5.9.0
473222
474# Validate workspace dependencies
475buddy workspace validate --all
223# Check what Buddy would do with it
224buddy check typescript --strategy minor
476225```
477226
478227See [Package Management](/features/package-management) for more details on package handling features.
docs/cli/setup.mdmodified+159-145
Changes to docs/cli/setup.md
@@ -115,11 +115,12 @@ Found 2 available integration(s):
115115### Pre-flight Validation
116116
117117```
118�� Pre-flight Validation
119✅ Git repository detected
120✅ Bun v1.2.19 detected
121⚠️ Found 2 existing workflows. Some may conflict with Buddy workflows.
122�� GitHub CLI detected. This can help with authentication.
118�� Pre-flight Validation:
119⚠️ Warnings:
120 • Found 2 existing workflow(s). Some may conflict with Buddy workflows.
121�� Suggestions:
122 • Using Bun v1.2.19
123 • GitHub CLI detected. This can help with authentication.
123124```
124125
125126**Environment Checks:**
@@ -163,9 +164,9 @@ Found 2 available integration(s):
163164### Interactive Progress Tracking
164165
165166```
166�� Setup Progress: 75% [███████████████░░░░░]
167�� Current Step: Workflow Generation (6/8)
168✅ Completed: Pre-flight checks, Project analysis, Repository Detection, GitHub Token Setup, Repository Settings
167�� Setup Progress: 80% [████████████████░░░░]
168�� Current Step: Workflow Configuration (8/10)
169✅ Completed: Detecting existing configurations, Discovering integrations, Running pre-flight checks, Analyzing project, Repository Detection, GitHub Token Setup, Repository Settings
169170```
170171
171172**Progress Features:**
@@ -176,10 +177,10 @@ Found 2 available integration(s):
176177- **Time tracking** - Monitors setup duration for performance insights
177178- **Recovery support** - Maintains progress state for resumption after interruptions
178179
179### Step 3: Repository Detection & Validation
180### Step 5: Repository Detection & Validation
180181
181182```
182�� Step 1: Repository Detection
183�� Repository Detection
183184✅ Detected repository: your-org/your-repo
184185�� GitHub URL: https://github.com/your-org/your-repo
185186```
@@ -193,24 +194,24 @@ Automatically detects your GitHub repository from `git remote get-url origin` an
193194- **Private repository support** - Enhanced validation for private repositories with appropriate token scopes
194195- **Organization settings** - Checks for organization-level restrictions that might affect setup
195196
196### Step 4: GitHub Token Setup
197### Step 6: GitHub Token Setup
197198
198199```
199�� Step 2: GitHub Token Setup
200For full functionality, Buddy needs a Personal Access Token (PAT).
200�� GitHub Token Setup
201For full functionality, Buddy needs appropriate GitHub permissions.
201202This enables workflow file updates and advanced GitHub Actions features.
202203```
203204
204205Provides three options:
205206
206- **Create new token** - Full guidance through PAT creation process
207- **Have existing token** - Setup for existing PAT
208- **Skip for now** - Use limited GITHUB_TOKEN permissions
207- **Use organization/repository secrets** - A PAT is already configured as an organization or repository secret
208- **Set up a new Personal Access Token** - Full guidance through PAT creation and secret configuration
209- **Use default GITHUB_TOKEN only** - Limited permissions; workflow file updates will not work
209210
210### Step 5: Repository Settings
211### Step 7: Repository Settings
211212
212213```
213�� Step 3: Repository Settings
214�� Repository Settings
214215```
215216
216217Guides you through configuring GitHub Actions permissions:
@@ -219,32 +220,35 @@ Guides you through configuring GitHub Actions permissions:
2192202. Select "Read and write permissions"
2202213. Enable "Allow GitHub Actions to create and approve pull requests"
221222
222### Step 6: Workflow Configuration
223### Step 8: Workflow Configuration
223224
224225```
225⚙️ Step 4: Workflow Configuration
226What type of update schedule would you like?
226⚙️ Workflow Configuration
227? What type of update schedule would you like?
227228```
228229
229230Choose from carefully crafted presets:
230231
231232#### Available Presets
232233
233| Preset | Description | Dashboard | Updates | Auto-merge |
234|--------|-------------|-----------|---------|------------|
235| **Standard Setup** | Balanced approach for most projects | 3x/week | Mon/Wed/Fri | Patch only |
236| **High Frequency** | Multiple checks per day | Daily | Every 6 hours | Patch only |
237| **Security Focused** | Security-first approach | Daily | Every 4 hours | Security patches |
238| **Minimal Updates** | Low-frequency updates | Weekly | Monday only | Manual |
239| **Development/Testing** | Testing and debugging | Manual | Every 15 min | Disabled |
240| **Custom Configuration** | Build your own schedule | Custom | Custom | Custom |
234| Preset | Description |
235|--------|-------------|
236| **Standard Setup (Recommended)** | Dashboard updates 3x/week, dependency updates on schedule |
237| **High Frequency** | Check for updates multiple times per day |
238| **Security Focused** | Frequent patch updates with security-first approach |
239| **Minimal Updates** | Weekly checks, lower frequency |
240| **Development/Testing** | Manual triggers + frequent checks for testing |
241| **Custom Configuration** | Create your own schedule |
241242
242### Step 7: Configuration File Generation
243The preset names the intent you picked; the workflow it writes is the same either way. See [Preset Details](#preset-details) for what that means once setup is done.
244
245### Step 9: Configuration File Generation
243246
244247```
245�� Step 5: Configuration File
246✅ Created buddy.config.json with your repository settings.
248�� Configuration File
249✅ Created buddy.config.ts with your repository settings.
247250�� You can edit this file to customize Buddy's behavior.
251�� The TypeScript config provides better IntelliSense and type safety.
248252```
249253
250254Creates a complete configuration file with:
@@ -255,46 +259,45 @@ Creates a complete configuration file with:
255259- Package strategies
256260- Default options
257261
258### Step 8: Workflow Generation
262### Step 10: Workflow Generation
259263
260264```
261�� Step 6: Workflow Generation
262✨ Setting up Standard Setup...
263�� Dashboard updates 3x/week, balanced dependency updates
265�� Workflow Generation
266✨ Setting up Standard Project...
267�� Daily patch updates, weekly minor updates, monthly major updates
268Generated unified buddy workflow (combines check, update, and dashboard)
269Generated GitHub Actions security audit workflow (buddy-security.yml)
270✓ Generated unified workflow in .github/workflows
264271```
265272
266Generates three core workflows:
267
268#### 1. Dashboard Workflow (`buddy-dashboard.yml`)
273Generates two workflows:
269274
270- **Schedule**: Monday, Wednesday, Friday at 9 AM UTC
271- **Purpose**: Manages dependency dashboard issue
272- **Features**: Manual triggers, dry-run mode, verbose logging
275#### 1. Unified Workflow (`buddy.yml`)
273276
274#### 2. Update Check Workflow (`buddy-check.yml`)
277- **Schedule**: dependency updates every 2 hours, dashboard 15 minutes later, cleanup daily at 4 AM UTC, health report Monday at 9 AM UTC
278- **Events**: `pull_request`, `issues`, `issue_comment`, `pull_request_review_comment` and `workflow_run`, so a ticked rebase box or an `@buddy` comment is acted on immediately rather than waited for
279- **Purpose**: One workflow covering checks, updates, the dashboard, reviews and comment commands
280- **Features**: `workflow_dispatch` with a `job` input to run a single job by hand
275281
276- **Schedule**: Every 15 minutes
277- **Purpose**: Auto-rebase PRs with checked rebase boxes
278- **Features**: Automatic PR updates, conflict resolution
282#### 2. Security Audit Workflow (`buddy-security.yml`)
279283
280#### 3. Update Workflow (`buddy-update.yml`)
284- **Schedule**: Monday at 6 AM UTC, plus every push and pull request touching `.github/workflows/**`
285- **Purpose**: Static-analyses your GitHub Actions workflows for supply-chain footguns
286- **Features**: Kept separate so its path filters fire independently of the dependency pipeline
281287
282- **Schedule**: Based on selected preset
283- **Purpose**: Scheduled dependency updates
284- **Features**: Manual triggers, strategy selection, package filtering
288If an earlier version of Buddy left `buddy-check.yml`, `buddy-update.yml`, `buddy-dashboard.yml` or `gh-audit.yml` behind, setup deletes them — their jobs now live in `buddy.yml` and `buddy-security.yml`.
285289
286290### Workflow Validation & Testing
287291
288292```
289293�� Validating Generated Workflows
290✅ buddy-dashboard.yml validated successfully
291✅ buddy-check.yml validated successfully
292✅ buddy-update.yml validated successfully
293294```
294295
296The checks live in `validateWorkflowGeneration`, exported from `@buddysh/buddy/setup`, so you can run them over a workflow of your own as well.
297
295298**Validation Features:**
296299
297- **YAML syntax validation** - Ensures all generated workflows are syntactically correct
300- **YAML syntax validation** - Ensures a workflow is syntactically correct
298301- **Required field verification** - Validates presence of name, on, jobs, and other essential fields
299302- **Security best practices** - Checks token usage, permissions, and security configurations
300303- **Buddy integration** - Verifies workflows include proper buddy execution commands
@@ -307,17 +310,13 @@ Generates three core workflows:
307310- **Secret handling** - Validates secure handling of tokens and sensitive information
308311- **Workflow permissions** - Checks for explicit permission definitions and security boundaries
309312
310### Step 9: Final Instructions & Integration Notifications
313### Final Instructions & Integration Notifications
311314
312315```
313316�� Setup Complete!
314✅ Generated 3 core workflows in .github/workflows/:
315
316 - buddy-dashboard.yml (Dependency Dashboard Management)
317 - buddy-check.yml (Auto-rebase PR checker)
318 - buddy-update.yml (Scheduled dependency updates)
319
320�� Configuration file: buddy.config.json
317✅ Generated unified buddy workflow in .github/workflows/:
318 - buddy.yml (Combined check, update, and dashboard management)
319�� Configuration file: buddy.config.ts
321320```
322321
323322Provides clear next steps with:
@@ -425,16 +424,17 @@ buddy setup --non-interactive --token-setup new-pat
425424
426425### Preset Options
427426
427Every preset writes the same `buddy.yml`: dependency updates every 2 hours on the `patch` strategy, the dashboard 15 minutes behind them, and a manual trigger for running any single job. The preset records the cadence you intended — change the cadence itself in the workflow's `schedule:` block afterwards.
428
428429#### Standard Preset
429430
430431```bash
431432buddy setup --non-interactive --preset standard
432433```
433434
434- Balanced approach for most projects
435- Every 2 hours schedule for testing
436- Dry-run enabled by default
437- Manual triggers available
435- Reported as **Standard Project**
436- Daily patch updates, weekly minor updates, monthly major updates
437- The default when `--preset` is omitted
438438
439439#### Testing Preset
440440
@@ -442,10 +442,9 @@ buddy setup --non-interactive --preset standard
442442buddy setup --non-interactive --preset testing
443443```
444444
445- Reported as **Development/Testing**
446- Manual trigger + every 20 minutes (for testing)
445447- Optimized for development and testing
446- Every 2 hours schedule with enhanced logging
447- Dry-run mode by default
448- Verbose output and detailed summaries
449448
450449#### Security Preset
451450
@@ -453,10 +452,9 @@ buddy setup --non-interactive --preset testing
453452buddy setup --non-interactive --preset security
454453```
455454
456- Security-focused configuration
457- Every 2 hours schedule for rapid security updates
458- Enhanced monitoring and reporting
459- Security-first update strategy
455- Reported as **Security Focused**
456- Frequent patch updates with security-first approach
457- Suitable for security-critical applications
460458
461459#### High-Frequency Preset
462460
@@ -464,9 +462,8 @@ buddy setup --non-interactive --preset security
464462buddy setup --non-interactive --preset high-frequency
465463```
466464
467- Multiple updates per day
468- Every 2 hours schedule
469- Aggressive update strategy
465- Reported as **High Frequency Updates**
466- Check for updates 4 times per day (6AM, 12PM, 6PM, 12AM)
470467- Suitable for active development
471468
472469#### Minimal Preset
@@ -475,10 +472,9 @@ buddy setup --non-interactive --preset high-frequency
475472buddy setup --non-interactive --preset minimal
476473```
477474
478- Low-frequency updates
479- Every 2 hours schedule (same as others)
480- Conservative approach
481- Minimal noise and disruption
475- Reported as **Minimal Updates**
476- Weekly patch updates, monthly minor/major updates
477- Conservative approach for stable projects
482478
483479### CI/CD Integration Examples
484480
@@ -576,76 +572,99 @@ echo "Buddy setup complete!"
576572
577573The setup process creates several files:
578574
579### Configuration File (`buddy.config.json`)
575### Configuration File (`buddy.config.ts`)
580576
581```json
582{
583 "repository": {
584 "owner": "your-org",
585 "name": "your-repo",
586 "provider": "github"
577```typescript
578import type { BuddyConfig } from '@buddysh/buddy'
579
580const config: BuddyConfig = {
581 repository: {
582 owner: 'your-org',
583 name: 'your-repo',
584 provider: 'github',
585 // Uses GITHUB_TOKEN by default
587586 },
588 "dashboard": {
589 "enabled": true,
590 "pin": false,
591 "title": "Dependency Dashboard"
587 dashboard: {
588 enabled: true,
589 title: 'Dependency Dashboard',
590 // issueNumber: undefined, // Auto-generated
592591 },
593 "workflows": {
594 "enabled": true,
595 "outputDir": ".github/workflows",
596 "templates": {
597 "daily": true,
598 "weekly": true,
599 "monthly": true
600 }
592 workflows: {
593 enabled: true,
594 outputDir: '.github/workflows',
595 templates: {
596 daily: true,
597 weekly: true,
598 monthly: true,
599 },
600 custom: [],
601601 },
602 "packages": {
603 "strategy": "all",
604 "ignore": []
602 packages: {
603 strategy: 'all',
604 ignore: [],
605 ignorePaths: [],
605606 },
606 "verbose": false
607 verbose: false,
607608}
609
610export default config
608611```
609612
610613### Workflow Files
611614
612#### Dashboard Workflow
615#### Unified Workflow (`buddy.yml`)
613616
614617```yaml
615name: Buddy Dashboard
618name: Buddy
616619
617620on:
618 schedule:
621 pull_request:
622 types: [edited, opened, ready_for_review, synchronize, closed]
619623
620 - cron: '0 9 _ _ 1,3,5' # Monday, Wednesday, Friday at 9 AM UTC
624 issues:
625 types: [edited, opened]
621626
622 workflow_dispatch: # Manual triggering
623```
627 issue_comment:
628 types: [created]
624629
625#### Update Check Workflow
630 pull_request_review_comment:
631 types: [created]
626632
627```yaml
628name: Buddy Check
633 workflow_run:
634 types: [completed]
629635
630on:
631636 schedule:
632637
633 - cron: '_/15 _ _ _ _' # Check every 15 minutes
638 - cron: '0 */2 * * *' # Dependency updates
639 - cron: '15 */2 * * *' # Dashboard, 15 minutes behind
640 - cron: '0 4 * * *' # Branch cleanup
641 - cron: '0 9 * * 1' # Weekly dependency-health report
634642
635 workflow_dispatch: # Manual trigger
643 workflow_dispatch: # Manual trigger, with job/strategy/dry_run inputs
636644```
637645
638#### Update Workflow
646#### Security Audit Workflow (`buddy-security.yml`)
639647
640648```yaml
641name: Buddy Update
649name: GH Actions Security Audit
642650
643651on:
652 push:
653 branches: [main]
654 paths:
655
656 - '.github/workflows/**'
657
658 pull_request:
659 paths:
660
661 - '.github/workflows/**'
662
644663 schedule:
645664
646 - cron: '0 9 _ * 1,3,5' # Mon, Wed, Fri
665 - cron: '0 6 * * 1' # Monday 06:00 UTC — weekly drift check
647666
648 workflow_dispatch: # Manual trigger with options
667 workflow_dispatch:
649668```
650669
651670## Token Setup Guide
@@ -716,44 +735,36 @@ Configure GitHub Actions permissions:
716735
717736## Preset Details
718737
738A preset is a statement of intent. Setup prints the one you chose and then writes the same `buddy.yml` for every preset: dependency updates every 2 hours (`0 */2 * * *`) on the `patch` strategy, the dashboard 15 minutes later, branch cleanup daily at 4 AM UTC and a dependency-health report on Monday at 9 AM UTC. Edit that `schedule:` block to change the cadence.
739
719740### Standard Setup (Recommended)
720741
721- **Dashboard**: Monday, Wednesday, Friday at 9 AM UTC
722- **Updates**: Monday, Wednesday, Friday at 9 AM UTC
723- **Strategy**: All updates (major, minor, patch)
724- **Auto-merge**: Disabled (manual review required)
742- **Reported as**: Standard Project
743- **Intent**: Daily patch updates, weekly minor updates, monthly major updates
725744- **Best for**: Most projects wanting balanced automation
726745
727746### High Frequency
728747
729- **Dashboard**: Daily at 9 AM UTC
730- **Updates**: Every 6 hours
731- **Strategy**: All updates
732- **Auto-merge**: Disabled
748- **Reported as**: High Frequency Updates
749- **Intent**: Check for updates 4 times per day (6AM, 12PM, 6PM, 12AM)
733750- **Best for**: Active projects needing quick updates
734751
735752### Security Focused
736753
737- **Dashboard**: Daily at 9 AM UTC
738- **Updates**: Every 4 hours
739- **Strategy**: All updates
740- **Auto-merge**: Disabled
754- **Reported as**: Security Focused
755- **Intent**: Frequent patch updates with security-first approach
741756- **Best for**: Security-critical applications
742757
743758### Minimal Updates
744759
745- **Dashboard**: Weekly on Monday at 9 AM UTC
746- **Updates**: Monday only at 9 AM UTC
747- **Strategy**: All updates
748- **Auto-merge**: Disabled
760- **Reported as**: Minimal Updates
761- **Intent**: Weekly patch updates, monthly minor/major updates
749762- **Best for**: Stable projects with low change frequency
750763
751764### Development/Testing
752765
753- **Dashboard**: Manual trigger only
754- **Updates**: Every 15 minutes
755- **Strategy**: Patch updates only
756- **Auto-merge**: Disabled
766- **Reported as**: Development/Testing
767- **Intent**: Manual trigger + every 20 minutes (for testing)
757768- **Best for**: Testing Buddy functionality
758769
759770## Post-Setup
@@ -764,7 +775,7 @@ After running setup, follow these steps:
764775
765776```bash
766777# Check configuration
767cat buddy.config.json
778cat buddy.config.ts
768779
769780# Review workflows
770781ls -la .github/workflows/
@@ -776,15 +787,18 @@ ls -la .github/workflows/
776787# Test repository detection
777788buddy scan --verbose
778789
779# Test dashboard creation
780buddy dashboard --dry-run
790# See what an update run would open, without opening it
791buddy update --dry-run
792
793# Create or refresh the dashboard issue
794buddy dashboard
781795```
782796
783797### 3. Commit Changes
784798
785799```bash
786800# Add generated files
787git add .github/workflows/ buddy.config.json
801git add .github/workflows/ buddy.config.ts
788802
789803# Commit setup
790804git commit -m "Add Buddy dependency management workflows"
@@ -797,7 +811,7 @@ git push
797811
7988121. Go to repository **Actions** tab
7998132. Verify workflows appear in the list
8003. Test manual trigger on dashboard workflow
8143. Test the manual trigger on the Buddy workflow, picking the `dashboard` job
8018154. Check workflow permissions if needed
802816
803817## Troubleshooting
@@ -884,7 +898,7 @@ buddy setup --verbose
884898buddy setup --non-interactive --preset testing --verbose
885899
886900# If setup completes, test scanning
887buddy scan --dry-run
901buddy scan --verbose
888902```
889903
890904## Technical Implementation
docs/cli/update.mdmodified+42-12
Changes to docs/cli/update.md
@@ -19,6 +19,8 @@ buddy scan [options]
1919- `--pattern <pattern>` - Glob pattern to match packages
2020- `--strategy <type>` - Update strategy: major|minor|patch|all (default: all)
2121- `--ignore <names>` - Comma-separated list of packages to ignore
22- `--respect-latest` - Leave `latest`, `*` and other dynamic ranges alone (default)
23- `--no-respect-latest` - Propose updates for dynamic ranges too
2224
2325### Examples
2426
@@ -40,6 +42,9 @@ buddy scan --strategy minor
4042
4143# Ignore specific packages
4244buddy scan --ignore "eslint,prettier"
45
46# Include packages pinned to "latest" or "*"
47buddy scan --no-respect-latest
4348```
4449
4550### Output
@@ -73,6 +78,8 @@ buddy update [options]
7378- `--strategy <type>` - Update strategy: major|minor|patch|all (default: all)
7479- `--ignore <names>` - Comma-separated list of packages to ignore
7580- `--dry-run` - Preview changes without making them
81- `--respect-latest` - Leave `latest`, `*` and other dynamic ranges alone (default)
82- `--no-respect-latest` - Update dynamic ranges too
7683
7784### Examples
7885
@@ -91,6 +98,9 @@ buddy update --verbose
9198
9299# Ignore specific packages
93100buddy update --ignore "@types/node,eslint"
101
102# Include packages pinned to "latest" or "*"
103buddy update --no-respect-latest
94104```
95105
96106### Dry Run Output
@@ -238,37 +248,57 @@ When checked (marked with `x`):
238248
239249All update commands respect configuration from `buddy.config.ts`:
240250
241### Strategy Override
251### Strategy
252
253`scan` and `update` always send a strategy of their own — `all` unless `--strategy` says otherwise — so `packages.strategy` is what the programmatic API and your own tooling read, not what these two commands run with. On the command line, name the strategy you want:
254
255```bash
256# Patch releases only, for this run
257buddy update --strategy patch
258```
259
260To hold a strategy for particular packages rather than the whole run, put it in a package rule. Rules run after the global strategy filter, so a rule narrows what those packages may propose whatever `--strategy` was passed:
242261
243262```typescript
244// Config strategy can be overridden by CLI
245263export default {
246264 packages: {
247 strategy: 'patch' // Default strategy
265 strategy: 'all',
266 rules: [
267 {
268 matchPackages: ['react', 'react-dom'],
269 strategy: 'patch' // React moves at patch pace regardless
270 }
271 ]
248272 }
249273}
250274```
251275
252```bash
253# Override config strategy
254buddy update --strategy minor
276### Ignore Lists
277
278```typescript
279export default {
280 packages: {
281 ignore: ['@types/node'] // Ignored on every run
282 }
283}
255284```
256285
257### Ignore Lists
286Names in `ignore` are matched exactly — `@types/*` matches no package at all. Use a rule for patterns:
258287
259288```typescript
260// Combine config and CLI ignore lists
261289export default {
262290 packages: {
263 ignore: ['@types/node'] // Always ignored
291 rules: [
292 { matchPackages: ['@types/*'], enabled: false }
293 ]
264294 }
265295}
266296```
267297
268298```bash
269# Additional ignores for this run
299# Ignore a different set for this run
270300buddy update --ignore "eslint,prettier"
271# Result: ignores @types/node, eslint, and prettier
301# Result: ignores eslint and prettier; the config list is not consulted
272302```
273303
274304## Error Handling
@@ -346,7 +376,7 @@ name: Dependency Updates
346376on:
347377 schedule:
348378
349 - cron: '0 2 _ _ 1' # Weekly on Monday
379 - cron: '0 2 * * 1' # Weekly on Monday
350380
351381 workflow_dispatch:
352382
docs/cli/utility.mdmodified+61-68
Changes to docs/cli/utility.md
@@ -12,62 +12,49 @@ buddy open-settings [options]
1212
1313### Description
1414
15Quickly open the GitHub settings pages needed to configure permissions for buddy. This includes repository settings, organization settings, and Actions configurations.
15Quickly open the GitHub settings pages needed to configure permissions for buddy. It opens the repository's Actions settings, follows with the organization's, and prints the exact options to change on each.
1616
1717### Options
1818
1919| Option | Description | Default |
2020|--------|-------------|---------|
21| `--type <type>` | Settings type to open | `'repo'` |
2221| `--verbose, -v` | Enable verbose logging | `false` |
2322
24### Settings Types
25
26- **`repo`** - Repository settings page
27- **`actions`** - Repository Actions settings
28- **`org`** - Organization settings
29- **`tokens`** - Personal access tokens page
30
3123### Examples
3224
3325```bash
34# Open repository settings
26# Open the Actions settings pages for this repository
3527buddy open-settings
3628
37# Open Actions settings
38buddy open-settings --type actions
39
40# Open organization settings
41buddy open-settings --type org
42
43# Open personal tokens page
44buddy open-settings --type tokens
29# Show how the repository was resolved
30buddy open-settings --verbose
4531```
4632
4733### What Opens
4834
49#### Repository Settings (`--type repo`)
35The repository comes from `repository.owner` and `repository.name` in `buddy.config.ts`, falling back to `git remote get-url origin`.
36
37#### Repository Actions settings
5038
51- General repository settings
52- Collaborators and teams
53- Branches and protection rules
39`https://github.com/<owner>/<repo>/settings/actions`
5440
55#### Actions Settings (`--type actions`)
41- Workflow permissions — select "Read and write permissions"
42- "Allow GitHub Actions to create and approve pull requests"
5643
57- GitHub Actions permissions
58- Workflow permissions
59- Runner settings
44#### Organization Actions settings
6045
61#### Organization Settings (`--type org`)
46`https://github.com/organizations/<owner>/settings/actions`
6247
63- Member privileges
64- Third-party access
65- GitHub Apps
48- The same two settings one level up, which may override the repository's
6649
67#### Tokens (`--type tokens`)
50If neither the config nor the git remote identifies a repository, buddy prints both URLs with placeholders instead of opening anything.
6851
69- Personal access tokens management
70- Fine-grained tokens
52### Related Pages
53
54buddy does not open these, but setup points you at them:
55
56- Personal access tokens — `https://github.com/settings/tokens`
57- Repository secrets — `https://github.com/<owner>/<repo>/settings/secrets/actions`
7158
7259## schedule
7360
@@ -79,53 +66,47 @@ buddy schedule [options]
7966
8067### Description
8168
82Execute buddy updates on a predefined schedule. This command is typically used in CI/CD environments or cron jobs for automated dependency management.
69Starts a scheduler in the foreground: it works out the next run from a cron expression, scans for updates when that time arrives, and opens pull requests for what it finds. The process stays alive until you stop it with Ctrl+C, so it belongs on a machine that stays up. On a CI runner, put the cadence in the workflow trigger and run `buddy update` instead, as the CI/CD Integration section below shows.
8370
8471### Options
8572
8673| Option | Description | Default |
8774|--------|-------------|---------|
88| `--cron <expression>` | Cron expression for scheduling | From config |
89| `--timezone <tz>` | Timezone for scheduling | `'UTC'` |
90| `--dry-run` | Show what would be updated without making changes | `false` |
91| `--strategy <type>` | Update strategy override | From config |
75| `--strategy <type>` | Update strategy, and the cadence that goes with it | `all` |
9276| `--verbose, -v` | Enable verbose logging | `false` |
9377
9478### Examples
9579
9680```bash
97# Run scheduled updates (uses config)
81# Run scheduled updates
9882buddy schedule
9983
100# Override cron schedule
101buddy schedule --cron "0 2 * * 1"
102
103# Different timezone
104buddy schedule --timezone "America/New*York"
105
106# Dry run to preview changes
107buddy schedule --dry-run
108
109# Override update strategy
84# Daily patch updates
11085buddy schedule --strategy patch
86
87# Watch what the scheduler is doing
88buddy schedule --verbose
11189```
11290
113### Cron Expressions
91### Schedules
11492
115Common scheduling patterns:
93The strategy picks the cadence, so that larger updates arrive less often:
11694
117```bash
118# Every day at 2 AM UTC
119buddy schedule --cron "0 2 * * *"
95| Strategy | Cron |
96|----------|------|
97| `patch` | `0 2 * * *` |
98| `minor` | `0 2 * * 1,4` |
99| `major` | `0 2 * * 1` |
100| `all` | `0 2 * * 1` |
120101
121# Weekly on Monday at 2 AM
122buddy schedule --cron "0 2 * * 1"
102The next run is derived from the hour and minute fields; the day-of-month and day-of-week fields are not evaluated, so all four of these fire at 2 AM every day. When the day has to matter, drive the cadence from a real cron daemon or a workflow `schedule:` trigger.
123103
124# Every 6 hours
125buddy schedule --cron "0 */6 * * *"
104On start the scheduler prints the expression it settled on and when it will next fire:
126105
127# Weekdays at 9 AM
128buddy schedule --cron "0 9 * * 1-5"
106```bash
107✅ Scheduler started with cron: 0 2 * * 1
108�� Next run: 2026-09-01T02:00:00.000Z
109�� Press Ctrl+C to stop the scheduler
129110```
130111
131112### Configuration Integration
@@ -135,17 +116,25 @@ The schedule command uses settings from `buddy.config.ts`:
135116```typescript
136117export default {
137118 schedule: {
138 cron: '0 2 * * 1', // Weekly on Monday at 2 AM
139 timezone: 'UTC',
119 timezone: 'America/New_York', // Time zone the cron is read in
120 },
121 repository: {
122 provider: 'github',
123 owner: 'your-org',
124 name: 'your-repo',
140125 },
141 packages: {
142 strategy: 'patch', // Used by scheduler
126 pullRequest: {
127 labels: ['dependencies'],
143128 },
144129} satisfies BuddyConfig
145130```
146131
132Repository details are required: without `repository.provider`, `repository.owner` and `repository.name`, the command exits before the scheduler starts. Pull requests are only opened when `pullRequest` is configured as well — otherwise a run scans, reports what it found, and stops there.
133
147134### CI/CD Integration
148135
136A runner exits when the job does, so there is nothing for a long-lived scheduler to wait for. Let the workflow trigger carry the schedule and run `buddy update`:
137
149138**GitHub Actions**
150139```yaml
151140name: Scheduled Dependencies
@@ -163,19 +152,23 @@ jobs:
163152 steps:
164153
165154 - uses: actions/checkout@v4
166 - uses: oven-sh/setup-bun@v1
167 - run: bunx @buddysh/buddy schedule
155 - uses: oven-sh/setup-bun@v2
156 - run: bunx @buddysh/buddy update --strategy patch --verbose
168157
169158 env:
170159 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
171160```
172161
162Same reasoning on a server you own — cron supplies the cadence, `update` does the work:
163
173164**Cron Job**
174165```bash
175166# Add to crontab
1760 2 * * 1 cd /path/to/project && bunx @buddysh/buddy schedule
1670 2 * * 1 cd /path/to/project && bunx @buddysh/buddy update --strategy patch
177168```
178169
170Reach for `buddy schedule` when you want one resident process instead, supervised by systemd or a process manager.
171
179172### Output
180173
181174The schedule command provides detailed information about:
@@ -189,7 +182,7 @@ The schedule command provides detailed information about:
189182
190183**Schedule not running:**
191184
192- Check cron expression syntax
185- Check the strategy you passed, and the cadence it maps to
193186- Verify timezone settings
194187- Ensure GitHub token is valid
195188
docs/config.mdmodified+59-18
Changes to docs/config.md
@@ -49,7 +49,7 @@ const config: BuddyConfig = {
4949
5050 // Scheduling configuration
5151 schedule: {
52 cron: '0 2 _ _ 1', // Weekly on Monday at 2 AM
52 cron: '0 2 * * 1', // Weekly on Monday at 2 AM
5353 timezone: 'UTC',
5454 },
5555}
@@ -78,7 +78,7 @@ const supportedFiles = [
7878]
7979```
8080
81All dependency files are parsed using the `ts-pkgx` library and updates are applied while preserving formatting, comments, and version prefixes (`^`, `~`, `>=`, etc.).
81All dependency files are parsed using the `ts-pantry` library and updates are applied while preserving formatting, comments, and version prefixes (`^`, `~`, `>=`, etc.).
8282
8383### Package Groups
8484
@@ -128,8 +128,8 @@ All matchers present on a rule must match (AND within a rule).
128128
129129| Matcher | Matches on |
130130| --------------------- | ------------------------------------------------------- |
131| `matchPackages` | Package names or globs (`@types/_`) |
132| `matchEcosystems` | `npm`, `composer`, `github-actions`, `docker`, `pkgx`, `zig` |
131| `matchPackages` | Package names or globs (`@types/*`) |
132| `matchEcosystems` | `npm`, `composer`, `github-actions`, `docker`, `pkgx`, `zig`, `python`, `rust`, `go`, `ruby` |
133133| `matchDepTypes` | `dependencies`, `devDependencies`, `peerDependencies`, … |
134134| `matchUpdateTypes` | `major`, `minor`, `patch` |
135135| `matchFiles` | Globs on the manifest path, for monorepo directories |
@@ -137,9 +137,14 @@ All matchers present on a rule must match (AND within a rule).
137137| `schedule` | Cron window during which the rule applies |
138138
139139A rule with no matchers applies to every update. Configuration validation
140rejects that unless you write `matchPackages: ['_']`, because a matcherless
141rule is almost always a typo'd matcher — and a typo does not disable a rule, it
142widens it.
140rejects that unless you write an explicit catch-all matcher, because a
141matcherless rule is almost always a typo'd matcher — and a typo does not
142disable a rule, it widens it.
143
144Write that catch-all as `matchPackages: ['**']`, not `['*']`. Package names are
145matched as paths, so a single `*` stops at the `/` in a scoped name: `['*']`
146matches `react` but not `@types/node`. Use `['**']` for every package, or
147`['@scope/*']` to target one scope.
143148
144149#### Effects
145150
@@ -204,7 +209,7 @@ Tuesday run holds these back and a Saturday run lets them through:
204209rules: [
205210 {
206211 matchUpdateTypes: ['major'],
207 schedule: '0 0-23 _ _ 6,0',
212 schedule: '0 0-23 * * 6,0',
208213 scheduleTimezone: 'Europe/Berlin',
209214 },
210215]
@@ -222,7 +227,7 @@ rules: [
222227
223228```typescript
224229rules: [
225 { matchPackages: ['*'], prPriority: 0 },
230 { matchPackages: ['**'], prPriority: 0 },
226231 { matchDepTypes: ['dependencies'], prPriority: 10, labels: ['runtime'] },
227232]
228233```
@@ -299,7 +304,7 @@ const config: BuddyConfig = {
299304 custom: [
300305 {
301306 name: 'Security Updates',
302 schedule: '0 _/6 _ _ _', // Every 6 hours
307 schedule: '0 */6 * * *', // Every 6 hours
303308 strategy: 'patch',
304309 autoMerge: true,
305310 reviewers: ['security-team'],
@@ -329,10 +334,18 @@ const config: BuddyConfig = {
329334| Option | Type | Description | Default |
330335|--------|------|-------------|---------|
331336| `strategy` | `'major' \| 'minor' \| 'patch' \| 'all'` | Update strategy | `'all'` |
332| `ignore` | `string[]` | Packages to ignore | `[]` |
337| `ignore` | `string[]` | Package names to ignore, matched exactly | `[]` |
333338| `pin` | `Record<string, string>` | Pin packages to versions | `{}` |
334339| `groups` | `PackageGroup[]` | Package groupings | `undefined` |
335340
341The strategy selects which semver impacts are proposed: `all` admits every
342update, `major` majors only, `minor` minors and patches, `patch` patches only.
343
344`ignore` is compared by exact package name — `@types/*` matches nothing and
345silently ignores nothing. Use a [package rule](#package-rules) with
346`matchPackages` when you want a pattern. (`ignorePaths`, which takes file
347paths, does use globs.)
348
336349### Logging
337350
338351| Option | Type | Description | Default |
@@ -392,7 +405,7 @@ Set `security.enabled: false` for fully offline runs.
392405|--------|------|-------------|---------|
393406| `reviewers` | `string[]` | GitHub usernames for review | `[]` |
394407| `assignees` | `string[]` | GitHub usernames to assign | `[]` |
395| `labels` | `string[]` | Labels to apply | `['dependencies']` |
408| `labels` | `string[]` | Labels to add, on top of the automatic set | `[]` |
396409| `autoMerge` | `AutoMergeConfig` | Auto-merge configuration, see [Auto-Merge](/features/auto-merge) | `undefined` |
397410
398411### Pull Request Templates
@@ -449,12 +462,13 @@ Buddy uses these environment variables:
449462# Required for GitHub operations
450463GITHUB_TOKEN=ghp_xxxxxxxxxxxx
451464
452# Optional: Alternative token name
453GH_TOKEN=ghp_xxxxxxxxxxxx
454
455# Optional: alternative token, preferred when set (needs `workflow` scope)
465# Optional: the workflow token, a PAT with `repo` and `workflow` scopes. Also the
466# last fallback for API operations, used only when GITHUB_TOKEN is unset
456467BUDDY_TOKEN=ghp_xxxxxxxxxxxx
457468
469# Optional: fallback for read-only calls (registry lookups, release notes)
470GH_TOKEN=ghp_xxxxxxxxxxxx
471
458472# Optional: GitHub Enterprise Server. GitHub Actions sets both automatically
459473GITHUB_API_URL=https://github.acme.com/api/v3
460474GITHUB_SERVER_URL=https://github.acme.com
@@ -478,6 +492,20 @@ BUDDY_HTTP_TIMEOUT_MS=30000
478492BUN_CONFIG_NO_CACHE=false
479493```
480494
495### Token precedence
496
497For git and pull request operations the token is resolved in this order:
498`repository.token` from your config, then `GITHUB_TOKEN`, then `BUDDY_TOKEN`.
499The ambient CI token deliberately comes first: it attributes pull requests to
500the CI bot rather than to whoever's personal token happens to be in the
501environment.
502
503Because GitHub Actions always injects `GITHUB_TOKEN`, `BUDDY_TOKEN` never wins
504that lookup on a runner. It has a different job there — it is picked up
505separately as the _workflow_ token, which is what lets Buddy commit changes to
506files under `.github/workflows/`. Set both: `GITHUB_TOKEN` for the API and PR
507work, `BUDDY_TOKEN` for the elevated `workflow` scope.
508
481509## GitHub Enterprise Server
482510
483511Buddy runs unmodified against GitHub Enterprise Server. On a GHES runner,
@@ -647,7 +675,7 @@ Buddy provides comprehensive dependency management across four categories:
647675- **dependencies.yaml**/**dependencies.yml** - Alternative format
648676- **pkgx.yaml**/**pkgx.yml** - pkgx-specific files
649677- **.deps.yaml**/**.deps.yml** - Hidden configuration files
650- Managed via `ts-pkgx` library integration
678- Managed via `ts-pantry` library integration
651679
652680### GitHub Actions
653681
@@ -702,6 +730,19 @@ const config: BuddyConfig = {
702730}
703731```
704732
733Every entry is an exact package name. To exclude a whole family, match it with
734a rule instead:
735
736```typescript
737const config: BuddyConfig = {
738 packages: {
739 rules: [
740 { matchPackages: ['@types/*'], enabled: false },
741 ],
742 },
743}
744```
745
705746#### Strategy Application
706747
707748Update strategies apply to all dependency types:
@@ -709,7 +750,7 @@ Update strategies apply to all dependency types:
709750```typescript
710751const config: BuddyConfig = {
711752 packages: {
712 strategy: 'patch', // Applies to npm, pkgx, AND GitHub Actions
753 strategy: 'patch', // Patch updates only, across npm, pkgx, AND GitHub Actions
713754 },
714755}
715756```
docs/features/auto-merge.mdmodified+3-1
Changes to docs/features/auto-merge.md
@@ -31,9 +31,11 @@ A PR qualifies when **any** listed condition accepts it.
3131|---|---|
3232| `patch-only` | Every update in the PR is a patch bump |
3333| `minor-only` | Every update is minor or patch (no majors) |
34| `security-only` | The PR carries the configured `security.label` |
34| `security-only` | The PR carries the configured `security.label` (default `security`) |
3535| `all` | Any Buddy PR, including major upgrades |
3636
37`security-only` reads a label, and Buddy does not apply that label on its own — a PR gets it because you put it there, either through `pullRequest.labels` or a package rule. Configure `security-only` without arranging for the label and nothing will ever match it.
38
3739Unknown condition names are rejected by config validation rather than ignored, so a typo like `patch_only` fails loudly instead of widening what merges unreviewed.
3840
3941Update types are read from the metadata manifest embedded in each PR body, not from the PR title. A retitled or hand-edited PR therefore cannot talk its way past a `patch-only` policy. A PR whose manifest is missing (opened before manifests existed) or truncated (a very large group whose manifest had to drop rows) is never auto-merged, because neither case proves what the PR actually changes.
docs/features/dependency-dashboard.mdmodified+2-2
Changes to docs/features/dependency-dashboard.md
@@ -183,7 +183,7 @@ name: Dependency Dashboard
183183on:
184184 schedule:
185185
186 - cron: '0 9 _ _ 1,3,5' # Monday, Wednesday, Friday at 9 AM UTC
186 - cron: '0 9 * * 1,3,5' # Monday, Wednesday, Friday at 9 AM UTC
187187
188188jobs:
189189 update-dashboard:
@@ -200,7 +200,7 @@ jobs:
200200 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
201201```
202202
203**�� Ready-to-use workflow**: Buddy includes a pre-built dashboard workflow at `.github/workflows/buddy-dashboard.yml` that you can use directly. It includes manual triggering, dry-run mode, and customizable options.
203**�� Ready-to-use workflow**: you rarely need the workflow above. `buddy setup` writes a single `.github/workflows/buddy.yml` whose dashboard job already refreshes the issue on the `15 */2 * * *` schedule, and it can be run on demand from the Actions tab — pick **Buddy**, then **Run workflow**, then set **Which job to run** to `dashboard`. The same dispatch takes a custom title, a specific issue number and the pin toggle.
204204
205205### Auto-Update
206206
docs/features/dependency-files.mdmodified+37-26
Changes to docs/features/dependency-files.md
@@ -19,7 +19,7 @@ Buddy automatically detects and updates the following dependency file formats:
1919
2020## How It Works
2121
22Buddy uses the `ts-pkgx` library to parse and resolve dependency files, ensuring full compatibility with the pkgx registry ecosystem while supporting tools like Launchpad that reuse the same registry format.
22Buddy uses the `ts-pantry` library to parse and resolve dependency files, ensuring full compatibility with the pkgx registry ecosystem while supporting tools like Launchpad that reuse the same registry format.
2323
2424### Automatic Detection
2525
@@ -260,7 +260,7 @@ export default {
260260 packages: {
261261 rules: [
262262 { matchEcosystems: ['npm'], groupName: 'npm dependencies' },
263 { matchEcosystems: ['launchpad'], groupName: 'pkgx tools' },
263 { matchEcosystems: ['pkgx'], groupName: 'pkgx tools' },
264264 { matchEcosystems: ['github-actions'], groupName: 'GitHub Actions' }
265265 ]
266266 },
@@ -325,32 +325,46 @@ export default {
325325
326326## CLI Commands
327327
328### Scan Specific File Types
328### Scanning
329
330Every manifest in the repository is scanned in one pass; there is no flag that
331narrows a run to one file type. What the CLI does take is a package filter and
332a strategy:
329333
330334```bash
331# Scan only package.json files
332buddy scan --file-type package.json
335# Scan every dependency file Buddy supports
336buddy scan
333337
334# Scan only dependency files
335buddy scan --file-type deps.yaml
338# Scan named packages only
339buddy scan --packages "bun,typescript"
336340
337# Scan specific files
338buddy scan --files "deps.yaml,package.json"
339```
341# Scan a family of packages by pattern
342buddy scan --pattern "@types/*"
340343
341### Update Specific Formats
344# Scan with a specific strategy
345buddy scan --strategy patch
346```
342347
343```bash
344# Update only npm dependencies
345buddy update --package-manager npm
348### Restricting Formats
346349
347# Update only pkgx dependencies
348buddy update --package-manager pkgx
350Narrowing by file or ecosystem is config, not a flag. A rule with
351`enabled: false` drops matching updates entirely, so the run only proposes what
352is left:
349353
350# Update with different strategies per type
351buddy update --strategy package.json:minor,deps.yaml:patch
354```typescript
355export default {
356 packages: {
357 rules: [
358 // Leave the pkgx/Launchpad files alone; npm only
359 { matchEcosystems: ['pkgx'], enabled: false }
360 ]
361 }
362} satisfies BuddyConfig
352363```
353364
365Per-format strategies work the same way — see
366[file-specific configuration](#file-specific-configuration) above.
367
354368## Troubleshooting
355369
356370### Common Issues
@@ -366,8 +380,8 @@ cat deps.yaml
366380
367381**pkgx resolution errors:**
368382```bash
369# Verify ts-pkgx can parse the file
370bunx ts-pkgx resolve deps.yaml
383# Verify ts-pantry can parse the file
384bunx ts-pantry resolve-deps deps.yaml
371385
372386# Check for syntax errors
373387yamllint deps.yaml
@@ -380,14 +394,11 @@ yamllint deps.yaml
380394# ❌ Avoid: 1.*, ^1.0, ~2
381395```
382396
383### Debug Mode
397### Verbose Mode
384398
385399```bash
386# Enable verbose logging for dependency files
387buddy scan --verbose --debug dependency-files
388
389# Show file detection process
390buddy scan --show-files
400# Log the file detection and resolution process
401buddy scan --verbose
391402```
392403
393404## Best Practices
docs/features/dependency-updates.mdmodified+4-4
Changes to docs/features/dependency-updates.md
@@ -1,7 +1,7 @@
11---
22layout: home
33title: Dependency Updates
4description: Buddy replaces Renovate and Dependabot — scanning, grouping, real changelogs, OSV advisories, a pinned dashboard, interactive rebase and auto-merge across eleven ecosystems.
4description: Buddy replaces Renovate and Dependabot — scanning, grouping, real changelogs, OSV advisories, a pinned dashboard, interactive rebase and auto-merge across ten ecosystems.
55
66hero:
77 name: "dependency updates"
@@ -91,7 +91,7 @@ hero:
9191 } satisfies BuddyConfig
9292
9393features:
94 - title: "Eleven ecosystems"
94 - title: "Ten ecosystems"
9595 icon: "🌍"
9696 span: 2
9797 details: "npm, Bun, yarn and pnpm; Composer; GitHub Actions; Docker; pkgx and Launchpad; Zig; and — through the adapter interface — Python, Rust, Go and Ruby. Every lock file that has one is regenerated with the right tool, not hand-edited."
@@ -133,8 +133,8 @@ Then the maintenance commands: `buddy dashboard` refreshes the pinned issue, `bu
133133
134134| Strategy | Updates it proposes |
135135| --- | --- |
136| `patch` | Everything, patch first — the safest default to automate |
137| `minor` | Major and minor, no patch-only churn |
136| `patch` | Patch only — the safest default to automate |
137| `minor` | Minor and patch, no majors |
138138| `major` | Major versions only |
139139| `all` | Everything, regardless of semver impact |
140140
docs/features/github-actions.mdmodified+14-2
Changes to docs/features/github-actions.md
@@ -119,8 +119,20 @@ buddy update
119119# Dry run to preview action updates
120120buddy update --dry-run
121121
122# Assign action updates to specific team
123buddy update --assignee devops-team
122# Keep the run to minor and patch updates
123buddy update --strategy minor
124```
125
126Reviewers, assignees and labels are not flags — they are set once in `buddy.config.ts` and applied to every PR Buddy opens:
127
128```typescript
129// buddy.config.ts
130export default {
131 pullRequest: {
132 teamReviewers: ['devops'],
133 labels: ['dependencies', 'github-actions'],
134 },
135}
124136```
125137
126138## Best Practices
docs/features/labeling-assignment.mdmodified+177-277
Changes to docs/features/labeling-assignment.md
@@ -1,327 +1,227 @@
11# Labeling & Assignment
22
3Buddy provides intelligent labeling and team assignment features to ensure proper pull request categorization and review workflows.
3Every pull request Buddy opens arrives already labelled, and — when you ask for
4it — already carrying the reviewers and assignees the change deserves. Labels
5come from two places: a set Buddy derives from the update itself, and whatever
6your `packages.rules` attach to the packages that matched. Reviewers and
7assignees come from your repository-wide `pullRequest` settings, unioned with
8the same rules.
9
10## Automatic Labels
11
12Buddy derives these from the group it is about to open a PR for. They need no
13configuration and are always present.
14
15| Label | Applied when |
16|---|---|
17| `dependencies` | Always |
18| `major` / `minor` / `patch` | The greatest semver impact in the PR |
19| `npm` | The PR touches a `package.json` |
20| `composer` | It touches `composer.json` or `composer.lock` |
21| `zig` | It touches `build.zig.zon` |
22| `system` | It touches a `deps.yaml`-style dependency file |
23| `github-actions` | It touches a workflow under `.github/workflows/` |
24| *the package name* | The PR updates exactly one package |
25
26A PR bumping `react` on its own therefore opens with `dependencies`, `minor`,
27`npm` and `react` before any rule of yours is consulted.
28
29Labels that do not exist on the repository are retried one at a time and skipped
30with a warning rather than failing the pull request, so a typo'd label costs you
31a label, not a PR.
32
33## Per-Package Labels, Reviewers and Assignees
34
35`packages.rules` is where targeting happens. A rule matches on any combination of
36package name, ecosystem, dependency type, update type, file path, installed
37version and schedule, and attaches `labels`, `reviewers` and `assignees` to
38whatever it matched.
439
5## Dynamic Labeling
40```typescript
41// buddy.config.ts
42import type { BuddyConfig } from '@buddysh/buddy'
43
44const config: BuddyConfig = {
45 packages: {
46 strategy: 'all',
47 rules: [
48 {
49 matchEcosystems: ['npm'],
50 labels: ['javascript'],
51 reviewers: ['platform-team'],
52 },
53 {
54 matchPackages: ['react', 'react-dom', '@types/react*'],
55 labels: ['frontend'],
56 reviewers: ['ui-lead'],
57 assignees: ['ui-lead'],
58 },
59 ],
60 },
61}
662
7Buddy automatically applies contextual labels based on package characteristics, update types, and change scope.
63export default config
64```
865
9### Default Label Categories
66### Effects Accumulate
1067
11#### Update Type Labels
68This is the part worth understanding, because it is what makes narrow rules safe
69to add: **list effects union, they do not override.**
1270
13- `patch-update` - Patch version updates (bug fixes)
14- `minor-update` - Minor version updates (new features)
15- `major-update` - Major version updates (breaking changes)
16- `security-update` - Security-related updates
17- `dependencies` - General dependency label
71A `react` bump in `package.json` matches *both* rules above. It does not take the
72last one and discard the first — it carries everything both rules asked for:
1873
19#### Package Ecosystem Labels
74| | Rule 1 (`npm`) | Rule 2 (`react*`) | Resolved |
75|---|---|---|---|
76| Labels | `javascript` | `frontend` | `javascript`, `frontend` |
77| Reviewers | `platform-team` | `ui-lead` | `platform-team`, `ui-lead` |
78| Assignees | — | `ui-lead` | `ui-lead` |
2079
21- `react-ecosystem` - React and related packages
22- `vue-ecosystem` - Vue.js and related packages
23- `angular-ecosystem` - Angular framework packages
24- `typescript` - TypeScript and type definitions
25- `testing` - Testing frameworks and utilities
26- `build-tools` - Build and bundling tools
27- `dev-dependencies` - Development-only packages
80Combined with the automatic labels, the pull request opens carrying
81`dependencies`, `minor`, `npm`, `react`, `javascript` and `frontend`, assigned to
82`ui-lead`, with review requested from `platform-team` and `ui-lead`. Duplicates
83are collapsed, so a name listed by three rules is requested once.
2884
29#### Scope Labels
85The non-list effects behave the opposite way. `enabled`, `strategy`,
86`groupName`, `autoMerge`, `minimumReleaseAge`, `prPriority` and `autoMigrate`
87are single values, so a later matching rule overrides an earlier one per field —
88which is what lets a broad rule set a default and a narrow one refine it.
3089
31- `single-package` - Updates affecting one package
32- `multi-package` - Updates affecting multiple packages
33- `monorepo-update` - Monorepo workspace updates
34- `breaking-changes` - Updates with breaking changes
90### Matchers
3591
36### Configuration
92All matchers present on one rule must match (AND within a rule). Add rules for
93OR.
3794
38```typescript
39export default {
40 pullRequest: {
41 labels: {
42 // Static labels (always applied)
43 static: ['dependencies', 'automated'],
44
45 // Dynamic labeling rules
46 dynamic: {
47 enabled: true,
48
49 // Update type labeling
50 updateType: {
51 patch: 'patch-update',
52 minor: 'minor-update',
53 major: 'major-update',
54 security: 'security-update'
55 },
56
57 // Package ecosystem detection
58 ecosystems: {
59 react: ['react*', '@types/react*'],
60 vue: ['vue*', '@vue/*'],
61 angular: ['@angular/*'],
62 typescript: ['typescript', '@types/*'],
63 testing: ['jest', 'vitest', '@testing-library/*']
64 },
65
66 // Custom label rules
67 rules: [
68 {
69 condition: 'packages.includes("@types/")',
70 label: 'type-definitions'
71 },
72 {
73 condition: 'packageCount > 5',
74 label: 'large-update'
75 },
76 {
77 condition: 'hasBreakingChanges',
78 label: 'breaking-changes'
79 }
80 ]
81 }
82 }
83 }
84} satisfies BuddyConfig
85```
95| Matcher | Matches on |
96|---|---|
97| `matchPackages` | Package names or globs (`@types/*`) |
98| `matchEcosystems` | `npm`, `composer`, `github-actions`, `docker`, `pkgx`, `zig`, `python`, `rust`, `go`, `ruby` |
99| `matchDepTypes` | `dependencies`, `devDependencies`, `peerDependencies`, … |
100| `matchUpdateTypes` | `major`, `minor`, `patch` |
101| `matchFiles` | Globs on the manifest path, for monorepo directories |
102| `matchCurrentVersion` | Semver range the *installed* version must satisfy |
103| `schedule` | Cron window during which the rule applies |
86104
87### Custom Label Rules
105A rule with no matchers at all applies to everything, and configuration
106validation rejects it on the grounds that it is more often a misspelled matcher
107than an intention — a typo does not disable a rule, it widens it.
88108
89#### Pattern-Based Labeling
109Glob `*` stops at `/`, so it does not match a scoped package: use `**` for
110"every package", or `@scope/*` for one scope.
90111
91112```typescript
92const patternLabeling = {
93 pullRequest: {
94 labels: {
95 patterns: {
96 '@types/*': ['type-definitions', 'typescript'],
97 'eslint*': ['linting', 'code-quality'],
98 'babel*': ['build-tools', 'transpilation'],
99 '*test*': ['testing'],
100 '*security*': ['security']
101 }
102 }
103 }
104}
105```
113rules: [
114 // Repository-wide labels, applied to every update
115 { matchPackages: ['**'], labels: ['dependencies-bot'] },
106116
107#### Conditional Labeling
117 // Per-workspace ownership in a monorepo
118 { matchFiles: ['packages/api/**'], reviewers: ['backend-team'] },
119 { matchFiles: ['packages/web/**'], reviewers: ['frontend-team'] },
108120
109```typescript
110const conditionalLabeling = {
111 pullRequest: {
112 labels: {
113 conditions: [
114 {
115 when: pr => pr.packages.length === 1,
116 apply: ['single-package']
117 },
118 {
119 when: pr => pr.packages.some(p => p.hasBreakingChanges),
120 apply: ['breaking-changes', 'requires-review']
121 },
122 {
123 when: pr => pr.updateType === 'security',
124 apply: ['security', 'high-priority']
125 },
126 {
127 when: pr => pr.packages.every(p => p.isDevDependency),
128 apply: ['dev-only', 'low-risk']
129 }
130 ]
131 }
132 }
133}
134```
135
136## Team Assignment
137
138Intelligent assignment of reviewers and assignees based on package ownership and team structure.
139
140### Reviewer Assignment
141
142#### Global Reviewers
143
144```typescript
145export default {
146 pullRequest: {
147 reviewers: ['tech-lead', 'senior-dev'],
148
149 // GitHub teams, requested alongside individual reviewers
150 teamReviewers: ['platform'],
121 // Type definitions go to whoever maintains the types
122 { matchPackages: ['@types/*'], labels: ['types'], assignees: ['types-owner'] },
151123
152 assignees: ['maintainer']
153 }
154} satisfies BuddyConfig
124 // Majors get a second pair of eyes, whatever else matched
125 { matchUpdateTypes: ['major'], labels: ['breaking-risk'], reviewers: ['tech-lead'] },
126]
155127```
156128
157How many approvals a merge requires is a GitHub branch-protection setting, not
158a Buddy one — Buddy requests reviewers, and the repository decides what
159counts.
129### Grouped Updates
160130
161#### Package-Based Assignment
131When several updates travel in one PR, their resolved effects merge the same
132way: labels, reviewers and assignees union across every update in the group. A
133group containing one `@types/*` bump and one `react` bump carries the labels and
134people from both rules, because the PR genuinely touches both.
162135
163```typescript
164const packageBasedAssignment = {
165 pullRequest: {
166 packageOwners: {
167 'react': ['frontend-team', 'react-expert'],
168 'vue': ['vue-team'],
169 '@types/*': ['typescript-team'],
170 'eslint*': ['code-quality-team'],
171 'jest': ['testing-team'],
172 'webpack': ['build-team'],
173 '@company/*': ['platform-team']
174 },
136`autoMerge` resolves conservatively across a group instead — every update must
137allow it, so one package that must not merge unattended holds back the whole PR
138containing it.
175139
176 // Fallback reviewers
177 fallbackReviewers: ['tech-lead', 'senior-dev']
178 }
179}
180```
140## Repository-Wide Reviewers and Assignees
181141
182#### Team-Based Assignment
183
184```typescript
185const teamBasedAssignment = {
186 pullRequest: {
187 teams: {
188 frontend: {
189 members: ['alice', 'bob', 'charlie'],
190 packages: ['react*', 'vue*', '@types/react*'],
191 requiredReviews: 2
192 },
193 backend: {
194 members: ['david', 'eve'],
195 packages: ['express*', '@types/node*'],
196 requiredReviews: 1
197 },
198 devtools: {
199 members: ['frank', 'grace'],
200 packages: ['eslint*', 'prettier*', 'webpack*'],
201 autoAssign: true
202 }
203 }
204 }
205}
206```
207
208### Assignee Management
209
210#### Automatic Assignment
142Names that should be on every Buddy PR regardless of what changed belong in
143`pullRequest`. All three are plain string arrays.
211144
212145```typescript
213146export default {
214147 pullRequest: {
215 assignees: {
216 // Static assignees
217 static: ['maintainer'],
218
219 // Dynamic assignment rules
220 rules: [
221 {
222 condition: 'updateType === "security"',
223 assignees: ['security-team']
224 },
225 {
226 condition: 'packages.includes("react")',
227 assignees: ['frontend-lead']
228 },
229 {
230 condition: 'packageCount > 10',
231 assignees: ['tech-lead']
232 }
233 ],
234
235 // Assignment limits
236 maxAssignees: 3,
237 requiresAssignee: true
238 }
239 }
148 reviewers: ['tech-lead'],
149 teamReviewers: ['platform'],
150 assignees: ['maintainer'],
151 },
240152} satisfies BuddyConfig
241153```
242154
243## CLI Label Management
244
245Manage labels and assignments via CLI:
155| Option | Type | Description |
156|---|---|---|
157| `reviewers` | `string[]` | GitHub usernames to request review from |
158| `teamReviewers` | `string[]` | GitHub team **slugs**, without the organisation prefix |
159| `assignees` | `string[]` | GitHub usernames to assign |
246160
247```bash
248# List current labels
249buddy labels list
161`reviewers` and `assignees` are unioned with whatever the matching rules
162contributed, so the two mechanisms compose rather than compete — the repository
163default is a floor, not a ceiling. When neither the config nor a rule names
164anybody, Buddy sends no reviewer request at all rather than an empty one, which
165GitHub would read as a deliberate request for nobody.
250166
251# Create custom label
252buddy labels create "custom-label" --color "ff0000" --description "Custom label"
167Team reviewers are requested in the same API call as individual reviewers, so a
168config listing `teamReviewers` and no `reviewers` never sends the request. Name
169at least one individual reviewer alongside the team, or let a rule supply one.
253170
254# Assign reviewers to PR
255buddy assign 123 --reviewers alice,bob --assignees charlie
256
257# Update PR labels
258buddy labels update 123 --add security --remove low-priority
259```
171How many approvals a merge actually requires is a GitHub branch-protection
172setting, not a Buddy one. Buddy requests reviewers; the repository decides what
173counts.
260174
261## Automation Examples
175## Holding a PR Back With a Label
262176
263### Security-First Assignment
177One label has behaviour attached to it. `pullRequest.autoMerge.optOutLabel` —
178`no-auto-merge` by default — suppresses auto-merge on any PR carrying it, checked
179both at the moment Buddy opens the PR and again when `buddy update-check`
180re-evaluates open ones.
264181
265182```typescript
266183export default {
267184 pullRequest: {
268 labels: {
269 rules: [
270 {
271 condition: 'isSecurityUpdate',
272 labels: ['security', 'high-priority', 'auto-merge-approved']
273 }
274 ]
185 autoMerge: {
186 enabled: true,
187 strategy: 'squash',
188 conditions: ['patch-only'],
189 optOutLabel: 'needs-human',
275190 },
276
277 assignees: {
278 rules: [
279 {
280 condition: 'isSecurityUpdate',
281 assignees: ['security-team'],
282 reviewers: ['security-lead', 'tech-lead'],
283 urgency: 'high'
284 }
285 ]
286 }
287 }
191 },
288192} satisfies BuddyConfig
289193```
290194
291### Development Workflow
195Because rule labels are resolved before the PR is opened, a rule can mark a
196package as never-unattended and the PR arrives already held back:
292197
293198```typescript
294export default {
295 pullRequest: {
296 labels: {
297 rules: [
298 {
299 condition: 'isDevDependency && updateType === "patch"',
300 labels: ['dev-only', 'auto-merge', 'low-risk']
301 },
302 {
303 condition: 'isProductionDependency && updateType === "major"',
304 labels: ['production', 'breaking-changes', 'requires-testing']
305 }
306 ]
307 },
308
309 assignees: {
310 rules: [
311 {
312 condition: 'isDevDependency',
313 assignees: ['dev-lead'],
314 reviewers: ['senior-dev']
315 },
316 {
317 condition: 'isProductionDependency',
318 assignees: ['tech-lead'],
319 reviewers: ['tech-lead', 'senior-dev-1', 'senior-dev-2']
320 }
321 ]
322 }
323 }
324} satisfies BuddyConfig
199rules: [
200 { matchPackages: ['@company/auth*'], labels: ['no-auto-merge'] },
201]
325202```
326203
327See [Pull Request Generation](/features/pull-requests) for more details on how labeling and assignment integrate with the overall PR workflow.
204Setting `enabled: false` or a narrower `strategy` on the rule is the stronger
205form of the same intent: the update is never proposed at all rather than proposed
206and held. See [Auto-Merge](/features/auto-merge) for what qualifies in the first
207place.
208
209## Labels Are Configuration, Not Commands
210
211There is no CLI for managing labels or assignees. Buddy resolves them at the
212moment it opens a pull request, so the way to change them is to change
213`buddy.config.ts` and let the next run pick it up.
214
215A rule you add now therefore shows up on the next PR for that group rather than
216on one already open. When a later run finds an existing open Buddy PR for that
217group it refreshes the PR in place, rewriting its labels to the automatically
218derived set and its reviewers and assignees to the repository-wide
219`pullRequest` names. A label added
220by hand on an open PR is therefore not guaranteed to survive the next refresh,
221and neither is one a rule contributed when the PR was opened. Close the PR and
222let the next run open it again when you need the current rules applied from
223scratch.
224
225See [Package Rules](/config#package-rules) for the full effect list and
226[Pull Request Generation](/features/pull-requests) for how labelling fits into
227the rest of the PR workflow.
docs/features/merge-gates.mdmodified+2-2
Changes to docs/features/merge-gates.md
@@ -38,7 +38,7 @@ hero:
3838 ✔ tests-updated behaviour change covered
3939
4040 error · 1 failing gate
41 check run published: buddy/gate
41 check run published: buddy/gates
4242 - file: "buddy.config.ts"
4343 lang: "ts"
4444 content: |
@@ -113,7 +113,7 @@ jobs:
113113 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
114114```
115115
116Then mark `buddy/gate` as a required check in your branch protection rules. That is the whole enforcement story: GitHub blocks the merge, Buddy just reports the truth.
116Then mark `buddy/gates` as a required check in your branch protection rules. That is the whole enforcement story: GitHub blocks the merge, Buddy just reports the truth.
117117
118118## Deterministic first {#deterministic}
119119
docs/features/package-management.mdmodified+65-27
Changes to docs/features/package-management.md
@@ -108,7 +108,7 @@ jobs:
108108 run: bun test
109109```
110110
111All dependency files are parsed using the `ts-pkgx` library to ensure compatibility with the pkgx registry ecosystem. GitHub Actions are detected by parsing `uses:` statements in workflow files and checking for updates via the GitHub releases API.
111All dependency files are parsed using the `ts-pantry` library to ensure compatibility with the pkgx registry ecosystem. GitHub Actions are detected by parsing `uses:` statements in workflow files and checking for updates via the GitHub releases API.
112112
113113### Project Structure Detection
114114
@@ -297,28 +297,45 @@ Platform requirements are automatically excluded from updates:
297297
298298Control which packages are managed by buddy.
299299
300### Ignore Patterns
300### Ignore List
301301
302302```typescript
303303export default {
304304 packages: {
305 // Global ignore list
305 // Global ignore list — exact package names
306306 ignore: [
307307 '@types/node', // Keep Node types stable
308308 'react', // Manual React updates
309 'vue', // Manual Vue updates
310 '@internal/*', // Internal packages
311 '@types/*', // All type definitions
312 'eslint-*', // All ESLint packages
313 'babel-*' // All Babel packages
309 'vue' // Manual Vue updates
314310 ]
315311 }
316312} satisfies BuddyConfig
317313```
318314
319`ignore` entries are matched as globs against the package name, so one list
320covers both exact names and whole families. To exclude by file path instead,
321use `ignorePaths`.
315`ignore` entries are compared by **exact name equality**. A glob such as
316`@types/*` matches no package at all, so it silently ignores nothing rather
317than failing loudly.
318
319### Ignore Patterns
320
321For whole families, use a rule: `matchPackages` accepts globs, and
322`enabled: false` drops every update it matches.
323
324```typescript
325export default {
326 packages: {
327 rules: [
328 { matchPackages: ['@internal/*'], enabled: false },
329 { matchPackages: ['@types/*'], enabled: false },
330 { matchPackages: ['eslint-*', 'babel-*'], enabled: false }
331 ]
332 }
333} satisfies BuddyConfig
334```
335
336The two lists behave differently on purpose, and the difference is easy to trip
337over: `ignore` is exact names, while the adjacent `ignorePaths` **does** take
338globs, because it matches file paths rather than package names.
322339
323340### Include/Exclude by Scope
324341
@@ -360,9 +377,8 @@ export default {
360377 },
361378 {
362379 name: 'Build Tools',
363 packages: ['webpack', 'webpack-cli', 'webpack-dev-server'],
364 strategy: 'major',
365 reviewers: ['build-team']
380 patterns: ['webpack', 'webpack-cli', 'webpack-dev-server'],
381 strategy: 'major'
366382 }
367383 ]
368384 }
@@ -377,18 +393,17 @@ const patternGroupsConfig = {
377393 groups: [
378394 {
379395 name: 'Type Definitions',
380 pattern: '@types/*',
381 strategy: 'minor',
382 autoMerge: true
396 patterns: ['@types/*'],
397 strategy: 'minor'
383398 },
384399 {
385400 name: 'ESLint Ecosystem',
386 pattern: 'eslint*',
401 patterns: ['eslint*'],
387402 strategy: 'patch'
388403 },
389404 {
390405 name: 'Babel Plugins',
391 pattern: 'babel-*',
406 patterns: ['babel-*'],
392407 strategy: 'minor'
393408 }
394409 ]
@@ -638,26 +653,49 @@ All package management features are available via CLI.
638653buddy check react vue typescript
639654
640655# Get package information
641buddy info @types/node --detailed
656buddy info @types/node
657
658# Machine-readable package information
659buddy info @types/node --json
642660
643661# Search packages
644662buddy search "ui component" --limit 10
645663
646664# Analyze dependencies
647buddy deps react --depth 2
665buddy deps react
666
667# Include dev and peer dependencies
668buddy deps react --all
648669```
649670
650671### Batch Operations
651672
673`buddy update` runs over everything the scan found; it has no package or group
674filter of its own. Narrow it with a strategy, an ignore list, or a preview run:
675
652676```bash
653# Update multiple packages
654buddy update --packages react,vue,typescript
677# Preview the pull requests without opening them
678buddy update --dry-run
679
680# Restrict this run to patch updates
681buddy update --strategy patch
682
683# Skip named packages for this run
684buddy update --ignore react,vue
685```
655686
656# Update by pattern
657buddy update --pattern "@types/_"
687To scope a run to a group or a pattern, express it in config as a rule and let
688`buddy update` honour it:
658689
659# Update by group
660buddy update --group "React Ecosystem"
690```typescript
691export default {
692 packages: {
693 rules: [
694 { matchPackages: ['@types/*'], groupName: 'Type Definitions' },
695 { matchEcosystems: ['docker'], enabled: false }
696 ]
697 }
698} satisfies BuddyConfig
661699```
662700
663701See [CLI Package Commands](/cli/package) for complete CLI reference.
docs/features/rebase.mdmodified+46-27
Changes to docs/features/rebase.md
@@ -27,7 +27,7 @@ Every Buddy pull request includes an interactive checkbox:
2727
2828### 2. Automatic Detection
2929
30A GitHub Actions workflow (`.github/workflows/buddy-check.yml`) runs every minute and:
30Ticking the box edits the pull request body, and that edit is the trigger. The unified workflow (`.github/workflows/buddy.yml`) listens on `pull_request: [edited]` — and on `issues: [edited]` for the same checkboxes on the dashboard — so nothing is polling and nothing waits for a schedule. The run then:
3131
32321. Scans all open pull requests
33332. Identifies Buddy PRs with checked rebase boxes
@@ -52,7 +52,7 @@ During rebase, Buddy:
52521. **Open any Buddy PR**
53532. **Scroll to the bottom** of the PR description
54543. **Check the rebase checkbox**: `- [x] If you want to update/retry this PR, check this box`
554. **Wait for automation**: The workflow will detect and process the request within 1 minute
554. **Wait for automation**: The edit fires the workflow straight away — no scheduled tick to wait for
56565. **Review updates**: PR will be refreshed with latest dependency versions
5757
5858### Manual Rebase via CLI
@@ -74,9 +74,10 @@ buddy update-check --dry-run --verbose
7474### Manual Trigger via GitHub Actions
7575
76761. Go to **Actions** tab in your repository
772. Select **"Buddy Check"** workflow
772. Select the **"Buddy"** workflow
78783. Click **"Run workflow"**
79794. Choose options:
80 - **Which job to run**: pick `check` to process rebase requests only
8081 - **Dry run**: Preview changes without applying them
81825. Click **"Run workflow"** to execute
8283
@@ -84,19 +85,39 @@ buddy update-check --dry-run --verbose
8485
8586### Workflow Setup
8687
87The rebase workflow is automatically created when you run `buddy setup`. It includes:
88The rebase handling lives in the unified workflow `buddy setup` writes to `.github/workflows/buddy.yml`. The parts that matter for rebasing:
8889
8990```yaml
90name: Buddy Check
91name: Buddy
9192
9293on:
93 schedule:
94 # Ticking the checkbox edits the PR body, which fires this event
95 pull_request:
96 types: [edited, opened, ready_for_review, synchronize, closed]
97
98 # The dashboard's checkboxes are the same request, made on an issue
99 issues:
100 types: [edited, opened]
94101
95 - cron: '*/1 * * * *' # Every minute
102 schedule:
103 - cron: '0 */2 * * *' # Dependency updates
104 - cron: '15 */2 * * *' # Dashboard refresh
105 - cron: '0 4 * * *' # Daily cleanup of orphaned branches and obsolete PRs
106 - cron: '0 9 * * 1' # Weekly dependency-health report
96107
97 workflow*dispatch: # Manual trigger
108 workflow_dispatch: # Manual trigger
98109 inputs:
99 dry*run:
110 job:
111 description: Which job to run
112 required: false
113 default: all
114 type: choice
115 options:
116 - all
117 - check
118 - update
119 - dashboard
120 dry_run:
100121 description: Dry run (preview only)
101122 required: false
102123 default: false
@@ -107,8 +128,12 @@ permissions:
107128 pull-requests: write
108129 issues: write
109130 actions: write # Required for workflow file updates
131 checks: read
132 statuses: read
110133```
111134
135None of those schedules drives rebase detection — the edit event covers that. They exist for the periodic jobs: dependency updates, the dashboard refresh, cleanup and the weekly report.
136
112137### Token Configuration
113138
114139#### Option 1: Personal Access Token (Full Features)
@@ -195,13 +220,9 @@ During rebase, Buddy updates:
195220
196221**Error**: `No buddy PRs found`
197222
198**Cause**: Workflow looks for PRs created by:
199
200- Branch names starting with `buddy/`
201- Author `github-actions[bot]`
202- Author containing `buddy`
223**Cause**: `buddy update-check` only considers open pull requests whose head branch starts with `buddy/`. The author is never inspected. The workflow adds one condition of its own on the edit trigger: an edit made by a bot account is ignored, so Buddy's own untick cannot re-trigger the run.
203224
204**Solution**: Ensure PRs were created by Buddy
225**Solution**: Ensure the PR was created by Buddy — a hand-made PR on a branch outside `buddy/` is never picked up — and tick the box from your own account rather than through another bot
205226
206227#### 4. Rebase Not Triggered
207228
@@ -213,22 +234,20 @@ During rebase, Buddy updates:
213234
214235## Advanced Usage
215236
216### Custom Rebase Logic
237### Rebasing One PR Directly
217238
218You can customize the rebase behavior by modifying the workflow:
239`update-check` sweeps every open Buddy PR for ticked boxes. To act on a single PR without touching the checkbox at all, address it by number:
219240
220```yaml
221# Custom rebase frequency
222on:
223 schedule:
224
225 - cron: '*/5 * * * *' # Every 5 minutes instead of 1
241```bash
242# Recreate PR #17 with the latest versions
243buddy rebase 17
226244
227# Custom PR detection
228env:
229 CUSTOM_AUTHOR_FILTER: 'my-custom-bot'
245# Rebase even when the PR already looks up to date
246buddy rebase 17 --force
230247```
231248
249A PR that is already current is skipped unless you pass `--force`, so this is safe to run from a script or from your own workflow step.
250
232251### Integration with Other Tools
233252
234253The rebase functionality works seamlessly with:
@@ -265,7 +284,7 @@ Track rebase operations via:
265284
266285### Performance Considerations
267286
268- **Frequency**: Every minute is optimal for responsiveness
287- **Frequency**: Detection costs nothing while idle — the run starts on the edit, not on a clock
269288- **Rate limits**: GitHub API rate limits apply
270289- **Resource usage**: Minimal overhead per execution
271290- **Parallel execution**: Multiple rebase requests handled sequentially
docs/features/scanning.mdmodified+17-4
Changes to docs/features/scanning.md
@@ -15,7 +15,7 @@ Buddy uses multiple scanning approaches depending on the file type:
1515
1616### Dependency File Scanning
1717
18- **pkgx Integration**: Uses `ts-pkgx` library for parsing dependency files
18- **pkgx Integration**: Uses `ts-pantry` library for parsing dependency files
1919- **Registry Compatibility**: Full compatibility with pkgx registry ecosystem
2020- **Format Support**: Handles multiple YAML formats (`.yaml`, `.yml`)
2121- **Launchpad Support**: Compatible with Launchpad dependency files
@@ -67,20 +67,33 @@ export default {
6767
6868#### Ignore Packages
6969
70Skip specific packages from scanning:
70Skip specific packages from scanning. Entries are compared by exact name — no
71globs:
7172
7273```typescript
7374export default {
7475 packages: {
7576 ignore: [
76 '@types/node', // Specific package
77 '@types/*', // Glob patterns
77 '@types/node', // Exact package name
7878 'react', // Dependencies you want to control manually
7979 ]
8080 }
8181}
8282```
8383
84To skip a whole family, use a rule with `matchPackages`, which does take
85patterns:
86
87```typescript
88export default {
89 packages: {
90 rules: [
91 { matchPackages: ['@types/*'], enabled: false }
92 ]
93 }
94}
95```
96
8497#### Pin Specific Versions
8598
8699Lock packages to specific versions:
docs/features/update-strategies.mdmodified+43-23
Changes to docs/features/update-strategies.md
@@ -58,9 +58,10 @@ export default {
5858- `typescript@5.1.0` → `typescript@5.2.0` ✅ (minor)
5959- `typescript@5.1.0` → `typescript@6.0.0` ❌ (major)
6060
61### `major` - Latest Stable
61### `major` - Breaking Changes Only
6262
63Updates to the latest stable version, including major versions with breaking changes.
63Updates major versions and nothing else. Minor and patch bumps are left for a
64run configured to take them.
6465
6566```typescript
6667// Example: 1.2.3 → 2.0.0
@@ -73,18 +74,20 @@ export default {
7374
7475**When to use:**
7576
76- Development environments
77- Regular maintenance windows
77- A dedicated maintenance window for breaking changes
78- Keeping major upgrades in their own pull requests
7879- Teams comfortable with handling breaking changes
7980
8081**Example updates:**
8182
82- `vue@2.7.0` → `vue@2.7.16` ✅ (patch)
8383- `vue@2.7.0` → `vue@3.4.0` ✅ (major)
84- `vue@2.7.0` → `vue@2.8.0` ❌ (minor)
85- `vue@2.7.0` → `vue@2.7.16` ❌ (patch)
8486
85### `all` - Most Aggressive
87### `all` - Everything
8688
87Updates to the absolute latest version available, including pre-releases when no stable version exists.
89Updates everything available, regardless of semver impact — major, minor and
90patch together. This is the default.
8891
8992```typescript
9093export default {
@@ -98,12 +101,26 @@ export default {
98101
99102- Experimental projects
100103- Early adoption teams
101- Testing latest features
104- Staying current across the whole dependency tree
102105
103106**Example updates:**
104107
105- `next@14.0.0` → `next@15.0.0-rc.1` ✅ (pre-release)
106- `react@18.2.0` → `react@19.0.0-beta.1` ✅ (beta)
108- `react@18.2.0` → `react@18.2.1` ✅ (patch)
109- `react@18.2.0` → `react@18.3.0` ✅ (minor)
110- `react@18.2.0` → `react@19.0.0` ✅ (major)
111
112Pre-release versions are a separate switch, not part of the strategy: set
113`packages.includePrerelease` if you want alphas, betas and release candidates
114considered.
115
116### At a Glance
117
118| Strategy | Updates it proposes |
119| --- | --- |
120| `all` | Everything, regardless of semver impact |
121| `major` | Major versions only |
122| `minor` | Minor and patch |
123| `patch` | Patch only |
107124
108125## Strategy Configuration
109126
@@ -137,11 +154,11 @@ export default {
137154 {
138155 name: 'Development Tools',
139156 patterns: ['eslint', 'prettier', 'typescript'],
140 strategy: 'major' // More aggressive for dev tools
157 strategy: 'major' // Dev-tool majors, batched on their own
141158 },
142159 {
143160 name: 'Testing Libraries',
144 packages: ['jest', 'vitest', '@testing-library/*'],
161 patterns: ['jest', 'vitest', '@testing-library/*'],
145162 strategy: 'minor'
146163 }
147164 ]
@@ -159,7 +176,7 @@ export default {
159176 strategy: 'minor',
160177 rules: [
161178 { matchPackages: ['react'], strategy: 'patch' }, // Keep React very stable
162 { matchPackages: ['typescript'], strategy: 'major' }, // Always latest TypeScript
179 { matchPackages: ['typescript'], strategy: 'major' }, // TypeScript majors only
163180 { matchPackages: ['@types/*'], strategy: 'all' } // Types can be aggressive
164181 ]
165182 }
@@ -228,7 +245,7 @@ const week1Config = { strategy: 'patch' }
228245// Week 2: Add minor updates
229246const week2Config = { strategy: 'minor' }
230247
231// Week 3: Add major updates for dev dependencies
248// Week 3: minor everywhere, plus a group that takes dev-tool majors
232249const week3Config = {
233250 strategy: 'minor',
234251 groups: [
@@ -253,7 +270,7 @@ export default {
253270 packages: {
254271 strategy: isProduction
255272 ? (isCorporate ? 'patch' : 'minor')
256 : 'major'
273 : 'all'
257274 }
258275} satisfies BuddyConfig
259276```
@@ -279,8 +296,8 @@ const config = {
279296 },
280297 {
281298 name: 'Build Tools',
282 packages: ['vite', 'rollup', 'esbuild'],
283 strategy: 'major' // Build tools are less breaking
299 patterns: ['vite', 'rollup', 'esbuild'],
300 strategy: 'major' // Build tools get their majors in a PR of their own
284301 }
285302 ]
286303 }
@@ -295,13 +312,16 @@ Override configuration strategies via CLI:
295312# Force patch strategy regardless of config
296313buddy update --strategy patch
297314
298# Use major strategy for specific packages
299buddy update --strategy major --packages react,vue
315# Take the major bumps on their own, in a preview run first
316buddy update --strategy major --dry-run
300317
301# Mixed strategies
302buddy update --patch typescript --minor react --major eslint
318# Take the majors, but leave two packages behind
319buddy update --strategy major --ignore react,vue
303320```
304321
322`--strategy` is a whole-run switch. Per-package strategies are config only —
323use `rules` with `matchPackages`, as above.
324
305325## Monitoring Strategy Effectiveness
306326
307327Track how strategies perform:
@@ -359,7 +379,7 @@ export default {
359379 {
360380 name: 'Development Tools',
361381 patterns: ['typescript', 'webpack', 'vite'],
362 strategy: 'major'
382 strategy: 'all'
363383 }
364384 ]
365385 }
@@ -371,7 +391,7 @@ export default {
371391```typescript
372392export default {
373393 packages: {
374 strategy: 'major',
394 strategy: 'all',
375395 groups: [
376396 {
377397 name: 'Database & Infrastructure',
docs/guide/configuration.mdmodified+10-10
Changes to docs/guide/configuration.md
@@ -50,8 +50,8 @@ Configure how Buddy interacts with your repository:
5050
5151```typescript
5252repository: {
53 // Git provider
54 provider: 'github', // 'github' | 'gitlab' | 'bitbucket'
53 // Git provider — only 'github' is implemented today
54 provider: 'github',
5555
5656 // Repository owner (organization or user)
5757 owner: 'stacksjs',
@@ -203,7 +203,7 @@ Choose from predefined workflow configurations:
203203### Standard (Default)
204204
205205```bash
206buddy setup --preset standard
206buddy setup --non-interactive --preset standard
207207```
208208
209209- Dashboard updates 3x/week
@@ -212,7 +212,7 @@ buddy setup --preset standard
212212### High Frequency
213213
214214```bash
215buddy setup --preset high-frequency
215buddy setup --non-interactive --preset high-frequency
216216```
217217
218218- Updates multiple times per day
@@ -221,7 +221,7 @@ buddy setup --preset high-frequency
221221### Security Focused
222222
223223```bash
224buddy setup --preset security
224buddy setup --non-interactive --preset security
225225```
226226
227227- Frequent security patches
@@ -230,7 +230,7 @@ buddy setup --preset security
230230### Minimal
231231
232232```bash
233buddy setup --preset minimal
233buddy setup --non-interactive --preset minimal
234234```
235235
236236- Weekly checks only
@@ -239,11 +239,11 @@ buddy setup --preset minimal
239239### Testing
240240
241241```bash
242buddy setup --preset testing
242buddy setup --non-interactive --preset testing
243243```
244244
245- Every 5 minutes
246- Dry run by default
245- Manual dashboard trigger, frequent update checks
246- Patch updates only, no auto-merge
247247- For development/testing
248248
249249## Migration from Other Tools
@@ -313,7 +313,7 @@ Create custom integrations in `.buddy/plugins/`:
313313 "enabled": true,
314314 "triggers": [
315315 { "event": "setup_complete" },
316 { "event": "pr_created" }
316 { "event": "validation_error" }
317317 ],
318318 "configuration": {
319319 "webhook_url": "https://your-webhook.com/notify"
docs/guide/getting-started.mdmodified+14-21
Changes to docs/guide/getting-started.md
@@ -105,8 +105,8 @@ buddy update-check --verbose
105105|----------|-------------|
106106| `all` | All updates regardless of semver impact |
107107| `major` | Only major version updates |
108| `minor` | Major and minor updates (no patch-only) |
109| `patch` | All updates (most conservative) |
108| `minor` | Minor and patch updates (no majors) |
109| `patch` | Only patch updates (most conservative) |
110110
111111## Supported Ecosystems
112112
@@ -134,31 +134,24 @@ Buddy automatically detects and updates:
134134
135135## Generated Workflows
136136
137After setup, Buddy creates three workflows:
137After setup, Buddy creates two workflows:
138138
139### `buddy-dashboard.yml`
139### `buddy.yml`
140140
141Maintains the dependency dashboard issue:
141One unified workflow covering checks, updates and the dashboard:
142142
143- Runs Monday, Wednesday, Friday at 9 AM UTC
144- Shows all open PRs and detected dependencies
145- Interactive checkbox controls
143- Scans for updates every 2 hours, refreshing the dashboard 15 minutes later
144- Rebase and dashboard checkboxes are event-driven, so ticking a box triggers a run immediately
145- Runs a daily cleanup pass at 4 AM UTC and a weekly dependency report Monday at 9 AM UTC
146- Answers `@buddy` comments and supports manual triggers
146147
147### `buddy-check.yml`
148### `buddy-security.yml`
148149
149Handles PR rebase requests:
150Audits your GitHub Actions workflows:
150151
151- Runs every minute
152- Detects checked rebase boxes
153- Updates PR content automatically
154
155### `buddy-update.yml`
156
157Creates dependency update PRs:
158
159- Schedule varies by preset
152- Runs on pushes and PRs that touch `.github/workflows/**`
153- Weekly drift check Monday at 6 AM UTC
160154- Supports manual triggers
161- Configurable update strategy
162155
163156## CLI Reference
164157
@@ -181,7 +174,7 @@ buddy update-check # Process rebase requests
181174buddy dashboard # Update dashboard issue
182175
183176# Help
184buddy help
177buddy --help
185178buddy --version
186179```
187180
docs/guide/pr-generation.mdmodified+27-16
Changes to docs/guide/pr-generation.md
@@ -64,10 +64,14 @@ pullRequest: {
6464| Variable | Description | Example |
6565|----------|-------------|---------|
6666| `{title}` | Generated title | "update typescript to 5.8.3" |
67| `{package}` | Package name | "typescript" |
68| `{from}` | Current version | "5.8.2" |
69| `{to}` | New version | "5.8.3" |
70| `{type}` | Update type | "patch" |
67| `{group}` | Update group name | "Non-Major Updates" |
68| `{packages}` | Comma-separated package names | "typescript, vitest" |
69| `{count}` | Number of packages in the PR | "2" |
70| `{update_type}` | Highest semver impact in the group | "patch" |
71| `{strategy}` | Configured update strategy | "minor" |
72
73Unknown tokens are left in place rather than blanked, so a typo shows up in the
74title instead of silently disappearing.
7175
7276### Examples
7377
@@ -76,12 +80,12 @@ pullRequest: {
7680titleFormat: 'chore(deps): {title}'
7781// Result: "chore(deps): update typescript to 5.8.3"
7882
79// Simple style
80titleFormat: 'Update {package} to {to}'
81// Result: "Update typescript to 5.8.3"
83// Group style
84titleFormat: 'Update {group} ({count} packages)'
85// Result: "Update Non-Major Updates (2 packages)"
8286
83// With type
84titleFormat: '[{type}] {title}'
87// With update type
88titleFormat: '[{update_type}] {title}'
8589// Result: "[patch] update typescript to 5.8.3"
8690```
8791
@@ -111,11 +115,14 @@ Buddy automatically adds contextual labels:
111115
112116| Label | Condition |
113117|-------|-----------|
114| `major-update` | Major version change |
115| `minor-update` | Minor version change |
116| `patch-update` | Patch version change |
117| `security` | Security vulnerability fix |
118| `dependencies` | Always applied |
119| `major` | Major version change |
120| `minor` | Minor version change |
121| `patch` | Patch version change |
122| `security` | Resolves a published advisory |
118123| `npm` | npm package update |
124| `composer` | Composer package update |
125| `zig` | Zig package update |
119126| `github-actions` | Workflow update |
120127
121128## Reviewers and Assignees
@@ -183,10 +190,14 @@ pullRequest: {
183190
184191| Condition | Description |
185192|-----------|-------------|
186| `patch-only` | Only patch updates |
187| `minor-and-patch` | Minor and patch updates |
193| `patch-only` | Every update in the PR is a patch |
194| `minor-only` | Every update is minor or patch |
195| `security-only` | The PR resolves a security advisory |
188196| `all` | All updates (use cautiously) |
189197
198A PR qualifies when any listed condition accepts it. An empty or missing list
199means nothing auto-merges.
200
190201## Rebase Feature
191202
192203Every PR includes a rebase checkbox:
@@ -202,7 +213,7 @@ Every PR includes a rebase checkbox:
202213### How It Works
203214
2042151. Check the box in the PR description
2052. `buddy-check.yml` workflow detects checked boxes
2162. Editing the PR body triggers the `buddy.yml` workflow, which detects checked boxes
2062173. PR is automatically updated with latest versions
2072184. Checkbox is unchecked after successful update
208219
docs/index.mdmodified+4-5
Changes to docs/index.md
@@ -47,11 +47,9 @@ hero:
4747 @buddy review new changes since last time
4848 @buddy full-review re-read the whole diff
4949 @buddy summary a summary, no inline notes
50 @buddy resolve resolve the threads it opened
5150 @buddy pause stop reviewing this PR
5251 @buddy resume start again
5352 @buddy fix-ci diagnose the failing checks
54 @buddy plan turn an issue into a plan
5553 @buddy rebase rebase a dependency update
5654 @buddy merge re-check auto-merge now
5755 @buddy remember ... keep a note for future runs
@@ -92,7 +90,7 @@ features:
9290 details: "Inline findings anchored to the lines you actually changed, each with the failure it causes rather than a style opinion. Buddy remembers what it already said, so a second push gets new findings — not the same ones again."
9391 - title: "Talks back in the thread"
9492 icon: "💬"
95 details: "Mention @buddy to re-review, summarise, resolve its own threads, pause on a noisy PR, or just ask a question about the diff."
93 details: "Mention @buddy to re-review, summarise, pause on a noisy PR, or just ask a question about the diff."
9694 - title: "Works without an API key"
9795 icon: "🦴"
9896 details: "buddy review --light runs secret scanning, actionlint, shellcheck, hadolint and syntax checks with no model and no network. Fast enough for a pre-commit hook."
@@ -104,7 +102,7 @@ features:
104102 details: "buddy fix-ci reads a failing workflow run, classifies the failure, and opens the repair when the fix is unambiguous."
105103 - title: "Also minds the dependencies"
106104 icon: "📦"
107 details: "The whole Renovate/Dependabot job — scanning, grouping, changelogs, a pinned dashboard, auto-merge — across npm, Composer, Docker, Actions, Go, Rust, Python and Ruby."
105 details: "The whole Renovate/Dependabot job — scanning, grouping, changelogs, a pinned dashboard, auto-merge — across npm, Composer, Docker, Actions, pkgx, Zig, Go, Rust, Python and Ruby."
108106 - title: "Your CI, your keys, your model"
109107 icon: "🏠"
110108 span: 2
@@ -191,6 +189,7 @@ Underneath sits the release notes for every version in the range, a compare link
191189| pkgx / Launchpad | `deps.yaml`, `dependencies.yaml`, `pkgx.yaml` | `pantry.lock` |
192190| GitHub Actions | `.github/workflows/*.yml` | — |
193191| Docker | `Dockerfile` | — |
192| Zig | `build.zig.zon` | — |
194193| Go, Rust, Python, Ruby | `go.mod`, `Cargo.toml`, `pyproject.toml`, `Gemfile` | `go.sum`, `Cargo.lock`, `poetry.lock`, `Gemfile.lock` |
195194
196195More in [pull request generation](/features/pull-requests), [the dashboard](/features/dependency-dashboard) and [ecosystems](/advanced/ecosystems).
@@ -204,7 +203,7 @@ More in [pull request generation](/features/pull-requests), [the dashboard](/fea
204203| Runs on | Your CI, your keys | Hosted app | Hosted or self-hosted | GitHub-hosted |
205204| Works with no API key | Analyzers only | — | n/a | n/a |
206205| Local pre-push review | Yes | — | — | — |
207| Config | TypeScript, JSON or YAML | YAML | JSON / JS | YAML |
206| Config | TypeScript, JavaScript or JSON | YAML | JSON / JS | YAML |
208207| Migration in | From Renovate and Dependabot | — | — | — |
209208
210209The full matrix — including Greptile, Qodo Merge, Graphite, Sourcery and Snyk —
docs/install.mdmodified+48-27
Changes to docs/install.md
@@ -17,9 +17,9 @@ npm i -g @buddysh/buddy
1717```
1818
1919```sh [bun]
20bun install --dev buddy
20bun install --dev @buddysh/buddy
2121# bun add --dev @buddysh/buddy
22# bun i -d buddy
22# bun i -d @buddysh/buddy
2323
2424# or, install globally via
2525bun add --global @buddysh/buddy
@@ -35,10 +35,10 @@ pnpm add --global @buddysh/buddy
3535
3636```sh [yarn]
3737yarn add --dev @buddysh/buddy
38# yarn i -d buddy
38# yarn i -d @buddysh/buddy
3939
4040# or, install globally via
41yarn global add buddy
41yarn global add @buddysh/buddy
4242```
4343
4444```sh [brew]
@@ -90,61 +90,82 @@ Choose the binary that matches your platform and architecture:
9090::: code-group
9191
9292```sh [macOS (arm64)]
93# Download the binary
94curl -L https://github.com/stacksjs/buddy/releases/download/v0.9.1/buddy-darwin-arm64 -o buddy
93# Download the archive
94curl -L https://github.com/stacksjs/buddy/releases/latest/download/buddy-darwin-arm64.zip -o buddy-darwin-arm64.zip
95
96# Unpack it
97unzip buddy-darwin-arm64.zip
9598
9699# Make it executable
97chmod +x buddy
100chmod +x buddy-darwin-arm64
98101
99102# Move it to your PATH
100mv buddy /usr/local/bin/buddy
103mv buddy-darwin-arm64 /usr/local/bin/buddy
101104```
102105
103106```sh [macOS (x64)]
104# Download the binary
105curl -L https://github.com/stacksjs/buddy/releases/download/v0.9.1/buddy-darwin-x64 -o buddy
107# Download the archive
108curl -L https://github.com/stacksjs/buddy/releases/latest/download/buddy-darwin-x64.zip -o buddy-darwin-x64.zip
109
110# Unpack it
111unzip buddy-darwin-x64.zip
106112
107113# Make it executable
108chmod +x buddy
114chmod +x buddy-darwin-x64
109115
110116# Move it to your PATH
111mv buddy /usr/local/bin/buddy
117mv buddy-darwin-x64 /usr/local/bin/buddy
112118```
113119
114120```sh [Linux (arm64)]
115# Download the binary
116curl -L https://github.com/stacksjs/buddy/releases/download/v0.9.1/buddy-linux-arm64 -o buddy
121# Download the archive
122curl -L https://github.com/stacksjs/buddy/releases/latest/download/buddy-linux-arm64.zip -o buddy-linux-arm64.zip
123
124# Unpack it
125unzip buddy-linux-arm64.zip
117126
118127# Make it executable
119chmod +x buddy
128chmod +x buddy-linux-arm64
120129
121130# Move it to your PATH
122mv buddy /usr/local/bin/buddy
131mv buddy-linux-arm64 /usr/local/bin/buddy
123132```
124133
125134```sh [Linux (x64)]
126# Download the binary
127curl -L https://github.com/stacksjs/buddy/releases/download/v0.9.1/buddy-linux-x64 -o buddy
135# Download the archive
136curl -L https://github.com/stacksjs/buddy/releases/latest/download/buddy-linux-x64.zip -o buddy-linux-x64.zip
137
138# Unpack it
139unzip buddy-linux-x64.zip
128140
129141# Make it executable
130chmod +x buddy
142chmod +x buddy-linux-x64
131143
132144# Move it to your PATH
133mv buddy /usr/local/bin/buddy
145mv buddy-linux-x64 /usr/local/bin/buddy
134146```
135147
136148```sh [Windows (x64)]
137# Download the binary
138curl -L https://github.com/stacksjs/buddy/releases/download/v0.9.1/buddy-windows-x64.exe -o buddy.exe
149# Download the archive
150curl -L https://github.com/stacksjs/buddy/releases/latest/download/buddy-windows-x64.zip -o buddy-windows-x64.zip
151
152# Unpack it
153tar -xf buddy-windows-x64.zip
139154
140155# Move it to your PATH (adjust the path as needed)
141move buddy.exe C:\Windows\System32\buddy.exe
156move buddy-windows-x64.exe C:\Windows\System32\buddy.exe
142157```
143158
144159:::
145160
146161::: tip
147You can also find the `buddy` binaries in GitHub [releases](https://github.com/stacksjs/buddy/releases).
162You can also find the `buddy` archives in GitHub [releases](https://github.com/stacksjs/buddy/releases). Every release publishes a `checksums.txt` alongside them, so you can verify a download before unpacking it:
163
164```sh
165curl -L https://github.com/stacksjs/buddy/releases/latest/download/checksums.txt -o checksums.txt
166shasum -a 256 -c checksums.txt --ignore-missing
167```
168
148169:::
149170
150171## GitHub Setup
@@ -216,8 +237,8 @@ buddy --version
216237# Test GitHub authentication
217238buddy scan --verbose
218239
219# Generate sample configuration
220buddy init
240# Diagnose credentials, git state and analyzer tooling
241buddy doctor
221242```
222243
223244## IDE Integration
@@ -250,7 +271,7 @@ COPY package.json bun.lockb ./
250271RUN bun install
251272
252273COPY . .
253RUN bun install -g buddy
274RUN bun install -g @buddysh/buddy
254275
255276CMD ["buddy", "scan"]
256277```
docs/intro.mdmodified+14-13
Changes to docs/intro.md
@@ -16,7 +16,7 @@ Neither half depends on the other. Run the reviewer alone, run the updater alone
1616
1717- **�� Inline Findings** - Anchored to changed lines, stating the failure rather than a preference
1818- **♻️ Incremental** - A second push gets new findings, not the ones you already read
19- **�� Conversational** - `@buddy review`, `full-review`, `summary`, `resolve`, `pause`, `resume`, `plan`, `remember`, or a plain question
19- **�� Conversational** - `@buddy review`, `full-review`, `summary`, `pause`, `resume`, `ignore`, `rebase`, `merge`, `fix-ci`, `remember`, or a plain question
2020- **�� Local Review** - `buddy review` reads the working tree, so problems surface before the PR exists
2121- **�� No Key Required** - `--light` runs secret scanning, actionlint, shellcheck, hadolint, markdownlint and syntax checks offline
2222- **�� Merge Gates** - Title format, description quality, linked issue and dependency policy, published as a check run
@@ -26,7 +26,7 @@ Neither half depends on the other. Run the reviewer alone, run the updater alone
2626
2727## Dependency Features
2828
29- **�� Smart Scanning** - Lightning-fast dependency detection using Bun, ts-pkgx, and GitHub API
29- **�� Smart Scanning** - Lightning-fast dependency detection using Bun, ts-pantry, and GitHub API
3030- **�� Automated PRs** - Professional pull requests with three separate dependency tables
3131- **�� Multi-Format Support** - Handles package.json, pkgx, Launchpad dependency files, and GitHub Actions
3232- **��️ Dynamic Labeling** - Contextual labels based on update type and package ecosystem
@@ -96,15 +96,14 @@ Choose from carefully crafted presets:
9696
9797#### 📝 Step 5: Configuration Generation
9898
99- Creates `buddy.config.json` with your repository settings
99- Creates `buddy.config.ts` with your repository settings
100100- Includes sensible defaults and customization options
101101
102102**�� Step 6: Workflow Generation**
103Generates three core GitHub Actions workflows:
103Generates two GitHub Actions workflows:
104104
105- `buddy-dashboard.yml` - Dependency Dashboard Management
106- `buddy-check.yml` - Auto-rebase PR checker
107- `buddy-update.yml` - Scheduled dependency updates
105- `buddy.yml` - Unified workflow covering checks, updates and the dashboard
106- `buddy-security.yml` - Workflow security audit, on its own path filters
108107
109108#### 🎯 Step 7: Final Instructions
110109
@@ -116,7 +115,7 @@ Generates three core GitHub Actions workflows:
116115
117116After the enhanced setup completes, you'll have:
118117
119- ✅ **Complete automation** - Three production-ready workflows with validation
118- ✅ **Complete automation** - Two production-ready workflows with validation
120119- ✅ **Professional dashboard** - Single issue tracking all dependencies
121120- ✅ **Interactive rebasing** - Checkbox-based PR updates with conflict resolution
122121- ✅ **Smart scheduling** - Optimized update frequency based on project analysis
@@ -232,15 +231,17 @@ jobs:
232231
233232```bash
234233# Daily security patches
235buddy update --strategy patch --auto-merge
234buddy update --strategy patch
236235
237236# Weekly minor updates
238buddy update --strategy minor --reviewers team-lead
237buddy update --strategy minor
239238
240# Monthly major updates
241buddy update --strategy major --assignees senior-dev
239# Monthly major updates, holding back one package
240buddy update --strategy major --ignore legacy-package
242241```
243242
243Reviewers, assignees, labels and auto-merge are not command line flags — set them once under `pullRequest` in `buddy.config.ts` and every run picks them up.
244
244245## 🏗️ Architecture
245246
246247Buddy is built with modern tools and best practices:
@@ -257,7 +258,7 @@ Buddy is built with modern tools and best practices:
257258|---------|-------|------------|----------|
258259| **Speed** | ⚡ Bun-native | �� Slower | �� Slower |
259260| **Package Managers** | Bun, npm, yarn, pnpm, pkgx, Launchpad | Limited | Limited |
260| **Configuration** | TypeScript, YAML, JSON/JS, package.json | YAML | JSON/JS |
261| **Configuration** | TypeScript, JS, JSON | YAML | JSON/JS |
261262| **Grouping** | ✅ Flexible | ✅ Basic | ✅ Advanced |
262263| **Zero Config** | ✅ Yes | ✅ Yes | ❌ Complex |
263264| **Self-hosted** | ✅ Yes | ❌ GitHub only | ✅ Yes |
docs/usage.mdmodified+79-51
Changes to docs/usage.md
@@ -87,16 +87,20 @@ buddy scan --strategy patch
8787# Create update pull requests
8888buddy update
8989buddy update --dry-run
90buddy update --assignee username
90buddy update --strategy patch
9191
9292# Rebase/retry a specific PR
9393buddy rebase 123
9494buddy rebase 123 --force
9595
96# Check if PR has rebase checkbox
97buddy update-check 123
96# Auto-rebase every open buddy PR with a checked rebase box
97buddy update-check
98buddy update-check --dry-run
9899```
99100
101Reviewers, assignees, labels and auto-merge are configured under `pullRequest` in
102`buddy.config.ts` — `buddy update` has no flags for them.
103
100104### Package Analysis
101105
102106```bash
@@ -118,16 +122,15 @@ buddy search "ui library"
118122### Configuration & Utilities
119123
120124```bash
121# Generate configuration file
122buddy init
123buddy init --template comprehensive
125# Generate the configuration file and GitHub Actions workflows
126buddy setup
127buddy setup --non-interactive --preset security
124128
125# Generate GitHub Actions workflows
126buddy workflow daily
127buddy workflow security
129# Diagnose credentials, git state and tooling
130buddy doctor
128131
129132# Utility commands
130buddy help
133buddy --help
131134buddy --version
132135```
133136
@@ -166,7 +169,7 @@ steps:
166169
167170- **npm packages**: Uses `bun outdated` for accurate detection
168171- **Composer packages**: Uses `composer outdated` and Packagist API
169- **pkgx/Launchpad packages**: Uses `ts-pkgx` library integration
172- **pkgx/Launchpad packages**: Uses `ts-pantry` library integration
170173- **GitHub Actions**: Fetches latest releases via GitHub API
171174
172175## Library Usage
@@ -189,12 +192,11 @@ const buddy = new Buddy({
189192})
190193
191194// Scan for updates
192const updates = await buddy.scanForUpdates()
193console.log(`Found ${updates.length} package updates`)
195const scanResult = await buddy.scanForUpdates()
196console.log(`Found ${scanResult.updates.length} package updates`)
194197
195198// Create pull requests
196const prs = await buddy.createPullRequests()
197console.log(`Created ${prs.length} pull requests`)
199await buddy.createPullRequests(scanResult)
198200```
199201
200202### Advanced Configuration
@@ -261,15 +263,15 @@ await buddy.run()
261263```typescript
262264try {
263265 const buddy = new Buddy(config)
264 const updates = await buddy.scanForUpdates()
266 const scanResult = await buddy.scanForUpdates()
265267
266 if (updates.length === 0) {
268 if (scanResult.updates.length === 0) {
267269 console.log('All packages are up to date!')
268270 return
269271 }
270272
271 const prs = await buddy.createPullRequests()
272 console.log(`Successfully created ${prs.length} PRs`)
273 await buddy.createPullRequests(scanResult)
274 console.log(`Opened pull requests for ${scanResult.updates.length} updates`)
273275}
274276catch (error) {
275277 if (error.code === 'GITHUB_TOKEN_MISSING') {
@@ -401,15 +403,14 @@ jobs:
401403 - run: bun install
402404 - name: Security updates only
403405
404 run: |
405 bunx @buddysh/buddy update \
406 --strategy patch \
407 --labels security,dependencies \
408 --auto-merge
406 run: bunx @buddysh/buddy update --strategy patch --verbose
409407 env:
410408 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
411409```
412410
411Labels and auto-merge for these PRs come from the `pullRequest` block in
412`buddy.config.ts`.
413
413414### Matrix Strategy
414415
415416```yaml
@@ -433,10 +434,7 @@ jobs:
433434 - run: bun install
434435 - name: Update ${{ matrix.strategy }}
435436
436 run: |
437 bunx @buddysh/buddy update \
438 --strategy ${{ matrix.strategy }} \
439 --labels ${{ matrix.strategy }}-updates
437 run: bunx @buddysh/buddy update --strategy ${{ matrix.strategy }}
440438 env:
441439 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
442440```
@@ -498,53 +496,83 @@ GITHUB_TOKEN=$
498496export GITHUB_TOKEN=ghp_xxxxxxxxxxxx
499497
500498# Optional: Custom registry
501export NPM_REGISTRY_URL=https://registry.npmjs.org
502
503# Optional: Bun configuration
504export BUN_CONFIG_NO_CACHE=false
499export NPM_CONFIG_REGISTRY=https://registry.npmjs.org
505500
506# Optional: Debug mode
507export DEBUG=buddy:_
501# Optional: Log verbosity (silent | error | warn | info | debug)
502export BUDDY_LOG_LEVEL=debug
508503```
509504
510505## Workflow Examples
511506
507`buddy update` accepts `--strategy`, `--ignore`, `--dry-run`, `--respect-latest`,
508`--no-respect-latest` and `--verbose`. Everything about the pull request itself —
509reviewers, assignees, labels, auto-merge — is read from `buddy.config.ts`, so each
510example below pairs the config with the script that runs it.
511
512512### Daily Patch Updates
513513
514```typescript
515// buddy.config.ts
516export default {
517 pullRequest: {
518 labels: ['security', 'patch-updates'],
519 autoMerge: {
520 enabled: true,
521 strategy: 'squash',
522 conditions: ['patch-only'],
523 },
524 },
525} satisfies BuddyConfig
526```
527
514528```bash
515529# !/bin/bash
516530# daily-updates.sh
517531
518buddy update \
519 --strategy patch \
520 --auto-merge \
521 --labels security,patch-updates
532buddy update --strategy patch
522533```
523534
524535### Weekly Comprehensive Updates
525536
537```typescript
538// buddy.config.ts
539export default {
540 pullRequest: {
541 reviewers: ['team-lead', 'senior-dev'],
542 assignees: ['maintainer'],
543 labels: ['dependencies', 'weekly-update'],
544 },
545} satisfies BuddyConfig
546```
547
526548```bash
527549# !/bin/bash
528550# weekly-updates.sh
529551
530buddy update \
531 --strategy all \
532 --reviewers team-lead,senior-dev \
533 --assignees maintainer \
534 --labels dependencies,weekly-update
552buddy update --strategy all
535553```
536554
537555### Emergency Security Update
538556
557```typescript
558// buddy.config.ts
559export default {
560 pullRequest: {
561 labels: ['security', 'urgent'],
562 autoMerge: {
563 enabled: true,
564 strategy: 'squash',
565 conditions: ['security-only'],
566 },
567 },
568} satisfies BuddyConfig
569```
570
539571```bash
540572# !/bin/bash
541573# security-update.sh
542574
543buddy update \
544 --strategy patch \
545 --packages-only security \
546 --auto-merge \
547 --labels security,urgent
575buddy update --strategy patch --verbose
548576```
549577
550578## Dependency File Support
@@ -640,10 +668,10 @@ by path, use a rule with `matchFiles` as above. See
640668## Testing
641669
642670```bash
643# Test configuration
644buddy scan --dry-run --verbose
671# Test configuration, credentials and git state
672buddy doctor --verbose
645673
646# Test GitHub authentication
674# Test scanning and GitHub authentication
647675buddy scan --verbose
648676
649677# Test package detection
docs/use-cases/platform-teams.mdmodified+1-1
Changes to docs/use-cases/platform-teams.md
@@ -64,7 +64,7 @@ hero:
6464 - file: "the check run"
6565 lang: "ascii"
6666 content: |
67 buddy/gate — 2 failing
67 buddy/gates — 2 failing
6868
6969 ✔ title-format conventional commit
7070 ✔ description complete