Skip to content
Merged
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
39 changes: 0 additions & 39 deletions openspec/changes/add-config-command/proposal.md

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
## Context

The `global-config` spec defines how OpenSpec reads/writes `config.json`, but users currently must edit it by hand. This command provides a CLI interface to that config.

## Goals / Non-Goals

**Goals:**
- Provide a discoverable CLI for config management
- Support scripting with machine-readable output
- Validate config changes with zod schema
- Handle nested keys gracefully

**Non-Goals:**
- Project-local config (reserved for future via `--scope` flag)
- Complex queries (JSONPath, filtering)
- Config file format migration

## Decisions

### Key Naming: camelCase with Dot Notation

**Decision:** Keys use camelCase matching the JSON structure, with dot notation for nesting.

**Rationale:**
- Matches the actual JSON keys (no translation layer)
- Dot notation is intuitive and widely used (lodash, jq, kubectl)
- Avoids complexity of supporting multiple casing styles

**Examples:**
```bash
openspec config get featureFlags # Returns object
openspec config get featureFlags.experimental # Returns nested value
openspec config set featureFlags.newFlag true
```

### Type Coercion: Auto-detect with `--string` Override

**Decision:** Parse values automatically; provide `--string` flag to force string storage.

**Rationale:**
- Most intuitive for common cases (`true`, `false`, `123`)
- Explicit override for edge cases (storing literal string "true")
- Follows npm/yarn config patterns

**Coercion rules:**
| Input | Stored As |
|-------|-----------|
| `true`, `false` | boolean |
| Numeric string (`123`, `3.14`) | number |
| Everything else | string |
| Any value with `--string` | string |

### Output Format: Raw by Default

**Decision:** `get` prints raw value only. `list` prints YAML-like format by default, JSON with `--json`.

**Rationale:**
- Raw output enables piping: `VAR=$(openspec config get key)`
- YAML-like is human-readable for inspection
- JSON for automation/scripting

### Schema Validation: Zod with Unknown Field Passthrough

**Decision:** Use zod for validation but preserve unknown fields per `global-config` spec.

**Rationale:**
- Type safety for known fields
- Forward compatibility (old CLI doesn't break new config)
- Follows existing `global-config` spec requirement

### Reserved Flag: `--scope`

**Decision:** Reserve `--scope global|project` but only implement `global` initially.

**Rationale:**
- Avoids breaking change if project-local config is added later
- Clear error message if someone tries `--scope project`

## Risks / Trade-offs

| Risk | Mitigation |
|------|------------|
| Dot notation conflicts with keys containing dots | Rare in practice; document limitation |
| Type coercion surprises | `--string` escape hatch; document rules |
| $EDITOR not set | Check and provide helpful error message |

## Open Questions

None - design is straightforward.
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
## Why

Users need a way to view and modify their global OpenSpec settings without manually editing JSON files. The `global-config` spec provides the foundation, but there's no user-facing interface to interact with the config. A dedicated `openspec config` command provides discoverability and ease of use.

## What Changes

Add `openspec config` subcommand with the following operations:

```bash
openspec config path # Show config file location
openspec config list [--json] # Show all current settings
openspec config get <key> # Get a specific value (raw, scriptable)
openspec config set <key> <value> [--string] # Set a value (auto-coerce types)
openspec config unset <key> # Remove a key (revert to default)
openspec config reset --all [-y] # Reset everything to defaults
openspec config edit # Open config in $EDITOR
```

**Key design decisions:**
- **Key naming**: Use camelCase to match JSON structure (e.g., `featureFlags.someFlag`)
- **Nested keys**: Support dot notation for nested access
- **Type coercion**: Auto-detect types by default; `--string` flag forces string storage
- **Scriptable output**: `get` prints raw value only (no labels) for easy piping
- **Zod validation**: Use zod for config schema validation and type safety
- **Future-proofing**: Reserve `--scope global|project` flag for potential project-local config

**Example usage:**
```bash
$ openspec config path
/Users/me/.config/openspec/config.json

$ openspec config list
featureFlags: {}

$ openspec config set featureFlags.enableTelemetry false
Set featureFlags.enableTelemetry = false

$ openspec config get featureFlags.enableTelemetry
false

$ openspec config list --json
{
"featureFlags": {}
}

$ openspec config unset featureFlags.enableTelemetry
Unset featureFlags.enableTelemetry (reverted to default)

$ openspec config edit
# Opens $EDITOR with config.json
```

## Impact

- Affected specs: New `cli-config` capability
- Affected code:
- New `src/commands/config.ts`
- New `src/core/config-schema.ts` (zod schema)
- Update CLI entry point to register config command
- Dependencies: Requires `global-config` spec (already implemented)
Loading
Loading