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
32 changes: 28 additions & 4 deletions docs/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,12 @@ openspec/

### `openspec update`

Update OpenSpec instruction files after upgrading the CLI. Re-generates AI tool configuration files using your current global profile, selected workflows, and delivery mode.
Update OpenSpec instruction files after upgrading the CLI. Re-generates AI tool configuration files using effective profile settings resolved by precedence:

- CLI scope override (`--scope`) when provided
- Project config (`openspec/config.yaml` or `openspec/config.yml`)
- User config
- Built-in defaults (`profile: core`, `delivery: both`)

```
openspec update [path] [options]
Expand All @@ -155,13 +160,20 @@ openspec update [path] [options]
| Option | Description |
|--------|-------------|
| `--force` | Force update even when files are up to date |
| `--scope <scope>` | Resolution scope override: `user` or `project` |

**Example:**

```bash
# Update instruction files after npm upgrade
npm update @fission-ai/openspec
openspec update

# Force user-only profile resolution for this run
openspec update --scope user

# Force project-prioritized resolution for this run
openspec update --scope project
```

---
Expand Down Expand Up @@ -933,7 +945,10 @@ spec-driven resolves from: package

### `openspec config`

View and modify global OpenSpec configuration.
View and modify OpenSpec configuration.

Default scope is `user`. Use `--scope project` to read/write project-scoped profile settings (`profile`, `delivery`, `workflows`) in `openspec/config.yaml` (or existing `config.yml`).
If you already use user-level config only, no migration is required: existing commands keep user-level behavior unless you explicitly opt into `--scope project`.

```
openspec config <subcommand> [options]
Expand Down Expand Up @@ -984,6 +999,15 @@ openspec config profile

# Fast preset: switch workflows to core (keeps delivery mode)
openspec config profile core

# Set project-scoped profile override
openspec config --scope project set profile custom

# Read project-scoped profile key
openspec config --scope project get profile

# Run profile wizard against project scope
openspec config --scope project profile
```

`openspec config profile` starts with a current-state summary, then lets you choose:
Expand All @@ -993,9 +1017,9 @@ openspec config profile core
- Keep current settings (exit)

If you keep current settings, no changes are written and no update prompt is shown.
If there are no config changes but the current project or workspace files are out of sync with your global profile/delivery, OpenSpec will show a warning and suggest `openspec update` for repo-local projects or `openspec workspace update` for workspace-local skills.
If there are no config changes but the current project or workspace files are out of sync with the active scope settings, OpenSpec will show a warning and suggest `openspec update` for repo-local projects or `openspec workspace update` for workspace-local skills.
Pressing `Ctrl+C` also cancels the flow cleanly (no stack trace) and exits with code `130`.
In the workflow checklist, `[x]` means the workflow is selected in global config. To apply those selections to project files, run `openspec update` (or choose `Apply changes to this project now?` when prompted inside a project). From inside a workspace, use `openspec workspace update` to refresh workspace-local skills; this remains skills-only and does not generate workspace slash commands.
In the workflow checklist, `[x]` means the workflow is selected in the effective scope state for this command. To apply those selections to project files, run `openspec update` (or choose `Apply changes to this project now?` when prompted inside a project). From inside a workspace, use `openspec workspace update` to refresh workspace-local skills; this remains skills-only and does not generate workspace slash commands.

**Interactive examples:**

Expand Down
21 changes: 21 additions & 0 deletions docs/customization.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ The `openspec/config.yaml` file is the easiest way to customize OpenSpec for you
- **Set a default schema** - Skip `--schema` on every command
- **Inject project context** - AI sees your tech stack, conventions, etc.
- **Add per-artifact rules** - Custom rules for specific artifacts
- **Override profile settings per project** - Set `profile`, `delivery`, and `workflows` locally

### Quick Setup

Expand All @@ -30,6 +31,15 @@ This walks you through creating a config interactively. Or create one manually:
# openspec/config.yaml
schema: spec-driven

# Optional: project-scoped profile settings
profile: custom
delivery: both
workflows:
- propose
- explore
- apply
- archive

context: |
Tech stack: TypeScript, React, Node.js, PostgreSQL
API style: RESTful, documented in docs/api.md
Expand Down Expand Up @@ -80,6 +90,17 @@ Tech stack: TypeScript, React, Node.js, PostgreSQL
- **Context** appears in ALL artifacts
- **Rules** ONLY appear for the matching artifact

### Profile Resolution Order

For profile-driven behavior (for example `openspec update`), OpenSpec resolves settings in this order:

1. CLI scope override (if `--scope` is provided)
2. Project config (`openspec/config.yaml` or existing `openspec/config.yml`)
3. User-level config (`openspec config ...`)
4. Defaults (`profile: core`, `delivery: both`, profile-derived workflows)

This is key-by-key fallback, so partial project settings are valid. Example: if project config only sets `profile`, `delivery` can still come from user-level config.

### Schema Resolution Order

When OpenSpec needs a schema, it checks in this order:
Expand Down
12 changes: 10 additions & 2 deletions src/cli/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,16 +162,24 @@ program
.command('update [path]')
.description('Update OpenSpec instruction files')
.option('--force', 'Force update even when tools are up to date')
.action(async (targetPath = '.', options?: { force?: boolean }) => {
.option('--scope <scope>', 'Profile resolution scope override (user or project)')
.action(async (targetPath = '.', options?: { force?: boolean; scope?: string }) => {
try {
if (options?.scope && options.scope !== 'user' && options.scope !== 'project') {
throw new Error(`Invalid scope "${options.scope}". Use "user" or "project".`);
}

const resolvedPath = path.resolve(targetPath);
const workspaceRoot = await findWorkspaceRoot(resolvedPath);
if (workspaceRoot) {
await runWorkspaceUpdateForRoot(workspaceRoot, { force: options?.force });
return;
}

const updateCommand = new UpdateCommand({ force: options?.force });
const updateCommand = new UpdateCommand({
force: options?.force,
scope: options?.scope as 'user' | 'project' | undefined,
});
await updateCommand.execute(resolvedPath);
} catch (error) {
console.log(); // Empty line for spacing
Expand Down
Loading