Skip to content

Commit ddbf1e2

Browse files
authored
Merge pull request #15 from cardstack/pr-review/command-restructure-and-defaults
Restructure CLI commands, add default workspace root, update docs
2 parents 435b822 + 357fa77 commit ddbf1e2

18 files changed

Lines changed: 743 additions & 242 deletions

.claude/CLAUDE.md

Lines changed: 35 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -80,13 +80,13 @@ BOXEL_PASSWORD="password" npx boxel profile add -u @username:boxel.ai -n "My Pro
8080
8181
### Step 3: Verify & List Workspaces
8282
```bash
83-
npx boxel list
83+
npx boxel workspace-list
8484
```
8585

86-
### Step 4: First Sync
87-
Help them sync their first workspace:
86+
### Step 4: First Pull
87+
Help them pull their first workspace (defaults to `~/boxel-workspaces/`):
8888
```bash
89-
npx boxel sync @username/workspace ./workspace-name
89+
npx boxel pull https://app.boxel.ai/username/workspace/
9090
```
9191

9292
### Switching Between Profiles
@@ -99,33 +99,32 @@ npx boxel profile switch username # Switch by partial match
9999

100100
## Local Workspace Organization
101101

102-
When syncing multiple workspaces locally, organize them by **domain/username/realm** to mirror the Matrix ID structure (`@username:domain`):
102+
The CLI stores synced workspaces under `~/boxel-workspaces/` by default, organized by **realm-server-hostname/username/realm**:
103103

104104
```
105-
boxel-workspaces/
106-
├── boxel.ai/ # Production domain
107-
│ └── acme-corp/ # Username
108-
│ ├── personal/ # Realm
105+
~/boxel-workspaces/ # Default root (all platforms)
106+
├── app.boxel.ai/ # Production realm server
107+
│ └── acme-corp/
108+
│ ├── personal/
109109
│ ├── project-atlas/
110110
│ └── inventory-tracker/
111-
└── stack.cards/ # Staging domain
111+
└── realms-staging.stack.cards/ # Staging realm server
112112
└── acme-corp/
113113
└── sandbox/
114114
```
115115

116+
**Default root:** `~/boxel-workspaces/` on macOS, Linux, and Windows. Override by passing an explicit local path to `pull` or `sync`.
117+
116118
**Benefits:**
117-
- Clear separation between production and staging environments
118-
- Matches the `@username:domain` profile ID format
119-
- Easy to identify which profile/environment a workspace belongs to
120-
- Supports multiple users on the same machine
119+
- Full realm server hostname as folder name eliminates staging/production ambiguity
120+
- Each environment is clearly identifiable by its path
121+
- No collision between realms on different servers
121122

122-
**First-time sync to this structure:**
123+
**First-time sync:**
123124
```bash
124-
# Production workspace
125-
boxel pull https://app.boxel.ai/acme-corp/project-atlas/ ./boxel-workspaces/boxel.ai/acme-corp/project-atlas
126-
127-
# Staging workspace
128-
boxel pull https://realms-staging.stack.cards/acme-corp/sandbox/ ./boxel-workspaces/stack.cards/acme-corp/sandbox
125+
# The CLI automatically places workspaces under ~/boxel-workspaces/
126+
boxel pull https://app.boxel.ai/acme-corp/project-atlas/
127+
boxel pull https://realms-staging.stack.cards/acme-corp/sandbox/
129128
```
130129

131130
---
@@ -160,8 +159,8 @@ Context-aware bidirectional sync:
160159
### `/repair` - Realm Metadata/Card Repair
161160
Use when workspaces show missing icon/background, wrong display name, or fail to open due to broken `index.json`/`cards-grid.json` links.
162161
- Read `.claude/commands/repair.md` for the step-by-step repair flow.
163-
- `boxel repair-realm <url>` repairs one realm
164-
- `boxel repair-realms` repairs all owned realms (excluding `personal` by default)
162+
- `boxel doctor repair-realm <url>` repairs one realm
163+
- `boxel doctor repair-realms` repairs all owned realms (excluding `personal` by default)
165164
- Also reconciles Matrix account data (`app.boxel.realms`) unless disabled
166165

167166
---
@@ -252,12 +251,12 @@ boxel stop # Stop all running watch (⇅) and track (⇆)
252251
### Realms (Multi-Realm Configuration)
253252
```bash
254253
boxel realms # List configured realms
255-
boxel realms --init # Create .boxel-workspaces.json
256-
boxel realms --add ./path # Add a realm
257-
boxel realms --add ./code --purpose "Card definitions" --patterns "*.gts" --default
258-
boxel realms --add ./data --purpose "Data instances" --card-types "BlogPost,Product"
259-
boxel realms --llm # Output LLM guidance for file placement
260-
boxel realms --remove ./path # Remove a realm
254+
boxel realms init # Create .boxel-workspaces.json
255+
boxel realms add ./path # Add a realm
256+
boxel realms add ./code --purpose "Card definitions" --patterns "*.gts" --default
257+
boxel realms add ./data --purpose "Data instances" --card-types "BlogPost,Product"
258+
boxel realms llm # Output LLM guidance for file placement
259+
boxel realms remove ./path # Remove a realm
261260
```
262261

263262
**File placement guidance:** The `--llm` output tells Claude which realm to use for different file types and card types.
@@ -299,11 +298,11 @@ boxel profile migrate # Migrate from old .env file
299298

300299
### Other
301300
```bash
302-
boxel list # List workspaces
301+
boxel workspace-list # List workspaces
303302
boxel create endpoint "Name" # Create workspace
304-
boxel consolidate-workspaces . # Move legacy local dirs into domain/owner/realm
305-
boxel repair-realm <url> # Repair one realm metadata/starter cards
306-
boxel repair-realms # Batch repair all owned realms
303+
boxel doctor consolidate-workspaces # Fix workspace dirs (defaults to ~/boxel-workspaces/)
304+
boxel doctor repair-realm <url> # Repair one realm metadata/starter cards
305+
boxel doctor repair-realms # Batch repair all owned realms
307306
boxel pull <url> ./local # One-way pull
308307
boxel push ./local <url> # One-way push
309308
```
@@ -419,14 +418,14 @@ When working with multiple realms (e.g., code + data separation):
419418

420419
```bash
421420
# Configure realms once
422-
boxel realms --add ./code-realm --purpose "Card definitions" --patterns "*.gts" --default
423-
boxel realms --add ./data-realm --purpose "Content instances" --card-types "BlogPost,Product"
421+
boxel realms add ./code-realm --purpose "Card definitions" --patterns "*.gts" --default
422+
boxel realms add ./data-realm --purpose "Content instances" --card-types "BlogPost,Product"
424423

425424
# Watch all configured realms
426425
boxel watch
427426

428427
# Check where to put a new file
429-
boxel realms --llm
428+
boxel realms llm
430429
```
431430

432431
**File placement heuristics:**
@@ -675,7 +674,7 @@ The `/_atomic` endpoint supports batch file operations that succeed or fail atom
675674
- For staging: ensure profile uses `@username:stack.cards`
676675

677676
### "No workspace found"
678-
- Run `boxel list` to see workspaces
677+
- Run `boxel workspace-list` to see workspaces
679678
- Use full URL for first sync
680679
- Ensure correct profile is active for the environment
681680

.claude/commands/repair.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,18 @@ Use this workflow when a workspace has any of these symptoms:
1010

1111
```bash
1212
# Inspect one realm without mutating
13-
boxel repair-realm <workspace-url> --dry-run
13+
boxel doctor repair-realm <workspace-url> --dry-run
1414

1515
# Repair one realm
16-
boxel repair-realm <workspace-url>
16+
boxel doctor repair-realm <workspace-url>
1717

1818
# Repair all realms owned by active profile user
19-
boxel repair-realms
19+
boxel doctor repair-realms
2020
```
2121

