Skip to content

CS-10630: Reimplement boxel realm remove command#4655

Open
FadhlanR wants to merge 1 commit intomainfrom
cs-10630-reimplement-boxel-realm-remove-command
Open

CS-10630: Reimplement boxel realm remove command#4655
FadhlanR wants to merge 1 commit intomainfrom
cs-10630-reimplement-boxel-realm-remove-command

Conversation

@FadhlanR
Copy link
Copy Markdown
Contributor

@FadhlanR FadhlanR commented May 5, 2026

Summary

  • Port boxel remove from the standalone cardstack/boxel-cli into packages/boxel-cli/src/commands/realm/remove.ts as boxel realm remove <realm-url>.
  • Soft remove only — drops the URL from the active profile's app.boxel.realms Matrix account_data list. Server-side realm files are not touched.
  • New ProfileManager.removeFromUserRealms() + removeRealmFromMatrixAccountData() helper, mirroring the existing add* pair.

Safety

  • TTY confirmation prompt before writing; bypass with -y, --yes.
  • Non-interactive invocation without --yes errors out instead of writing silently.
  • --dry-run previews previousCount -> nextCount without sending a Matrix PUT.
  • removeRealm() returns a structured result on every path (never process.exits), so other commands can call it programmatically.

Linear

CS-10630 — part of Incorporate Boxel CLI to Monorepo.

Test plan

  • pnpm --filter @cardstack/boxel-cli lint:types
  • pnpm --filter @cardstack/boxel-cli lint:js
  • pnpm --filter @cardstack/boxel-cli exec vitest run tests/integration/realm-remove.test.ts (requires Synapse + realm server running locally)
  • Manual TTY: boxel realm remove <url> prompts y/N, writes on y, cancels on N.
  • Manual: boxel realm remove <url> --yes skips the prompt.
  • Manual: boxel realm remove <url> < /dev/null errors out (non-TTY without --yes).
  • Manual: boxel realm remove <url> --dry-run prints the count delta and exits without writing.
  • Manual: after remove, boxel realm list --all-accessible still shows the realm (server files preserved).

🤖 Generated with Claude Code

Soft-removes a realm URL from the active profile's `app.boxel.realms`
Matrix account_data list. Server-side files are untouched.

- New `removeRealm()` programmatic API in commands/realm/remove.ts
  (returns a result object on every code path; never prompts, never
  calls process.exit).
- CLI wrapper with TTY confirmation, `-y/--yes` to skip, and
  `--dry-run` to preview the change.
- `removeRealmFromMatrixAccountData()` helper in lib/auth.ts and
  `ProfileManager.removeFromUserRealms()` for reuse by other commands.
- Integration tests against a real test realm server cover: happy
  path, not-in-list, dry-run, trailing-slash normalization, soft-
  remove (server files preserved), and no-active-profile.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@FadhlanR FadhlanR marked this pull request as ready for review May 5, 2026 13:35
@FadhlanR FadhlanR requested a review from a team May 5, 2026 13:36
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 845a5fc7fc

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +188 to +191
if (!existingRealms.includes(realmUrl)) {
return false;
}
let next = existingRealms.filter((url) => url !== realmUrl);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Normalize stored realm URLs before matching/removing

removeRealm() normalizes URLs with ensureTrailingSlash, but removeRealmFromMatrixAccountData() compares and filters against raw existingRealms values. If account data contains a legacy entry like https://host/realm (no trailing slash), the preview path in realm/remove.ts treats it as present while this function returns false and performs no PUT, so boxel realm remove fails with “Removal did not complete.” for valid realms. Normalize existingRealms during membership/removal (or remove both slash variants) so runtime behavior matches the command’s normalization logic.

Useful? React with 👍 / 👎.

@habdelra
Copy link
Copy Markdown
Contributor

habdelra commented May 5, 2026

so this seems very subtle--its doesn't actually remove the realm, it just unlinks the realm from the user's matrix data. if the user tries to make a new realm with the same name they will get an error that this realm already exists--which is probably confusing since they thought they removed it. is it really the intent that we are just "unlinking" the realm here instead of removing it? if so should we name it something that makes that more clear?

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR ports the standalone CLI “remove realm” behavior into the monorepo as boxel realm remove <realm-url>, implementing a soft remove that updates the active profile’s app.boxel.realms Matrix account_data list (without deleting server-side realm files).

Changes:

  • Added a new boxel realm remove command with --dry-run and --yes support plus a programmatic removeRealm() API.
  • Introduced ProfileManager.removeFromUserRealms() and removeRealmFromMatrixAccountData() to mirror existing “add realm” helpers.
  • Added an integration test suite covering removal, dry-run behavior, normalization, and “soft remove” semantics.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
packages/boxel-cli/tests/integration/realm-remove.test.ts New integration coverage for removing realms from the user list and verifying server realms remain accessible.
packages/boxel-cli/src/lib/profile-manager.ts Adds removeFromUserRealms() wrapper to update Matrix account_data via the auth helper.
packages/boxel-cli/src/lib/auth.ts Adds removeRealmFromMatrixAccountData() to remove a realm URL from app.boxel.realms.
packages/boxel-cli/src/commands/realm/remove.ts New command implementation + programmatic removeRealm() API with confirmation/dry-run flows.
packages/boxel-cli/src/commands/realm/index.ts Registers the new remove subcommand under boxel realm.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +186 to +191
let existingRealms = await getUserRealmsFromMatrixAccountData(matrixAuth);

if (!existingRealms.includes(realmUrl)) {
return false;
}
let next = existingRealms.filter((url) => url !== realmUrl);
Comment on lines +72 to +95
let normalized = existing.map(ensureTrailingSlash);
let previousCount = normalized.length;

if (!normalized.includes(realmUrl)) {
return {
realmUrl,
removed: false,
previousCount,
nextCount: previousCount,
notInList: true,
error: 'Realm is not in app.boxel.realms. Nothing to remove.',
};
}

let nextCount = previousCount - 1;

if (options.dryRun) {
return { realmUrl, removed: false, previousCount, nextCount };
}

try {
let removed = await pm.removeFromUserRealms(realmUrl);
return { realmUrl, removed, previousCount, nextCount };
} catch (err) {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants