Skip to content

feat(stores): set one default store for every repo on your machine#1363

Open
clay-good wants to merge 1 commit into
mainfrom
feat/global-default-store
Open

feat(stores): set one default store for every repo on your machine#1363
clay-good wants to merge 1 commit into
mainfrom
feat/global-default-store

Conversation

@clay-good

@clay-good clay-good commented Jul 15, 2026

Copy link
Copy Markdown
Collaborator

Closes #1359.

What was missing

Stores let many code repos share one planning repo, but there was no machine-level default. To use a store without typing --store on every command, you had to add store: <id> to every repo's openspec/config.yaml. No global equivalent existed.

What it does

Adds defaultStore to the global config. Set it once:

openspec config set defaultStore team-plans

Now any command run outside a planning root — with no --store and no project pointer — resolves to that store. It's the last step in root resolution, so nothing about precedence changes:

1. --store <id>        explicit                → that store
2. nearest openspec/   local planning root     → this repo
3. store: pointer      project config.yaml     → that store
4. defaultStore (NEW)  global config           → that store   ← only new step
5. none of the above   registered stores?      → selection-hint error

Purely additive: --store, a local root, and a project store: pointer all still win. Existing users see no change unless they opt in. A stale or unregistered defaultStore degrades to the existing error, reshaped to say how to fix or clear it.

Proof it works

Real output from the built CLI (bin/openspec.js) against a registered team-plans store, run from a scratch dir with no local root:

Before — no default set:

✖ Error: No OpenSpec root found in the current directory or its ancestors.
  Registered stores: team-plans. Pass --store <id> to use one, or run openspec init.

After openspec config set defaultStore team-plans:

Using OpenSpec root: team-plans (/private/var/.../team-plans)
No active changes found.

Stale default (unregistered id):

✖ Error: Global defaultStore 'ghost-plans': Unknown store 'ghost-plans'. No stores are registered.
  Fix: Register the store (openspec store register <path> --id ghost-plans)
       or clear the stale global default (openspec config unset defaultStore).

config get/unset defaultStore round-trip; unsetting reverts to the selection-hint error.

Tests

  • test/core/root-selection.test.ts — 6 new cases: resolves the default; local root, project pointer, and --store each win over it; stale-default degrade error; falls through to the hint when unset. Harness now pins XDG_CONFIG_HOME so no test reads the developer's real config.
  • test/commands/config.test.tsset/get/unset defaultStore round-trip + key validation (accepts defaultStore, rejects nested keys).

Full suite green except the 17 pre-existing environment-only zsh-installer failures (oh-my-zsh; unaffected by this change).

Scope

config-schema.ts (schema field + known key), global-config.ts (interface field), root-selection.ts (fallback step + degrade helper), docs (stores user guide + cli.md). No changes to store registration, metadata, or existing resolution precedence.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added a machine-wide defaultStore setting for OpenSpec.
    • Commands now use the configured default store when no explicit or local store is available.
    • Added commands to set and clear the default store.
  • Bug Fixes

    • Improved error guidance when the configured default store is unavailable or outdated.
  • Documentation

    • Updated CLI and store guides with configuration instructions and store-resolution precedence.

Adds a machine-level `defaultStore` to the global config. When no --store
flag, local planning root, or project-level `store:` pointer resolves, root
resolution now consults `defaultStore` before erroring — so users who plan
many code repos into one store can set it once instead of editing every
repo's openspec/config.yaml.

Purely additive: existing precedence (--store > local root > project pointer)
is unchanged; the fallback only replaces the failure path. A stale or
unregistered defaultStore degrades to the existing error, reshaped to point
at clearing the global default.

Closes #1359

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@clay-good
clay-good requested a review from TabishB as a code owner July 15, 2026 14:26
@coderabbitai

coderabbitai Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 24b6be5d-ff0e-43c1-b6e4-04f1c4e0e73b

📥 Commits

Reviewing files that changed from the base of the PR and between 0a99f41 and 35c07af.

📒 Files selected for processing (7)
  • docs/cli.md
  • docs/stores-beta/user-guide.md
  • src/core/config-schema.ts
  • src/core/global-config.ts
  • src/core/root-selection.ts
  • test/commands/config.test.ts
  • test/core/root-selection.test.ts

📝 Walkthrough

Walkthrough

Adds defaultStore to global configuration and uses it as a fallback during OpenSpec root resolution. CLI and stores documentation, configuration lifecycle tests, precedence tests, and stale-default error coverage are included.

Changes

Global default store fallback

Layer / File(s) Summary
Configuration contract and CLI lifecycle
src/core/config-schema.ts, src/core/global-config.ts, test/commands/config.test.ts
Adds the optional defaultStore setting, accepts it as a top-level key, and tests setting, reading, unsetting, and nested-key validation.
Root resolution fallback
src/core/root-selection.ts, test/core/root-selection.test.ts
Resolves the configured default after explicit, local, and project-level store sources; tests precedence, stale defaults, and fallback error behavior.
CLI and stores documentation
docs/cli.md, docs/stores-beta/user-guide.md
Documents configuring and clearing defaultStore, its precedence, and behavior when the referenced store is unavailable.

Estimated code review effort: 3 (Moderate) | ~20 minutes

### Sequence Diagram(s)

sequenceDiagram
  participant Command
  participant resolveOpenSpecRoot
  participant GlobalConfig
  participant StoreRegistry
  Command->>resolveOpenSpecRoot: resolve without explicit store
  resolveOpenSpecRoot->>GlobalConfig: read defaultStore
  GlobalConfig-->>resolveOpenSpecRoot: store id
  resolveOpenSpecRoot->>StoreRegistry: resolve default store
  StoreRegistry-->>resolveOpenSpecRoot: root or stale-store error
  resolveOpenSpecRoot-->>Command: selected root or guidance
Loading

Possibly related PRs

Suggested reviewers: tabishb

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and matches the main change: adding a machine-level default store fallback for all repos.
Linked Issues check ✅ Passed The changes add defaultStore to global config, use it as the final root-resolution fallback, and cover config commands, docs, and stale-default handling.
Out of Scope Changes check ✅ Passed The edits stay within the stated scope: config schema, root selection, docs, and tests for the new defaultStore fallback.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/global-default-store

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying openspec-docs with  Cloudflare Pages  Cloudflare Pages

Latest commit: 35c07af
Status: ✅  Deploy successful!
Preview URL: https://3f0b2644.openspec-docs.pages.dev
Branch Preview URL: https://feat-global-default-store.openspec-docs.pages.dev

View logs

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.

Feature: Add defaultStore to global config as machine-level fallback in root resolution

1 participant