2222
## Behavior
2323

24-
`repair-realm` and `repair-realms` perform these repairs:
24+
`doctor repair-realm` and `doctor repair-realms` perform these repairs:
2525
- `.realm.json`: normalize `name`, `iconURL`, `backgroundURL`
2626
- `index.json`: ensure `relationships.cardsGrid.links.self` = `./cards-grid`
2727
- `cards-grid.json`: restore default cards-grid card if missing/corrupt

.claude/commands/setup.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,13 @@ BOXEL_PASSWORD="password" npx boxel profile add -u @username:stack.cards -n "Sta
5252
5353
### 3. Verify
5454
```bash
55-
npx boxel list
55+
npx boxel workspace-list
5656
```
5757

5858
### 4. First Sync
59-
Help them sync a workspace:
59+
Help them pull a workspace (defaults to `~/boxel-workspaces/`):
6060
```bash
61-
npx boxel sync @username/workspace ./workspace-name
61+
npx boxel pull https://app.boxel.ai/username/workspace/
6262
```
6363

6464
## Profile Management
@@ -81,8 +81,8 @@ npx boxel profile migrate
8181
## Success Message
8282
```
8383
Setup complete! You can now:
84-
- `npx boxel list` - See your workspaces
85-
- `npx boxel sync @username/workspace` - Sync a workspace
84+
- `npx boxel workspace-list` - See your workspaces
85+
- `npx boxel pull <url>` - Pull a workspace to ~/boxel-workspaces/
8686
- `npx boxel watch .` - Monitor for changes
8787
- `npx boxel history .` - View/restore checkpoints
8888

AGENTS.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ Trigger examples:
3838
- `sync`: bidirectional conflict resolution
3939
- `track`: local file watching with auto-checkpoints (use `--push` for real-time server sync)
4040
- `watch`: remote change watching (pulls server changes)
41-
- `repair-realm`: repair one realm metadata + starter cards + optional Matrix reconciliation
42-
- `repair-realms`: batch repair all owned realms and reconcile Matrix realm list
41+
- `doctor repair-realm`: repair one realm metadata + starter cards + optional Matrix reconciliation
42+
- `doctor repair-realms`: batch repair all owned realms and reconcile Matrix realm list
4343

4444
After local edits tracked with `track`, push to server with:
4545
- `boxel sync . --prefer-local`
@@ -49,16 +49,16 @@ After local edits tracked with `track`, push to server with:
4949
If user has no profile configured:
5050
1. `npx boxel profile`
5151
2. `npx boxel profile add` (interactive preferred)
52-
3. `npx boxel list`
53-
4. First sync/pull into local workspace
52+
3. `npx boxel workspace-list`
53+
4. First sync/pull into local workspace (default root: `~/boxel-workspaces/`)
5454

5555
Security note:
5656
- Prefer interactive password entry or `BOXEL_PASSWORD` env var.
5757
- Avoid plain `-p` password usage in shell history.
5858

5959
## Multi-Realm Guidance
60-
- Configure realms with `boxel realms --add ...`
61-
- Use `boxel realms --llm` for file-placement guidance.
60+
- Configure realms with `boxel realms add ...`
61+
- Use `boxel realms llm` for file-placement guidance.
6262
- Heuristic:
6363
- `.gts` -> code realm (`*.gts` pattern)
6464
- instances -> realm mapped for card type

CHANGELOG.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,39 @@
22

33
All notable changes to `boxel-cli`. Format loosely follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versions follow [SemVer](https://semver.org/spec/v2.0.0.html).
44

5+
## 1.1.0 — 2026-04-20
6+
7+
Command-surface restructure plus the two regressions @backspace caught in his PR #15 review. Minor version bump because command names and default paths change in user-visible ways.
8+
9+
### New
10+
11+
- **`boxel doctor` parent command** groups maintenance tasks: `doctor repair-realm`, `doctor repair-realms`, `doctor consolidate-workspaces`, `doctor force-reindex`. Keeps the root command tree focused on day-to-day sync operations.
12+
- **`boxel workspace-list`** (formerly `boxel list`) lists Boxel workspaces the active profile can access. `boxel list` stays as a shorthand alias.
13+
- **`boxel realms <subcommand>`** — positional subcommands replace the old flag-based interface. `boxel realms add ./path`, `realms remove ./path`, `realms init`, `realms list`, `realms llm`. `boxel realms` with no args shows the list.
14+
- **Default workspace root at `~/boxel-workspaces/<domain>/<owner>/<realm>/`.** `boxel pull <url>` now works without a local-dir argument — it derives a canonical path from the URL and creates the directory. `doctor consolidate-workspaces` scans `~/boxel-workspaces/` by default.
15+
- Terminology discipline across docs and help text: **realm** = the server-side thing a URL points at; **workspace** = the Matrix-level organizational unit visible in the Boxel UI.
16+
17+
### Fixed
18+
19+
- **`--fix-index` was on by default, opposite of what PR #15 advertised.** Commander's `.option('--no-fix-index')` makes the underlying boolean default to `true`. Running `boxel doctor repair-realm <url>` silently rewrote `index.json` / `cards-grid.json` even on realms with customized index files (caught by @backspace on the Checkly-prerendered realm that lost its custom index). Flipped to `.option('--fix-index')` — now opt-in. Added regression tests that exercise commander parsing directly.
20+
- **Pull path extraction broke for published realms without an owner segment.** `https://realms-staging.stack.cards/boxel-homepage/` (1 segment) wrote to `.../boxel-homepage/boxel-homepage` (duplicated); `https://gabbro.staging.boxel.build/` (0 segments) wrote to `.../unknown-owner/workspace` (invented placeholders). The layout now adapts to the URL: 0 segments → `<host>/`, 1 segment → `<host>/<realm>/`, 2+ segments → `<host>/<owner>/<realm>/` (unchanged). `findManifestPaths()` walks 2-level layouts so legacy-path detection still works after the shape change.
21+
- **`track --push` showed "Push failed" with no detail on batch errors.** Now surfaces the underlying errors (e.g. `HTTP 413: Payload Too Large`) so you can tell a transient server problem from a size limit.
22+
- **`boxel realms remove <path>`** used to succeed silently on a path not in the config. Now errors with a clear "realm not found" message.
23+
- **Realm folder naming** now uses the full realm server hostname (no domain normalization). Prevents staging/production collisions when two realms share the owner/realm parts.
24+
25+
### Changed (breaking)
26+
27+
- **`boxel realms --add/--init/--remove/--llm` flag form removed.** PR #15 kept these as hidden aliases; per @backspace's review ("we might as well make a clean break as this is not officially released") they're gone. Use positional subcommands.
28+
- **`boxel doctor force-reindex`** replaces the top-level `touch` command semantics when used as a diagnostic; the plain `touch` command stays for everyday single-file re-indexing.
29+
30+
### For contributors
31+
32+
- New `test/commands/repair.test.ts` regression tests for commander flag parsing — catches the `--no-fix-index` default-inversion bug at the commander layer (the previous tests only checked the handler's `options.fixIndex ?? false` fallback, which ran after commander had already set the bad default).
33+
- New `test/lib/workspace-paths.test.ts` cases for 0-segment and 1-segment URLs.
34+
- Removed dead `realmsCommand()` legacy dispatcher and `RealmsOptions` interface from `src/commands/realms.ts`.
35+
36+
---
37+
538
## 1.0.2 — 2026-04-20
639

740
Low-risk ports from `@cardstack/boxel-cli` (the official package in the Boxel monorepo). No user-visible command changes; architectural alignment + mild speedups.

0 commit comments

Comments
 (0)