Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
### Added

- Added first-class Bitbucket Cloud support for configuring provider profiles, preparing and checking out pull request review bundles, reading pull request discussions, showing status, and publishing revpack outputs.
- Added primary onboarding commands and help: `revpack connect`, top-level `revpack doctor`, `revpack setup --agent <target>`, a concise top-level workflow, and checkout target examples.

### Changed

Expand Down
24 changes: 8 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,35 +29,27 @@ npm install -g @stefanvictora/revpack
Open the repository you want to review, then configure a provider profile:

```bash
revpack config setup
revpack connect
export REVPACK_GITHUB_TOKEN=ghp_xxxxxxxxxxxx
# or
export REVPACK_GITLAB_TOKEN=glpat-xxxxxxxxxxxx
# or
export REVPACK_BITBUCKET_EMAIL=you@example.com
export REVPACK_BITBUCKET_TOKEN=ATBBTxxxxxxxxxxxx
revpack config doctor
revpack doctor
```

Optionally, add review guidance:

```bash
revpack setup
```

Customize `REVIEW.md` when you want agents to follow project-specific review priorities.

Then add instructions for your agent:
Add review guidance and instructions for your agent:

```bash
# Pick one:
revpack setup agent claude
revpack setup agent codex
revpack setup agent cursor
revpack setup agent copilot
revpack setup --agent claude
revpack setup --agent codex
revpack setup --agent cursor
revpack setup --agent copilot
```

This writes project-level instruction files, such as an agent command, skill, or prompt. It does not install or run the agent.
This creates `REVIEW.md` when missing and writes project-level instruction files, such as an agent command, skill, or prompt. It does not install or run the agent.

Use `--dry-run` to preview generated files before writing them.

Expand Down
32 changes: 29 additions & 3 deletions docs/commands.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
# Command reference

## Primary workflow

```bash
revpack connect # create a provider profile interactively
revpack doctor # check the matching provider profile
revpack setup --agent codex # create REVIEW.md and install one agent adapter
revpack prepare # create or refresh the review bundle
# run your agent
revpack status
revpack publish all
```

For another PR/MR, use `revpack checkout <url-or-id>`. For a local branch review, use `revpack prepare --local [base]`.

## `prepare [ref]`

Creates or refreshes the `.revpack/` bundle for a PR/MR.
Expand Down Expand Up @@ -105,6 +119,10 @@ Creates project-level files that help agents review consistently.

```bash
revpack setup
revpack setup --agent claude
revpack setup --agent codex
revpack setup --agent cursor
revpack setup --agent copilot
revpack setup agent claude
revpack setup agent codex
revpack setup agent cursor
Expand All @@ -113,6 +131,8 @@ revpack setup --prompts
revpack setup --dry-run
```

`revpack setup` creates only `REVIEW.md`.
`revpack setup --agent <target>` creates `REVIEW.md` when missing and installs one agent adapter.
`revpack setup agent <target>` writes project-level instruction files for one agent target and does not create `REVIEW.md`.

`--prompts` is kept as a deprecated compatibility flag. It creates `REVIEW.md` and installs the Copilot `/revpack-review` prompt.
Expand All @@ -129,16 +149,22 @@ Generated harness files:
Creates, inspects, and edits provider profiles. Revpack stores provider settings in named profiles. Commands such as `show`, `doctor`, `get`, `set`, and `unset` use the profile resolved from the current git remote unless you pass `--profile`; `config profile` commands manage saved profiles directly.

