byterover-cli 0.1.1 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/README.md +37 -27
  2. package/bin/dev.cmd +1 -1
  3. package/bin/dev.js +1 -1
  4. package/bin/run.cmd +1 -1
  5. package/bin/run.js +1 -1
  6. package/dist/commands/add.js +1 -1
  7. package/dist/commands/init.d.ts +6 -0
  8. package/dist/commands/init.js +73 -27
  9. package/dist/commands/logout.d.ts +16 -0
  10. package/dist/commands/logout.js +61 -0
  11. package/dist/commands/push.d.ts +5 -5
  12. package/dist/commands/push.js +11 -11
  13. package/dist/commands/retrieve.d.ts +2 -2
  14. package/dist/commands/retrieve.js +3 -3
  15. package/dist/commands/space/list.js +10 -5
  16. package/dist/commands/space/switch.js +8 -7
  17. package/dist/commands/status.js +5 -5
  18. package/dist/config/environment.d.ts +3 -2
  19. package/dist/config/environment.js +5 -3
  20. package/dist/constants.d.ts +8 -1
  21. package/dist/constants.js +8 -1
  22. package/dist/core/domain/entities/{br-config.d.ts → brv-config.d.ts} +5 -5
  23. package/dist/core/domain/entities/{br-config.js → brv-config.js} +5 -5
  24. package/dist/core/domain/entities/event.d.ts +1 -1
  25. package/dist/core/domain/entities/event.js +1 -0
  26. package/dist/core/interfaces/i-playbook-service.d.ts +1 -1
  27. package/dist/core/interfaces/i-project-config-store.d.ts +10 -10
  28. package/dist/core/interfaces/i-rule-template-service.d.ts +0 -4
  29. package/dist/core/interfaces/i-rule-template-service.js +1 -4
  30. package/dist/hooks/init/welcome.d.ts +3 -0
  31. package/dist/hooks/init/welcome.js +31 -0
  32. package/dist/infra/ace/ace-file-utils.js +2 -2
  33. package/dist/infra/ace/file-bullet-content-store.d.ts +4 -4
  34. package/dist/infra/ace/file-bullet-content-store.js +7 -7
  35. package/dist/infra/ace/file-delta-store.d.ts +1 -1
  36. package/dist/infra/ace/file-delta-store.js +1 -1
  37. package/dist/infra/ace/file-executor-output-store.d.ts +1 -1
  38. package/dist/infra/ace/file-executor-output-store.js +1 -1
  39. package/dist/infra/ace/file-playbook-store.d.ts +3 -3
  40. package/dist/infra/ace/file-playbook-store.js +6 -6
  41. package/dist/infra/ace/file-reflection-store.d.ts +1 -1
  42. package/dist/infra/ace/file-reflection-store.js +1 -1
  43. package/dist/infra/config/file-config-store.d.ts +6 -8
  44. package/dist/infra/config/file-config-store.js +10 -11
  45. package/dist/infra/playbook/file-playbook-service.d.ts +0 -1
  46. package/dist/infra/playbook/file-playbook-service.js +7 -8
  47. package/dist/infra/rule/constants.d.ts +4 -0
  48. package/dist/infra/rule/constants.js +4 -0
  49. package/dist/infra/rule/rule-template-service.js +1 -1
  50. package/dist/infra/rule/rule-writer-service.js +1 -5
  51. package/dist/templates/README.md +5 -5
  52. package/dist/templates/sections/command-reference.md +41 -23
  53. package/dist/templates/sections/workflow.md +11 -12
  54. package/oclif.manifest.json +44 -4
  55. package/package.json +9 -8
package/README.md CHANGED
@@ -6,6 +6,14 @@ Command-line interface for ByteRover, enabling seamless team/space management, a
6
6
  [![Downloads/week](https://img.shields.io/npm/dw/byterover-cli.svg)](https://npmjs.org/package/byterover-cli)
7
7
  [![Node](https://img.shields.io/badge/node-%3E%3D18.0.0-brightgreen.svg)](https://nodejs.org)
8
8
 
9
+ ## Important
10
+
11
+ Starting with version **0.2.0**, the ByteRover CLI command has been renamed from `br` to `brv` to avoid conflicts with [broot](https://github.com/Canop/broot), another popular CLI tool that also uses the `br` command.
12
+
13
+ This is a **breaking change** that requires action from existing users.
14
+
15
+ Please check the migration guide [here](https://docs.byterover.dev/beta/migration-br-brv).
16
+
9
17
  ## Table of Contents
10
18
 
11
19
  * [Installation](#installation)
@@ -40,17 +48,19 @@ npm install -g byterover-cli
40
48
  ### Verify installation
41
49
 
42
50
  ```bash
43
- br --version
51
+ brv --version
44
52
  ```
45
53
 
46
54
  ## Quick Start
47
55
 
56
+ Visit [**ByteRover's Beta Docs**](https://docs.byterover.dev/beta) for more information.
57
+
48
58
  Get started with ByteRover CLI in three simple steps:
49
59
 
50
60
  ### 1. Authenticate
51
61
 
52
62
  ```bash
53
- br login
63
+ brv login
54
64
  ```
55
65
 
56
66
  This opens your browser to complete OAuth authentication. Your credentials are securely stored in the system keychain.
@@ -58,8 +68,8 @@ This opens your browser to complete OAuth authentication. Your credentials are s
58
68
  ### 2. Initialize a project
59
69
 
60
70
  ```bash
61
- cd your-project-directory
62
- br init
71
+ cd to/your/project
72
+ brv init
63
73
  ```
64
74
 
65
75
  Select a space from your available spaces and configure your project.
@@ -100,14 +110,14 @@ If you're using a coding agent like Claude Code:
100
110
 
101
111
  ```bash
102
112
  # Complete ACE workflow in a single command
103
- br complete "auth-feature" \
113
+ brv complete "auth-feature" \
104
114
  "Implemented JWT authentication with secure token handling" \
105
115
  "Successfully added OAuth2 authentication" \
106
116
  --tool-usage "Read:src/auth.ts,Edit:src/auth.ts,Bash:npm test" \
107
117
  --feedback "All tests passed, auth works correctly"
108
118
  ```
109
119
 
110
- For comprehensive ACE instructions for coding agents, check the corresponding coding agents' instruction files after `br init` or `br gen-rules`.
120
+ For comprehensive ACE instructions for coding agents, check the corresponding coding agents' instruction files after `brv init` or `brv gen-rules`.
111
121
 
112
122
  ## Essential Commands
113
123
 
@@ -115,46 +125,46 @@ For comprehensive ACE instructions for coding agents, check the corresponding co
115
125
 
116
126
  ```bash
117
127
  # Log in to ByteRover
118
- br login
128
+ brv login
119
129
 
120
130
  # Check your authentication and project status
121
- br status
131
+ brv status
122
132
  ```
123
133
 
124
134
  ### Project Setup
125
135
 
126
136
  ```bash
127
137
  # Initialize project with ByteRover
128
- br init
138
+ brv init
129
139
 
130
140
  # List available spaces
131
- br space list
141
+ brv space list
132
142
 
133
143
  # Switch to a different space or team
134
- br space switch
144
+ brv space switch
135
145
  ```
136
146
 
137
147
  ### Memory Operations
138
148
 
139
149
  ```bash
140
150
  # Retrieve memories from ByteRover (outputs to stdout for agent context)
141
- br retrieve --query "authentication best practices"
142
- br retrieve -q "error handling" -n "src/auth/login.ts,src/auth/oauth.ts"
151
+ brv retrieve --query "authentication best practices"
152
+ brv retrieve -q "error handling" -n "src/auth/login.ts,src/auth/oauth.ts"
143
153
 
144
154
  # Push your playbook to ByteRover's memory storage
145
- br push
155
+ brv push
146
156
  ```
147
157
 
148
158
  ### For Coding Agents
149
159
 
150
160
  ```bash
151
161
  # Complete ACE workflow (recommended for agents)
152
- br complete <hint> <reasoning> <answer> \
162
+ brv complete <hint> <reasoning> <answer> \
153
163
  --tool-usage <tools> \
154
164
  --feedback <feedback>
155
165
 
156
166
  # Generate agent rules (sets up ACE workflow for your coding agent)
157
- br gen-rules
167
+ brv gen-rules
158
168
  ```
159
169
 
160
170
  ## Authentication
@@ -163,7 +173,7 @@ ByteRover CLI uses **OAuth 2.0 with PKCE** (Proof Key for Code Exchange) for sec
163
173
 
164
174
  ### How it works
165
175
 
166
- 1. Run `br login` to start authentication
176
+ 1. Run `brv login` to start authentication
167
177
  2. Your browser opens to the ByteRover authorization page
168
178
  3. After successful login, tokens are securely stored in your system keychain
169
179
  4. All subsequent commands automatically use your stored credentials
@@ -179,7 +189,7 @@ ByteRover CLI uses **OAuth 2.0 with PKCE** (Proof Key for Code Exchange) for sec
179
189
 
180
190
  ### Project Configuration
181
191
 
182
- When you run `br init`, a configuration file is created at `.br/config.json` in your project directory containing:
192
+ When you run `brv init`, a configuration file is created at `.brv/config.json` in your project directory containing:
183
193
 
184
194
  - **Space ID**: The ByteRover workspace/space associated with this project
185
195
  - **User information**: Your user ID and email
@@ -187,17 +197,17 @@ When you run `br init`, a configuration file is created at `.br/config.json` in
187
197
 
188
198
  ### ACE File Structure
189
199
 
190
- ACE stores all outputs in `.br/ace/`:
200
+ ACE stores all outputs in `.brv/ace/`:
191
201
 
192
202
  ```
193
- .br/ace/
203
+ .brv/ace/
194
204
  ├── playbook.json # Your living knowledge base
195
205
  ├── executor-outputs/ # Coding task outputs
196
206
  ├── reflections/ # Task analysis and feedback
197
207
  └── deltas/ # Playbook updates
198
208
  ```
199
209
 
200
- **Note**: When you run `br push`, the playbook is uploaded to ByteRover's memory storage, and local ACE files are automatically cleaned up to keep your workspace organized.
210
+ **Note**: When you run `brv push`, the playbook is uploaded to ByteRover's memory storage, and local ACE files are automatically cleaned up to keep your workspace organized.
201
211
 
202
212
  ## Getting Help
203
213
 
@@ -205,20 +215,20 @@ ACE stores all outputs in `.br/ace/`:
205
215
 
206
216
  ```bash
207
217
  # Get general help
208
- br help
218
+ brv --help
209
219
 
210
220
  # Get help for a specific command
211
- br help login
212
- br help init
213
- br help push
221
+ brv login --help
222
+ brv init --help
223
+ brv push --help
214
224
  ```
215
225
 
216
226
  ### Support
217
227
 
218
228
  If you encounter issues or have questions:
219
229
 
220
- 1. Check the command help: `br help [command]`
221
- 2. Review your status: `br status`
230
+ 1. Check the command help: `brv [command] --help`
231
+ 2. Review your status: `brv status`
222
232
  3. Contact ByteRover support
223
233
 
224
234
  ---
package/bin/dev.cmd CHANGED
@@ -1,4 +1,4 @@
1
1
  @echo off
2
2
 
3
- set BR_ENV=development
3
+ set BRV_ENV=development
4
4
  node --loader ts-node/esm --no-warnings=ExperimentalWarning "%~dp0\dev" %*
package/bin/dev.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env -S node --loader ts-node/esm --disable-warning=ExperimentalWarning
2
2
 
3
- process.env.BR_ENV = 'development'
3
+ process.env.BRV_ENV = 'development'
4
4
 
5
5
  import {execute} from '@oclif/core'
6
6
 
package/bin/run.cmd CHANGED
@@ -1,4 +1,4 @@
1
1
  @echo off
2
2
 
3
- set BR_ENV=production
3
+ set BRV_ENV=production
4
4
  node "%~dp0\run" %*
package/bin/run.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- process.env.BR_ENV = 'production'
3
+ process.env.BRV_ENV = 'production'
4
4
 
5
5
  import {execute} from '@oclif/core'
6
6
 
@@ -62,7 +62,7 @@ export default class Add extends Command {
62
62
  this.log(` Section: ${section}`);
63
63
  const contentDisplay = content.length > 200 ? `${content.slice(0, 200)}...` : content;
64
64
  this.log(` Content: ${contentDisplay}`);
65
- this.log('\nTip: Use `br status` to view and update bullets later');
65
+ this.log('\nTip: Use `brv status` to view and update bullets later');
66
66
  const confirmed = await confirm({
67
67
  default: true,
68
68
  message: 'Add this bullet?',
@@ -6,10 +6,16 @@ import type { IProjectConfigStore } from '../core/interfaces/i-project-config-st
6
6
  import type { ISpaceService } from '../core/interfaces/i-space-service.js';
7
7
  import type { ITeamService } from '../core/interfaces/i-team-service.js';
8
8
  import type { ITokenStore } from '../core/interfaces/i-token-store.js';
9
+ import { BrvConfig } from '../core/domain/entities/brv-config.js';
9
10
  import { ITrackingService } from '../core/interfaces/i-tracking-service.js';
10
11
  export default class Init extends Command {
11
12
  static description: string;
12
13
  static examples: string[];
14
+ static flags: {
15
+ force: import("@oclif/core/interfaces").BooleanFlag<boolean>;
16
+ };
17
+ protected cleanupBeforeReInitialization(): Promise<void>;
18
+ protected confirmReInitialization(config: BrvConfig): Promise<boolean>;
13
19
  protected createServices(): {
14
20
  playbookService: IPlaybookService;
15
21
  projectConfigStore: IProjectConfigStore;
@@ -1,7 +1,10 @@
1
- import { select } from '@inquirer/prompts';
2
- import { Command, ux } from '@oclif/core';
1
+ import { confirm, select } from '@inquirer/prompts';
2
+ import { Command, Flags, ux } from '@oclif/core';
3
+ import { rm } from 'node:fs/promises';
4
+ import { join } from 'node:path';
3
5
  import { getCurrentConfig } from '../config/environment.js';
4
- import { BrConfig } from '../core/domain/entities/br-config.js';
6
+ import { BRV_DIR, PROJECT_CONFIG_FILE } from '../constants.js';
7
+ import { BrvConfig } from '../core/domain/entities/brv-config.js';
5
8
  import { ProjectConfigStore } from '../infra/config/file-config-store.js';
6
9
  import { FilePlaybookService } from '../infra/playbook/file-playbook-service.js';
7
10
  import { HttpSpaceService } from '../infra/space/http-space-service.js';
@@ -9,12 +12,47 @@ import { KeychainTokenStore } from '../infra/storage/keychain-token-store.js';
9
12
  import { HttpTeamService } from '../infra/team/http-team-service.js';
10
13
  import { MixpanelTrackingService } from '../infra/tracking/mixpanel-tracking-service.js';
11
14
  export default class Init extends Command {
12
- static description = 'Initialize a project with ByteRover (creates .br/config.json with team/space selection and initializes ACE playbook)';
15
+ static description = `Initialize a project with ByteRover (creates ${BRV_DIR}/${PROJECT_CONFIG_FILE} with team/space selection and initializes ACE playbook)`;
13
16
  static examples = [
14
17
  '<%= config.bin %> <%= command.id %>',
15
18
  '# Re-initialize if config exists (will show current config and exit):\n<%= config.bin %> <%= command.id %>',
16
19
  '# Full workflow: login then initialize:\n<%= config.bin %> login\n<%= config.bin %> <%= command.id %>',
17
20
  ];
21
+ static flags = {
22
+ force: Flags.boolean({
23
+ char: 'f',
24
+ default: false,
25
+ description: 'Force re-initialization without confirmation prompt',
26
+ }),
27
+ };
28
+ async cleanupBeforeReInitialization() {
29
+ const brvDir = join(process.cwd(), BRV_DIR);
30
+ this.log('\n Cleaning up existing ByteRover directory...');
31
+ ux.action.start(` Removing ${BRV_DIR}/`);
32
+ try {
33
+ await rm(brvDir, { force: true, recursive: true });
34
+ ux.action.stop('✓');
35
+ }
36
+ catch (error) {
37
+ ux.action.stop('✗');
38
+ this.error(`Failed to remove ${BRV_DIR}/: ${error instanceof Error ? error.message : 'Unknown error'}`);
39
+ }
40
+ }
41
+ async confirmReInitialization(config) {
42
+ this.log('\n Project is already initialized');
43
+ this.log(` Team: ${config.teamName}`);
44
+ this.log(` Space: ${config.spaceName}`);
45
+ this.log(` Config: ${join(process.cwd(), BRV_DIR, PROJECT_CONFIG_FILE)}`);
46
+ this.log('\n Re-initializing will:');
47
+ this.log(` - Remove the entire ${BRV_DIR}/ directory and all its contents`);
48
+ this.log(' - Allow you to select a new team/space');
49
+ this.log(' - Create a fresh configuration and ACE playbook');
50
+ this.log(' - Regenerate rule instructions\n');
51
+ return confirm({
52
+ default: false,
53
+ message: 'Continue with re-initialization?',
54
+ });
55
+ }
18
56
  createServices() {
19
57
  const envConfig = getCurrentConfig();
20
58
  const tokenStore = new KeychainTokenStore();
@@ -61,37 +99,49 @@ export default class Init extends Command {
61
99
  return selectedTeam;
62
100
  }
63
101
  async run() {
102
+ const { flags } = await this.parse(Init);
64
103
  try {
65
104
  const { playbookService, projectConfigStore, spaceService, teamService, tokenStore, trackingService } = this.createServices();
66
- // 1. Check if already initialized
67
- const isInitialized = await projectConfigStore.exists();
68
- if (isInitialized) {
69
- this.log('Project is already initialized with ByteRover.');
70
- const existingProjectConfig = await projectConfigStore.read();
71
- this.log(`Your space for this project is: ${existingProjectConfig?.teamName}/${existingProjectConfig?.spaceName}`);
72
- return;
105
+ const alreadyInitialized = await projectConfigStore.exists();
106
+ if (alreadyInitialized) {
107
+ const currentConfig = await projectConfigStore.read();
108
+ if (currentConfig === undefined) {
109
+ this.error('Configuration file exists but cannot be read. Please check .brv/config.json');
110
+ }
111
+ if (!flags.force) {
112
+ const confirmed = await this.confirmReInitialization(currentConfig);
113
+ if (!confirmed) {
114
+ this.log('\nCancelled. Project configuration unchanged.');
115
+ return;
116
+ }
117
+ }
118
+ try {
119
+ await this.cleanupBeforeReInitialization();
120
+ }
121
+ catch (error) {
122
+ this.error(`Failed to clean up existing data: ${error instanceof Error ? error.message : 'Unknown error'}`);
123
+ }
124
+ this.log('\n'); // Spacing before continuing with init flow
73
125
  }
74
126
  this.log('Initializing ByteRover project...\n');
75
- // 2. Load and validate authentication token
76
127
  const token = await tokenStore.load();
77
128
  if (token === undefined) {
78
- this.error('Not authenticated. Please run "br login" first.');
129
+ this.error('Not authenticated. Please run "brv login" first.');
79
130
  }
80
131
  if (!token.isValid()) {
81
- this.error('Authentication token expired. Please run "br login" again.');
132
+ this.error('Authentication token expired. Please run "brv login" again.');
82
133
  }
83
- // 3. Fetch all teams with spinner
84
134
  ux.action.start('Fetching all teams');
85
135
  const teamResult = await teamService.getTeams(token.accessToken, token.sessionKey, { fetchAll: true });
86
136
  ux.action.stop();
87
137
  const { teams } = teamResult;
88
138
  if (teams.length === 0) {
89
- this.error('No teams found. Please create a team in the ByteRover dashboard first.');
139
+ this.log('No teams found.');
140
+ this.log(`Please visit ${getCurrentConfig().webAppUrl} to create your first team.`);
141
+ return;
90
142
  }
91
- // 4. Prompt for team selection
92
143
  this.log();
93
144
  const selectedTeam = await this.promptForTeamSelection(teams);
94
- // 5. Fetch all spaces for the selected team with spinner
95
145
  ux.action.start('Fetching all spaces');
96
146
  const spaceResult = await spaceService.getSpaces(token.accessToken, token.sessionKey, selectedTeam.id, {
97
147
  fetchAll: true,
@@ -99,15 +149,14 @@ export default class Init extends Command {
99
149
  ux.action.stop();
100
150
  const { spaces } = spaceResult;
101
151
  if (spaces.length === 0) {
102
- this.error(`No spaces found in team "${selectedTeam.getDisplayName()}". Please create a space in the ByteRover dashboard first.`);
152
+ this.log(`No spaces found in team "${selectedTeam.getDisplayName()}"`);
153
+ this.log(`Please visit ${getCurrentConfig().webAppUrl} to create your first space for ${selectedTeam.getDisplayName()}.`);
154
+ return;
103
155
  }
104
- // 6. Prompt for space selection
105
156
  this.log();
106
157
  const selectedSpace = await this.promptForSpaceSelection(spaces);
107
- // 7. Create and save configuration
108
- const config = BrConfig.fromSpace(selectedSpace);
158
+ const config = BrvConfig.fromSpace(selectedSpace);
109
159
  await projectConfigStore.write(config);
110
- // 8. Initialize ACE playbook
111
160
  this.log('\nInitializing ACE context...');
112
161
  try {
113
162
  const playbookPath = await playbookService.initialize();
@@ -117,16 +166,13 @@ export default class Init extends Command {
117
166
  // Warn but don't fail if ACE init fails
118
167
  this.warn(`ACE initialization skipped: ${error instanceof Error ? error.message : 'Unknown error'}`);
119
168
  }
120
- // 9. Generate rules
121
169
  this.log(`\nGenerate rule instructions for coding agents to work with ByteRover correctly`);
122
170
  this.log();
123
171
  await this.config.runCommand('gen-rules');
124
- // Track space initialization
125
172
  await trackingService.track('space:init');
126
- // 10. Display success
127
173
  this.log(`\n✓ Project initialized successfully!`);
128
174
  this.log(`✓ Connected to space: ${selectedSpace.getDisplayName()}`);
129
- this.log(`✓ Configuration saved to: .br/config.json`);
175
+ this.log(`✓ Configuration saved to: ${BRV_DIR}/${PROJECT_CONFIG_FILE}`);
130
176
  }
131
177
  catch (error) {
132
178
  this.error(error instanceof Error ? error.message : 'Initialization failed');
@@ -0,0 +1,16 @@
1
+ import { Command } from '@oclif/core';
2
+ import type { ITokenStore } from '../core/interfaces/i-token-store.js';
3
+ import type { ITrackingService } from '../core/interfaces/i-tracking-service.js';
4
+ export default class Logout extends Command {
5
+ static description: string;
6
+ static examples: string[];
7
+ static flags: {
8
+ yes: import("@oclif/core/interfaces").BooleanFlag<boolean>;
9
+ };
10
+ protected confirmLogout(userEmail: string): Promise<boolean>;
11
+ protected createServices(): {
12
+ tokenStore: ITokenStore;
13
+ trackingService: ITrackingService;
14
+ };
15
+ run(): Promise<void>;
16
+ }
@@ -0,0 +1,61 @@
1
+ import { confirm } from '@inquirer/prompts';
2
+ import { Command, Flags } from '@oclif/core';
3
+ import { KeychainTokenStore } from '../infra/storage/keychain-token-store.js';
4
+ import { MixpanelTrackingService } from '../infra/tracking/mixpanel-tracking-service.js';
5
+ export default class Logout extends Command {
6
+ static description = 'Log out of ByteRover CLI and clear authentication (does not affect local project files)';
7
+ static examples = ['<%= config.bin %> <%= command.id %>', '<%= config.bin %> <%= command.id %> --yes'];
8
+ static flags = {
9
+ yes: Flags.boolean({
10
+ char: 'y',
11
+ default: false,
12
+ description: 'Skip confirmation prompt',
13
+ }),
14
+ };
15
+ async confirmLogout(userEmail) {
16
+ return confirm({
17
+ // Pressing 'Enter' = Yes
18
+ default: true,
19
+ message: `Logging out ${userEmail}. Are you sure?`,
20
+ });
21
+ }
22
+ createServices() {
23
+ const tokenStore = new KeychainTokenStore();
24
+ const trackingService = new MixpanelTrackingService(tokenStore);
25
+ return {
26
+ tokenStore,
27
+ trackingService,
28
+ };
29
+ }
30
+ async run() {
31
+ const { flags } = await this.parse(Logout);
32
+ const { tokenStore, trackingService } = this.createServices();
33
+ try {
34
+ const token = await tokenStore.load();
35
+ if (token === undefined) {
36
+ this.log('You are not currently logged in.');
37
+ return;
38
+ }
39
+ if (!flags.yes) {
40
+ const confirmed = await this.confirmLogout(token.userEmail);
41
+ if (!confirmed) {
42
+ this.log('Logout cancelled.');
43
+ return;
44
+ }
45
+ }
46
+ try {
47
+ await trackingService.track('auth:signed_out');
48
+ }
49
+ catch { }
50
+ await tokenStore.clear();
51
+ this.log('Successfully logged out.');
52
+ this.log("Run 'brv login' to authenticate again.");
53
+ }
54
+ catch (error) {
55
+ if (error instanceof Error && error.message.includes('keychain')) {
56
+ this.error('Unable to access system keychain. Please check your system permissions and try again.');
57
+ }
58
+ this.error(error instanceof Error ? error.message : 'Logout failed');
59
+ }
60
+ }
61
+ }
@@ -1,6 +1,6 @@
1
1
  import { Command } from '@oclif/core';
2
2
  import type { AuthToken } from '../core/domain/entities/auth-token.js';
3
- import type { BrConfig } from '../core/domain/entities/br-config.js';
3
+ import type { BrvConfig } from '../core/domain/entities/brv-config.js';
4
4
  import type { PresignedUrl } from '../core/domain/entities/presigned-url.js';
5
5
  import type { PresignedUrlsResponse } from '../core/domain/entities/presigned-urls-response.js';
6
6
  import type { IMemoryStorageService } from '../core/interfaces/i-memory-storage-service.js';
@@ -15,10 +15,10 @@ export default class Push extends Command {
15
15
  branch: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
16
16
  yes: import("@oclif/core/interfaces").BooleanFlag<boolean>;
17
17
  };
18
- protected checkProjectInit(projectConfigStore: IProjectConfigStore): Promise<BrConfig>;
18
+ protected checkProjectInit(projectConfigStore: IProjectConfigStore): Promise<BrvConfig>;
19
19
  protected cleanUpLocalFiles(playbookStore: IPlaybookStore): Promise<void>;
20
- protected confirmPush(projectConfig: BrConfig, branch: string, fileCount: number): Promise<boolean>;
21
- protected confirmUpload(memoryService: IMemoryStorageService, token: AuthToken, projectConfig: BrConfig, requestId: string): Promise<void>;
20
+ protected confirmPush(projectConfig: BrvConfig, branch: string, fileCount: number): Promise<boolean>;
21
+ protected confirmUpload(memoryService: IMemoryStorageService, token: AuthToken, projectConfig: BrvConfig, requestId: string): Promise<void>;
22
22
  protected createServices(): {
23
23
  memoryService: IMemoryStorageService;
24
24
  playbookStore: IPlaybookStore;
@@ -26,7 +26,7 @@ export default class Push extends Command {
26
26
  tokenStore: ITokenStore;
27
27
  trackingService: ITrackingService;
28
28
  };
29
- protected getPresignedUrls(memoryService: IMemoryStorageService, token: AuthToken, projectConfig: BrConfig): Promise<PresignedUrlsResponse>;
29
+ protected getPresignedUrls(memoryService: IMemoryStorageService, token: AuthToken, projectConfig: BrvConfig): Promise<PresignedUrlsResponse>;
30
30
  protected loadPlaybookContent(playbookStore: IPlaybookStore): Promise<string>;
31
31
  run(): Promise<void>;
32
32
  protected uploadFiles(memoryService: IMemoryStorageService, presignedUrls: ReadonlyArray<PresignedUrl>, playbookContent: string): Promise<void>;
@@ -2,7 +2,7 @@ import { confirm } from '@inquirer/prompts';
2
2
  import { Command, Flags, ux } from '@oclif/core';
3
3
  import { join } from 'node:path';
4
4
  import { getCurrentConfig } from '../config/environment.js';
5
- import { ACE_DIR, BR_DIR, DEFAULT_BRANCH, DELTAS_DIR, EXECUTOR_OUTPUTS_DIR, REFLECTIONS_DIR } from '../constants.js';
5
+ import { ACE_DIR, BRV_DIR, BULLETS_DIR, DEFAULT_BRANCH, DELTAS_DIR, EXECUTOR_OUTPUTS_DIR, PLAYBOOK_FILE, REFLECTIONS_DIR, } from '../constants.js';
6
6
  import { FilePlaybookStore } from '../infra/ace/file-playbook-store.js';
7
7
  import { ProjectConfigStore } from '../infra/config/file-config-store.js';
8
8
  import { HttpMemoryStorageService } from '../infra/memory/http-memory-storage-service.js';
@@ -32,7 +32,7 @@ export default class Push extends Command {
32
32
  async checkProjectInit(projectConfigStore) {
33
33
  const projectConfig = await projectConfigStore.read();
34
34
  if (projectConfig === undefined) {
35
- this.error('Project not initialized. Run "br init" first.');
35
+ this.error('Project not initialized. Run "brv init" first.');
36
36
  }
37
37
  return projectConfig;
38
38
  }
@@ -44,7 +44,7 @@ export default class Push extends Command {
44
44
  ux.action.stop('✓');
45
45
  // Clean executor outputs
46
46
  const baseDir = process.cwd();
47
- const aceDir = join(baseDir, BR_DIR, ACE_DIR);
47
+ const aceDir = join(baseDir, BRV_DIR, ACE_DIR);
48
48
  const executorOutputsDir = join(aceDir, EXECUTOR_OUTPUTS_DIR);
49
49
  const reflectionsDir = join(aceDir, REFLECTIONS_DIR);
50
50
  const deltasDir = join(aceDir, DELTAS_DIR);
@@ -67,10 +67,10 @@ export default class Push extends Command {
67
67
  this.log(` Files to upload: ${fileCount}`);
68
68
  this.log('\nAfter successful push, these local files will be cleaned up:');
69
69
  this.log(' - Playbook content');
70
- this.log(' - Bullet files (.br/ace/bullets/)');
71
- this.log(' - Executor outputs (.br/ace/executor-outputs/)');
72
- this.log(' - Reflections (.br/ace/reflections/)');
73
- this.log(' - Deltas (.br/ace/deltas/)');
70
+ this.log(` - Bullet files (${BRV_DIR}/${ACE_DIR}/${BULLETS_DIR}/)`);
71
+ this.log(` - Executor outputs (${BRV_DIR}/${ACE_DIR}/${EXECUTOR_OUTPUTS_DIR}/)`);
72
+ this.log(` - Reflections (${BRV_DIR}/${ACE_DIR}/${REFLECTIONS_DIR}/)`);
73
+ this.log(` - Deltas (${BRV_DIR}/${ACE_DIR}/${DELTAS_DIR}/)`);
74
74
  return confirm({
75
75
  default: false,
76
76
  message: 'Push to ByteRover and clean up local files?',
@@ -107,7 +107,7 @@ export default class Push extends Command {
107
107
  const response = await memoryService.getPresignedUrls({
108
108
  accessToken: token.accessToken,
109
109
  branch: flags.branch,
110
- fileNames: ['playbook.json'],
110
+ fileNames: [`${PLAYBOOK_FILE}`],
111
111
  sessionKey: token.sessionKey,
112
112
  spaceId: projectConfig.spaceId,
113
113
  teamId: projectConfig.teamId,
@@ -164,17 +164,17 @@ export default class Push extends Command {
164
164
  async validateAuth(tokenStore) {
165
165
  const token = await tokenStore.load();
166
166
  if (token === undefined) {
167
- this.error('Not authenticated. Run "br login" first.');
167
+ this.error('Not authenticated. Run "brv login" first.');
168
168
  }
169
169
  if (!token.isValid()) {
170
- this.error('Authentication token expired. Run "br login" again.');
170
+ this.error('Authentication token expired. Run "brv login" again.');
171
171
  }
172
172
  return token;
173
173
  }
174
174
  async verifyPlaybookExists(playbookStore) {
175
175
  const playbookExists = await playbookStore.exists();
176
176
  if (!playbookExists) {
177
- this.error('Playbook not found. Run "br init" to create one.');
177
+ this.error('Playbook not found. Run "brv init" to create one.');
178
178
  }
179
179
  }
180
180
  }
@@ -1,6 +1,6 @@
1
1
  import { Command } from '@oclif/core';
2
2
  import type { AuthToken } from '../core/domain/entities/auth-token.js';
3
- import type { BrConfig } from '../core/domain/entities/br-config.js';
3
+ import type { BrvConfig } from '../core/domain/entities/brv-config.js';
4
4
  import type { IMemoryRetrievalService } from '../core/interfaces/i-memory-retrieval-service.js';
5
5
  import type { IProjectConfigStore } from '../core/interfaces/i-project-config-store.js';
6
6
  import type { ITokenStore } from '../core/interfaces/i-token-store.js';
@@ -13,7 +13,7 @@ export default class Retrieve extends Command {
13
13
  'node-keys': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
14
14
  query: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
15
15
  };
16
- protected checkProjectInt(projectConfigStore: IProjectConfigStore): Promise<BrConfig>;
16
+ protected checkProjectInt(projectConfigStore: IProjectConfigStore): Promise<BrvConfig>;
17
17
  protected createServices(): {
18
18
  memoryService: IMemoryRetrievalService;
19
19
  projectConfigStore: IProjectConfigStore;
@@ -31,7 +31,7 @@ export default class Retrieve extends Command {
31
31
  async checkProjectInt(projectConfigStore) {
32
32
  const isInitialized = await projectConfigStore.exists();
33
33
  if (!isInitialized) {
34
- this.error('Project is not initialized. Please run "br init" first.');
34
+ this.error('Project is not initialized. Please run "brv init" first.');
35
35
  }
36
36
  const config = await projectConfigStore.read();
37
37
  if (!config) {
@@ -82,10 +82,10 @@ export default class Retrieve extends Command {
82
82
  async validateAuth(tokenStore) {
83
83
  const token = await tokenStore.load();
84
84
  if (token === undefined) {
85
- this.error('Not authenticated. Please run "br auth login" first.');
85
+ this.error('Not authenticated. Please run "brv login" first.');
86
86
  }
87
87
  if (!token.isValid()) {
88
- this.error('Authentication token expired. Please run "br auth login" again.');
88
+ this.error('Authentication token expired. Please run "brv login" again.');
89
89
  }
90
90
  return token;
91
91
  }