```bash
# Create
# Primary onboarding
revpack connect
revpack doctor
revpack doctor --profile myprofile

# Compatibility aliases
revpack config setup
revpack config doctor

# Non-interactive profile creation
revpack config profile create myBitbucket --provider bitbucket-cloud --url https://bitbucket.org --email-env REVPACK_BITBUCKET_EMAIL --token-env REVPACK_BITBUCKET_TOKEN

# Current project
revpack config show
revpack config show --profile myprofile
revpack config show --sources
revpack config doctor
revpack config doctor --profile myprofile

# Profile values
revpack config get <key>
Expand Down
24 changes: 24 additions & 0 deletions src/cli/commands/checkout.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,30 @@ describe('checkout command', () => {
expect(runSetupMock).toHaveBeenCalledWith({ cwd: process.cwd() });
});

it('shows concise target examples in help', async () => {
const output: string[] = [];
const program = new Command();
program.exitOverride();
program.configureOutput({
writeOut: (value) => output.push(value),
writeErr: (value) => output.push(value),
});
registerCheckoutCommand(program);

try {
await program.parseAsync(['node', 'revpack', 'checkout', '--help']);
} catch {
// Commander exits after printing --help when exitOverride is enabled.
}

const help = output.join('');
expect(help).toContain('Examples:');
expect(help).toContain('revpack checkout !42');
expect(help).toContain('revpack checkout 58 --repo owner/repo');
expect(help).toContain('revpack checkout https://github.com/owner/repo/pull/58');
expect(help).toContain('revpack checkout workspace/repo#42 --profile bitbucket');
});

async function parseCheckout(...args: string[]): Promise<void> {
const program = new Command();
program.exitOverride();
Expand Down
13 changes: 12 additions & 1 deletion src/cli/commands/checkout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { formatGuidanceLine } from '../output.js';
import { runSetup } from './setup.js';

export function registerCheckoutCommand(program: Command): void {
program
const checkoutCmd = program
.command('checkout <ref>')
.description(
[
Expand Down Expand Up @@ -82,6 +82,17 @@ export function registerCheckoutCommand(program: Command): void {
handleError(err);
}
});

checkoutCmd.addHelpText(
'after',
`
Examples:
revpack checkout !42
revpack checkout 58 --repo owner/repo
revpack checkout https://github.com/owner/repo/pull/58
revpack checkout workspace/repo#42 --profile bitbucket
`,
);
}

function createPrepareFetchLogger(): (message: string) => void {
Expand Down
31 changes: 28 additions & 3 deletions src/cli/commands/config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
validateProviderUrlForProvider,
} from '../../config/index.js';
import { ConfigError } from '../../core/errors.js';
import { registerConfigCommand } from './config.js';
import { registerConfigCommand, registerPrimaryConfigCommands } from './config.js';

describe('config command', () => {
it('prints help for the parent command instead of showing resolved config', async () => {
Expand All @@ -33,15 +33,40 @@ describe('config command', () => {
expect(help).toContain('profile');
expect(help).toContain('List, show, create, or delete saved profiles');
expect(help).toContain('Create:');
expect(help).toContain('revpack config setup');
expect(help).toContain('revpack connect');
expect(help).toContain('Current project:');
expect(help).toContain('revpack config doctor');
expect(help).toContain('revpack doctor');
expect(help).toContain('Saved profiles:');
expect(help).toContain('revpack config profile list');
expect(help).toContain('revpack config profile delete <name>');
expect(help).toContain('setup');
expect(help).toContain('doctor');
expect(help).not.toContain('No active profile');
});

it('registers top-level connect and doctor commands', async () => {
const output: string[] = [];
const program = new Command();
program.exitOverride();
program.configureOutput({
writeOut: (value) => output.push(value),
writeErr: (value) => output.push(value),
});
registerPrimaryConfigCommands(program);

try {
await program.parseAsync(['node', 'revpack', 'doctor', '--help']);
} catch {
// Commander exits after printing --help when exitOverride is enabled.
}

const help = output.join('');
expect(help).toContain('Usage: revpack doctor [options]');
expect(help).toContain('--profile <name>');
expect(help).toContain('--json');
expect(program.commands.map((command) => command.name())).toEqual(['connect', 'doctor']);
});

it('describes profile create as the non-interactive creation path', async () => {
const output: string[] = [];
const program = new Command();
Expand Down
Loading