Skip to content

Conversation

@TabishB
Copy link
Contributor

@TabishB TabishB commented Dec 21, 2025

Summary

  • Implements openspec config command with full subcommand suite for managing global configuration
  • Adds zod schema validation with forward-compatible passthrough for unknown fields
  • Includes Windows-compatible editor spawning with proper path quoting
  • Adds comprehensive unit and integration tests (60 new tests)

New Subcommands

Subcommand Description
config path Show config file location
config list [--json] Show all current settings
config get <key> Get a specific value (raw output)
config set <key> <value> [--string] Set a value with auto type coercion
config unset <key> Remove a key (revert to default)
config reset --all [-y] Reset configuration to defaults
config edit Open config in $EDITOR/$VISUAL

Key Features

  • Dot notation for nested key access (e.g., featureFlags.someFlag)
  • Auto type coercion: true/false → boolean, numeric strings → number
  • --string flag to force string storage (e.g., store literal "true")
  • Reserved --scope flag for future project-local config support
  • Shell completion registry integration for tab completion

Test plan

  • All 60 new tests pass (npm test)
  • Manual testing of all subcommands
  • Verified zod validation rejects invalid values in featureFlags
  • Tested nested key access with dot notation
  • Tested type coercion edge cases
  • Verified Windows compatibility fix for paths with spaces

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added a new config command with subcommands: path, list, get, set, unset, reset, edit
    • list supports --json; get prints raw/scriptable JSON for objects
    • set supports nested keys via dot notation, auto type coercion and a --string override
    • reset requires --all and supports -y to skip confirmation
    • edit opens the config in the user's editor
  • Documentation

    • Added detailed CLI config spec and design notes
  • Tests

    • New tests covering config commands, schema, and completions

✏️ Tip: You can customize this high-level summary in your review settings.

…ement

Implements the `openspec config` command with subcommands:
- `path`: Show config file location
- `list [--json]`: Show all current settings
- `get <key>`: Get a specific value (raw output for scripting)
- `set <key> <value> [--string]`: Set a value with auto type coercion
- `unset <key>`: Remove a key (revert to default)
- `reset --all [-y]`: Reset configuration to defaults
- `edit`: Open config in $EDITOR/$VISUAL

Key features:
- Dot notation for nested key access (e.g., featureFlags.someFlag)
- Auto type coercion (true/false → boolean, numbers → number)
- --string flag to force string storage
- Zod schema validation with unknown field passthrough
- Reserved --scope flag for future project-local config
- Windows-compatible editor spawning with proper path quoting
- Shell completion registry integration
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 21, 2025

Walkthrough

Adds a new "config" CLI command with subcommands (path, list, get, set, unset, reset, edit), a Zod-backed global config schema and utilities, CLI wiring and completion registry entries, tests for command behavior and schema utilities, and design/spec documentation for the feature.

Changes

Cohort / File(s) Summary
Config core & schema
src/core/config-schema.ts
Adds Zod-based GlobalConfigSchema and DEFAULT_CONFIG, utilities for nested-dot access (get/set/delete), value coercion, YAML-like formatting, key-path validation, and config validation with error aggregation.
Config CLI implementation
src/commands/config.ts
New registerConfigCommand(program) registering config with subcommands: path, list (--json), get, set (--string), unset, reset (--all, -y), and edit; includes preAction global-scope enforcement, validation, safe mutation, editor spawn, and user feedback/error handling.
CLI entrypoint integration
src/cli/index.ts
Imports and registers registerConfigCommand(program) to wire the new config command into the CLI lifecycle.
Shell completion registry
src/core/completions/command-registry.ts
Adds a config top-level command entry with metadata for all subcommands and flags to the command registry used for completions.
Integration tests
test/commands/config.test.ts
Adds tests for global config path resolution, save/load behavior, defaults and unknown-field preservation, invalid JSON handling, and asserts presence and flags of all config subcommands in the completion registry.
Unit tests for schema
test/core/config-schema.test.ts
Adds comprehensive unit tests for nested accessors, set/delete semantics, coercion rules, YAML formatting, and schema validation scenarios and edge cases.
Design / spec / proposal / tasks
openspec/specs/cli-config/spec.md, openspec/changes/archive/2025-12-21-add-config-command/{proposal.md,design.md,tasks.md}, openspec/changes/add-config-command/proposal.md
Adds spec, proposal, design, and task documents describing CLI behavior, design decisions (camelCase, dot notation, coercion, output modes), validation rules, and implementation/testing tasks.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Focus areas:
    • src/core/config-schema.ts: nested get/set/delete correctness, edge cases (nulls/primitives), coercion rules, and Zod schema passthrough/validation messaging.
    • src/commands/config.ts: correctness of each subcommand (especially set, unset, reset, edit), safe mutation and save flow, editor spawn without shell, and preAction scope enforcement.
    • Tests (test/*): ensure file I/O, env var mocking (XDG_CONFIG_HOME), and exit/edge behaviors are reliable.

Possibly related PRs

Poem

🐰
I nibble dots and camelCase,
I stash your flags in a safe small space.
Get, set, unset — a hopping song,
Edit and reset if things go wrong.
Configs tidy, saved with glee — hop, hop, hurray for me! 🎋

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding an openspec config command for managing global configuration, which aligns with the substantial implementation across CLI wiring, command handlers, schema validation, and comprehensive tests.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch TabishB/config-cli-review

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 and usage tips.

- Add tests for unknown fields with various types
- Add test to verify error message path for featureFlags
- Add test for number values rejection in featureFlags
- Add config set simulation tests to verify full coerce → set → validate flow
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (4)
openspec/changes/add-config-command/specs/cli-config/spec.md (1)

1-6: Minor style improvement: Remove redundant "interface" after "CLI".

The static analysis tool correctly identified that "CLI interface" is redundant since CLI already stands for "Command Line Interface." Consider simplifying to "CLI" or "command-line interface."

🔎 Suggested fix
-Provide a CLI interface for viewing and modifying global OpenSpec configuration. Enables users to manage settings without manually editing JSON files, with support for scripting and automation.
+Provide a CLI for viewing and modifying global OpenSpec configuration. Enables users to manage settings without manually editing JSON files, with support for scripting and automation.
src/core/config-schema.ts (2)

186-198: Minor: Redundant type assertion after instanceof check.

Line 192 casts error to z.ZodError right after the instanceof z.ZodError check, which is unnecessary since TypeScript already narrows the type. This is harmless but slightly redundant.

🔎 Simplified version
   } catch (error) {
     if (error instanceof z.ZodError) {
-      const zodError = error as z.ZodError;
-      const messages = zodError.issues.map((e) => `${e.path.join('.')}: ${e.message}`);
+      const messages = error.issues.map((e) => `${e.path.join('.')}: ${e.message}`);
       return { success: false, error: messages.join('; ') };
     }

57-71: Add guard for empty path edge case in setNestedValue.

If path is an empty string, path.split('.') returns [""], which would set obj[""] = value. While unlikely in normal CLI usage (since the set <key> command requires an argument), adding a guard like if (!path) throw new Error('path cannot be empty') would improve robustness.

openspec/changes/add-config-command/design.md (1)

1-88: LGTM - Comprehensive design document.

The design document appropriately covers the context, goals, decisions, and trade-offs for the new config command. The decision rationale is clear, and the known limitations (dot notation conflicts, type coercion edge cases) are properly documented.

Minor markdown style improvements

The static analysis tools flagged a couple of style issues:

  1. Line 3: "CLI interface" is redundant (CLI stands for Command Line Interface). Consider simplifying to "CLI".
  2. Line 46: Add blank lines before and after the table for better markdown formatting.
-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.
+The `global-config` spec defines how OpenSpec reads/writes `config.json`, but users currently must edit it by hand. This command provides a CLI to that config.
 - 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
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 68e0a7e and 5f5688d.

📒 Files selected for processing (10)
  • openspec/changes/add-config-command/design.md (1 hunks)
  • openspec/changes/add-config-command/proposal.md (1 hunks)
  • openspec/changes/add-config-command/specs/cli-config/spec.md (1 hunks)
  • openspec/changes/add-config-command/tasks.md (1 hunks)
  • src/cli/index.ts (2 hunks)
  • src/commands/config.ts (1 hunks)
  • src/core/completions/command-registry.ts (1 hunks)
  • src/core/config-schema.ts (1 hunks)
  • test/commands/config.test.ts (1 hunks)
  • test/core/config-schema.test.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
openspec/changes/**/*.md

📄 CodeRabbit inference engine (openspec/AGENTS.md)

Scaffold proposal using proposal.md, tasks.md, optional design.md, and delta specs under openspec/changes/<id>/

Files:

  • openspec/changes/add-config-command/proposal.md
  • openspec/changes/add-config-command/design.md
  • openspec/changes/add-config-command/tasks.md
  • openspec/changes/add-config-command/specs/cli-config/spec.md
openspec/changes/*/proposal.md

📄 CodeRabbit inference engine (openspec/AGENTS.md)

Ensure proposal.md includes sections: Why (1-2 sentences), What Changes (bullet list with breaking change markers), and Impact (affected specs and code)

Files:

  • openspec/changes/add-config-command/proposal.md
openspec/changes/*/tasks.md

📄 CodeRabbit inference engine (openspec/AGENTS.md)

Ensure tasks.md contains implementation checklist with numbered sections and checkbox items

Files:

  • openspec/changes/add-config-command/tasks.md
openspec/changes/**/specs/**/spec.md

📄 CodeRabbit inference engine (openspec/AGENTS.md)

openspec/changes/**/specs/**/spec.md: Use ## ADDED|MODIFIED|REMOVED|RENAMED Requirements headers in spec delta files
Include at least one #### Scenario: per requirement in spec delta files
Use #### Scenario: Name format (4 hashtags) for scenario headers, not bullets or bold text
Use ## ADDED Requirements for new orthogonal capabilities that can stand alone; use ## MODIFIED Requirements for behavior changes of existing requirements
When using MODIFIED Requirements, paste the full requirement block including header and all scenarios

Files:

  • openspec/changes/add-config-command/specs/cli-config/spec.md
🧠 Learnings (7)
📚 Learning: 2025-11-25T01:08:19.004Z
Learnt from: CR
Repo: Fission-AI/OpenSpec PR: 0
File: openspec/AGENTS.md:0-0
Timestamp: 2025-11-25T01:08:19.004Z
Learning: Applies to openspec/changes/**/*.md : Scaffold proposal using `proposal.md`, `tasks.md`, optional `design.md`, and delta specs under `openspec/changes/<id>/`

Applied to files:

  • openspec/changes/add-config-command/proposal.md
  • openspec/changes/add-config-command/design.md
  • openspec/changes/add-config-command/specs/cli-config/spec.md
📚 Learning: 2025-11-25T01:08:19.004Z
Learnt from: CR
Repo: Fission-AI/OpenSpec PR: 0
File: openspec/AGENTS.md:0-0
Timestamp: 2025-11-25T01:08:19.004Z
Learning: Applies to openspec/changes/*/proposal.md : Ensure `proposal.md` includes sections: Why (1-2 sentences), What Changes (bullet list with breaking change markers), and Impact (affected specs and code)

Applied to files:

  • openspec/changes/add-config-command/proposal.md
  • openspec/changes/add-config-command/specs/cli-config/spec.md
📚 Learning: 2025-11-25T01:08:19.004Z
Learnt from: CR
Repo: Fission-AI/OpenSpec PR: 0
File: openspec/AGENTS.md:0-0
Timestamp: 2025-11-25T01:08:19.004Z
Learning: Applies to openspec/changes/**/specs/**/spec.md : Use `## ADDED Requirements` for new orthogonal capabilities that can stand alone; use `## MODIFIED Requirements` for behavior changes of existing requirements

Applied to files:

  • openspec/changes/add-config-command/proposal.md
  • openspec/changes/add-config-command/specs/cli-config/spec.md
📚 Learning: 2025-11-25T01:08:19.004Z
Learnt from: CR
Repo: Fission-AI/OpenSpec PR: 0
File: openspec/AGENTS.md:0-0
Timestamp: 2025-11-25T01:08:19.004Z
Learning: Applies to openspec/changes/**/specs/**/spec.md : Use `## ADDED|MODIFIED|REMOVED|RENAMED Requirements` headers in spec delta files

Applied to files:

  • openspec/changes/add-config-command/proposal.md
  • openspec/changes/add-config-command/specs/cli-config/spec.md
📚 Learning: 2025-11-25T01:08:02.839Z
Learnt from: CR
Repo: Fission-AI/OpenSpec PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T01:08:02.839Z
Learning: Use `@/openspec/AGENTS.md` to learn how to create and apply change proposals, spec format and conventions, and project structure and guidelines

Applied to files:

  • openspec/changes/add-config-command/proposal.md
📚 Learning: 2025-11-25T01:08:19.004Z
Learnt from: CR
Repo: Fission-AI/OpenSpec PR: 0
File: openspec/AGENTS.md:0-0
Timestamp: 2025-11-25T01:08:19.004Z
Learning: Create `design.md` only when needed: cross-cutting changes, new external dependencies, significant data model changes, security/performance complexity, or pre-coding ambiguity

Applied to files:

  • openspec/changes/add-config-command/design.md
📚 Learning: 2025-11-25T01:08:19.004Z
Learnt from: CR
Repo: Fission-AI/OpenSpec PR: 0
File: openspec/AGENTS.md:0-0
Timestamp: 2025-11-25T01:08:19.004Z
Learning: Applies to openspec/changes/*/tasks.md : Ensure `tasks.md` contains implementation checklist with numbered sections and checkbox items

Applied to files:

  • openspec/changes/add-config-command/tasks.md
🧬 Code graph analysis (4)
test/core/config-schema.test.ts (1)
src/core/config-schema.ts (8)
  • getNestedValue (32-47)
  • setNestedValue (57-71)
  • deleteNestedValue (80-98)
  • coerceValue (110-130)
  • formatValueYaml (139-178)
  • validateConfig (186-198)
  • GlobalConfigSchema (7-14)
  • DEFAULT_CONFIG (21-23)
src/cli/index.ts (1)
src/commands/config.ts (1)
  • registerConfigCommand (27-203)
src/commands/config.ts (1)
src/core/config-schema.ts (7)
  • formatValueYaml (139-178)
  • getNestedValue (32-47)
  • coerceValue (110-130)
  • setNestedValue (57-71)
  • validateConfig (186-198)
  • deleteNestedValue (80-98)
  • DEFAULT_CONFIG (21-23)
test/commands/config.test.ts (1)
src/core/completions/command-registry.ts (1)
  • COMMAND_REGISTRY (35-360)
🪛 LanguageTool
openspec/changes/add-config-command/design.md

[style] ~3-~3: This phrase is redundant (‘I’ stands for ‘interface’). Use simply “CLI”.
Context: ...dit it by hand. This command provides a CLI interface to that config. ## Goals / Non-Goals ...

(ACRONYM_TAUTOLOGY)

openspec/changes/add-config-command/specs/cli-config/spec.md

[style] ~5-~5: This phrase is redundant (‘I’ stands for ‘interface’). Use simply “CLI”.
Context: ...ig Specification ## Purpose Provide a CLI interface for viewing and modifying global OpenSp...

(ACRONYM_TAUTOLOGY)

🪛 markdownlint-cli2 (0.18.1)
openspec/changes/add-config-command/design.md

46-46: Tables should be surrounded by blank lines

(MD058, blanks-around-tables)

🔇 Additional comments (21)
openspec/changes/add-config-command/specs/cli-config/spec.md (1)

7-213: Spec structure follows guidelines correctly.

The specification properly uses ## ADDED Requirements for new orthogonal capabilities, and all scenarios follow the #### Scenario: Name format as required. The WHEN/THEN/AND structure is consistent throughout.

src/core/config-schema.ts (5)

7-23: Schema definition is well-structured.

The use of .passthrough() for forward compatibility with unknown fields is appropriate, and the DEFAULT_CONFIG correctly matches the schema structure.


32-47: LGTM!

The getNestedValue function correctly handles edge cases including null, undefined, and non-object intermediate values.


80-98: LGTM!

The deleteNestedValue function correctly returns a boolean indicating whether the key existed and was deleted. Same edge case consideration for empty paths applies here.


110-130: Well-implemented type coercion.

The function correctly handles edge cases: empty strings are not coerced to 0 (via the value.trim() !== '' check), and only exact case-sensitive "true"/"false" strings are coerced to booleans.


139-178: LGTM for intended use case.

The YAML-like formatting handles primitives, arrays, and objects appropriately for human-readable config display.

src/cli/index.ts (2)

17-17: LGTM!

Import follows the existing pattern for command registration.


204-204: LGTM!

Registration follows the same pattern as registerSpecCommand, placing the config command appropriately in the CLI initialization sequence.

src/core/completions/command-registry.ts (1)

291-359: Config command registry entry is complete and consistent.

The registry entry correctly defines all subcommands (path, list, get, set, unset, reset, edit) with their respective flags, matching the specification. The structure follows the existing patterns used by other commands like spec and completion.

openspec/changes/add-config-command/proposal.md (1)

1-60: Proposal follows required structure.

The proposal includes all required sections per coding guidelines:

  • Why: Concise explanation of the user need (lines 1-3)
  • What Changes: Bullet list with examples (lines 5-51)
  • Impact: Affected specs and code listed (lines 53-60)

Based on learnings, the proposal correctly omits breaking change markers since this is additive functionality.

openspec/changes/add-config-command/tasks.md (1)

1-28: LGTM - Well-structured implementation checklist.

The tasks file follows the required format with numbered sections and checkbox items. All 17 tasks are marked complete, covering core infrastructure, command implementation, integration, and testing. The organization is clear and comprehensive.

Based on coding guidelines, this properly implements the required tasks.md structure.

test/commands/config.test.ts (3)

12-37: Excellent test isolation setup.

The test setup demonstrates good practices:

  • Unique temp directories per test using timestamp and random suffix (line 14)
  • Proper environment variable isolation and restoration (lines 18-19, 27)
  • Module cache reset to pick up new environment variables (line 36)
  • Spy setup and cleanup for console.error (lines 22, 33)

This ensures tests are fully isolated and won't interfere with each other or the actual config file.


39-92: Comprehensive integration test coverage.

The tests cover all critical integration scenarios:

  • Config path resolution with XDG_CONFIG_HOME
  • Save/load round-trips
  • Default behavior when config file is missing
  • Unknown field preservation (passthrough validation)
  • Graceful handling of invalid JSON with error logging

The use of dynamic imports (lines 40, 46, 54, 67, 81) correctly ensures each test gets a fresh module with the updated environment variables.


94-157: Thorough shell completion registry verification.

The tests systematically verify:

  • Config command exists in registry with correct description
  • All 7 subcommands are present (path, list, get, set, unset, reset, edit)
  • Subcommand-specific flags: --json on list, --string on set, --all/-y on reset
  • Top-level --scope flag on config command

This ensures the completion registry stays synchronized with the command implementation.

test/core/config-schema.test.ts (4)

15-55: Excellent coverage of getNestedValue edge cases.

The tests comprehensively cover:

  • Top-level and nested dot-notation access (lines 16-24)
  • Non-existent paths returning undefined (lines 26-34)
  • Traversal through null and primitives (lines 36-44)
  • Object and array value handling (lines 46-54)

This ensures robust handling of all access patterns mentioned in the design document.


57-93: Thorough setNestedValue testing.

The tests validate critical behaviors:

  • Top-level and nested value assignment
  • Automatic creation of intermediate objects (line 70-74)
  • Overwriting existing values and primitives (lines 76-86)
  • Preservation of sibling keys (lines 88-92)

These scenarios ensure the dot-notation setter works correctly for all use cases.


129-180: Comprehensive type coercion test coverage.

The tests validate all coercion rules from the design document:

  • Boolean coercion for "true"/"false" (lines 130-136)
  • Number coercion for integers, floats, negatives, scientific notation (lines 138-148, 177-179)
  • String preservation for non-coercible values (lines 150-164)
  • Force string flag override (lines 166-170)
  • Infinity rejection per design (lines 172-175)

The edge case coverage (empty strings, whitespace, mixed alphanumeric) is excellent.


225-256: Solid validation testing with zod schema.

The tests verify:

  • Valid configurations with featureFlags (line 226-229)
  • Empty and missing featureFlags (lines 231-239)
  • Unknown field passthrough (lines 241-244) - critical for forward compatibility
  • Rejection of invalid types (lines 246-255)

This aligns with the design decision to use zod with passthrough for forward compatibility.

src/commands/config.ts (3)

27-38: Good defensive validation for reserved scope flag.

The preAction hook (lines 32-38) prevents usage of non-global scopes with a clear error message. This reserves the --scope flag for future project-local config implementation without breaking changes, as documented in the design.


84-111: Excellent validation-before-save pattern.

The set command demonstrates best practices:

  • Creates a deep copy for validation (line 93) before mutating the actual config
  • Validates the new config with zod schema (lines 97-102)
  • Only persists changes if validation passes (lines 105-106)
  • Provides clear error messages on validation failure

This prevents saving invalid configurations that could break the tool.


130-157: Safe reset implementation with confirmation.

The reset command includes good safeguards:

  • Requires explicit --all flag (lines 136-141) to prevent accidental resets
  • Prompts for confirmation unless -y/--yes is provided (lines 143-152)
  • Uses the inquirer library for interactive confirmation with default to false (line 146)

This follows the principle of making destructive operations harder to execute accidentally.

…spaces

Use spawn with shell: false and pass configPath as an argument instead
of building a shell command string. This correctly handles spaces in
both the EDITOR path and config file path on all platforms.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/commands/config.ts (1)

159-198: Past review comment successfully addressed!

The editor spawning now uses spawn(editor, [configPath], { stdio: 'inherit', shell: false }), which correctly handles spaces in both the editor path and config path without shell parsing issues. This is the recommended approach and resolves the Windows compatibility concern from the previous review.


Consider validating config after edit.

Currently, the command doesn't validate the config file after the user closes the editor. If the user introduces syntax errors or schema violations during manual editing, these won't be detected until the config is next loaded, potentially causing confusing failures.

Optional: Add validation after editor closes

You could add validation after the editor closes to catch errors immediately:

       await new Promise<void>((resolve, reject) => {
         child.on('close', (code) => {
           if (code === 0) {
             resolve();
           } else {
             reject(new Error(`Editor exited with code ${code}`));
           }
         });
         child.on('error', reject);
       });
+
+      // Validate the edited config
+      try {
+        const editedConfig = getGlobalConfig();
+        const validation = validateConfig(editedConfig);
+        if (!validation.success) {
+          console.error(`Warning: Configuration validation failed - ${validation.error}`);
+          console.error('Please fix the errors or run `openspec config reset --all -y` to restore defaults.');
+          process.exitCode = 1;
+        } else {
+          console.log('Configuration validated successfully');
+        }
+      } catch (error) {
+        console.error(`Error: Failed to load config - ${error instanceof Error ? error.message : 'Unknown error'}`);
+        console.error('The config file may contain invalid JSON. Please fix or reset.');
+        process.exitCode = 1;
+      }
     });
 }

Note: This is optional, as many CLI tools trust users to manually validate their edits.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 20a6d02 and efa154b.

📒 Files selected for processing (1)
  • src/commands/config.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/commands/config.ts (1)
src/core/config-schema.ts (7)
  • formatValueYaml (139-178)
  • getNestedValue (32-47)
  • coerceValue (110-130)
  • setNestedValue (57-71)
  • validateConfig (186-198)
  • deleteNestedValue (80-98)
  • DEFAULT_CONFIG (21-23)
🔇 Additional comments (2)
src/commands/config.ts (2)

63-80: LGTM! Silent exit is appropriate for scriptable output.

The command correctly returns raw values suitable for scripting, with the exit code indicating success/failure. The lack of an error message when a key is not found is intentional to keep stdout clean for script consumption.


83-110: LGTM! Solid validation and error handling.

The copy-before-validate pattern ensures that invalid configurations are rejected before any changes are persisted. The validation flow is well-structured and provides clear feedback to users.

Move completed change to archive and apply spec deltas to create
the cli-config specification documenting the config command interface.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (3)
openspec/changes/archive/2025-12-21-add-config-command/design.md (1)

3-3: Minor: Remove redundant phrase "CLI interface".

The phrase "CLI interface" is tautological (I = interface). Per static analysis, simplify to "CLI".

🔎 Proposed fix
-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.
+The `global-config` spec defines how OpenSpec reads/writes `config.json`, but users currently must edit it by hand. This command provides a CLI to that config.
openspec/specs/cli-config/spec.md (1)

1-10: Minor: Remove redundant phrase "CLI interface".

The phrase "CLI interface" is tautological. Per static analysis, simplify to "CLI" for clarity.

🔎 Proposed fix
-## Purpose
-Provide a user-friendly CLI interface for viewing and modifying global OpenSpec configuration settings without manually editing JSON files.
+## Purpose
+Provide a user-friendly CLI for viewing and modifying global OpenSpec configuration settings without manually editing JSON files.
openspec/changes/archive/2025-12-21-add-config-command/specs/cli-config/spec.md (1)

1-10: Minor: Remove redundant phrase "CLI interface".

The phrase "CLI interface" is tautological. Per static analysis, simplify to "CLI" for consistency.

🔎 Proposed fix
-## Purpose
-
-Provide a CLI interface for viewing and modifying global OpenSpec configuration. Enables users to manage settings without manually editing JSON files, with support for scripting and automation.
+## Purpose
+
+Provide a CLI for viewing and modifying global OpenSpec configuration. Enables users to manage settings without manually editing JSON files, with support for scripting and automation.
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between efa154b and c8e89fd.

📒 Files selected for processing (5)
  • openspec/changes/archive/2025-12-21-add-config-command/design.md (1 hunks)
  • openspec/changes/archive/2025-12-21-add-config-command/proposal.md (1 hunks)
  • openspec/changes/archive/2025-12-21-add-config-command/specs/cli-config/spec.md (1 hunks)
  • openspec/changes/archive/2025-12-21-add-config-command/tasks.md (1 hunks)
  • openspec/specs/cli-config/spec.md (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
openspec/changes/**/*.md

📄 CodeRabbit inference engine (openspec/AGENTS.md)

Scaffold proposal using proposal.md, tasks.md, optional design.md, and delta specs under openspec/changes/<id>/

Files:

  • openspec/changes/archive/2025-12-21-add-config-command/proposal.md
  • openspec/changes/archive/2025-12-21-add-config-command/specs/cli-config/spec.md
  • openspec/changes/archive/2025-12-21-add-config-command/tasks.md
  • openspec/changes/archive/2025-12-21-add-config-command/design.md
openspec/changes/**/specs/**/spec.md

📄 CodeRabbit inference engine (openspec/AGENTS.md)

openspec/changes/**/specs/**/spec.md: Use ## ADDED|MODIFIED|REMOVED|RENAMED Requirements headers in spec delta files
Include at least one #### Scenario: per requirement in spec delta files
Use #### Scenario: Name format (4 hashtags) for scenario headers, not bullets or bold text
Use ## ADDED Requirements for new orthogonal capabilities that can stand alone; use ## MODIFIED Requirements for behavior changes of existing requirements
When using MODIFIED Requirements, paste the full requirement block including header and all scenarios

Files:

  • openspec/changes/archive/2025-12-21-add-config-command/specs/cli-config/spec.md
openspec/specs/**/spec.md

📄 CodeRabbit inference engine (openspec/AGENTS.md)

Use SHALL/MUST for normative requirements in spec files; avoid should/may unless intentionally non-normative

Files:

  • openspec/specs/cli-config/spec.md
🧠 Learnings (7)
📚 Learning: 2025-11-25T01:08:19.004Z
Learnt from: CR
Repo: Fission-AI/OpenSpec PR: 0
File: openspec/AGENTS.md:0-0
Timestamp: 2025-11-25T01:08:19.004Z
Learning: Applies to openspec/changes/**/*.md : Scaffold proposal using `proposal.md`, `tasks.md`, optional `design.md`, and delta specs under `openspec/changes/<id>/`

Applied to files:

  • openspec/changes/archive/2025-12-21-add-config-command/proposal.md
  • openspec/specs/cli-config/spec.md
  • openspec/changes/archive/2025-12-21-add-config-command/tasks.md
  • openspec/changes/archive/2025-12-21-add-config-command/design.md
📚 Learning: 2025-11-25T01:08:19.004Z
Learnt from: CR
Repo: Fission-AI/OpenSpec PR: 0
File: openspec/AGENTS.md:0-0
Timestamp: 2025-11-25T01:08:19.004Z
Learning: Applies to openspec/changes/*/proposal.md : Ensure `proposal.md` includes sections: Why (1-2 sentences), What Changes (bullet list with breaking change markers), and Impact (affected specs and code)

Applied to files:

  • openspec/changes/archive/2025-12-21-add-config-command/proposal.md
  • openspec/specs/cli-config/spec.md
📚 Learning: 2025-11-25T01:08:02.839Z
Learnt from: CR
Repo: Fission-AI/OpenSpec PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T01:08:02.839Z
Learning: Use `@/openspec/AGENTS.md` to learn how to create and apply change proposals, spec format and conventions, and project structure and guidelines

Applied to files:

  • openspec/changes/archive/2025-12-21-add-config-command/proposal.md
  • openspec/specs/cli-config/spec.md
📚 Learning: 2025-11-25T01:08:19.004Z
Learnt from: CR
Repo: Fission-AI/OpenSpec PR: 0
File: openspec/AGENTS.md:0-0
Timestamp: 2025-11-25T01:08:19.004Z
Learning: Applies to openspec/changes/**/specs/**/spec.md : Use `## ADDED|MODIFIED|REMOVED|RENAMED Requirements` headers in spec delta files

Applied to files:

  • openspec/changes/archive/2025-12-21-add-config-command/proposal.md
  • openspec/changes/archive/2025-12-21-add-config-command/specs/cli-config/spec.md
  • openspec/specs/cli-config/spec.md
📚 Learning: 2025-11-25T01:08:19.004Z
Learnt from: CR
Repo: Fission-AI/OpenSpec PR: 0
File: openspec/AGENTS.md:0-0
Timestamp: 2025-11-25T01:08:19.004Z
Learning: Applies to openspec/changes/**/specs/**/spec.md : Use `## ADDED Requirements` for new orthogonal capabilities that can stand alone; use `## MODIFIED Requirements` for behavior changes of existing requirements

Applied to files:

  • openspec/changes/archive/2025-12-21-add-config-command/specs/cli-config/spec.md
  • openspec/specs/cli-config/spec.md
📚 Learning: 2025-11-25T01:08:19.004Z
Learnt from: CR
Repo: Fission-AI/OpenSpec PR: 0
File: openspec/AGENTS.md:0-0
Timestamp: 2025-11-25T01:08:19.004Z
Learning: Applies to openspec/changes/*/tasks.md : Ensure `tasks.md` contains implementation checklist with numbered sections and checkbox items

Applied to files:

  • openspec/changes/archive/2025-12-21-add-config-command/tasks.md
📚 Learning: 2025-11-25T01:08:19.004Z
Learnt from: CR
Repo: Fission-AI/OpenSpec PR: 0
File: openspec/AGENTS.md:0-0
Timestamp: 2025-11-25T01:08:19.004Z
Learning: Create `design.md` only when needed: cross-cutting changes, new external dependencies, significant data model changes, security/performance complexity, or pre-coding ambiguity

Applied to files:

  • openspec/changes/archive/2025-12-21-add-config-command/design.md
🪛 LanguageTool
openspec/changes/archive/2025-12-21-add-config-command/specs/cli-config/spec.md

[style] ~5-~5: This phrase is redundant (‘I’ stands for ‘interface’). Use simply “CLI”.
Context: ...ig Specification ## Purpose Provide a CLI interface for viewing and modifying global OpenSp...

(ACRONYM_TAUTOLOGY)

openspec/specs/cli-config/spec.md

[style] ~4-~4: This phrase is redundant (‘I’ stands for ‘interface’). Use simply “CLI”.
Context: ...ion ## Purpose Provide a user-friendly CLI interface for viewing and modifying global OpenSp...

(ACRONYM_TAUTOLOGY)

openspec/changes/archive/2025-12-21-add-config-command/design.md

[style] ~3-~3: This phrase is redundant (‘I’ stands for ‘interface’). Use simply “CLI”.
Context: ...dit it by hand. This command provides a CLI interface to that config. ## Goals / Non-Goals ...

(ACRONYM_TAUTOLOGY)

🔇 Additional comments (2)
openspec/changes/archive/2025-12-21-add-config-command/tasks.md (1)

1-28: LGTM — Well-structured implementation checklist.

The tasks are clearly organized with numbered sections and checkbox items, all marked complete, indicating the feature is comprehensively implemented.

openspec/changes/archive/2025-12-21-add-config-command/proposal.md (1)

1-60: LGTM — Comprehensive and well-structured proposal.

The proposal clearly articulates the "Why," detailed "What Changes" with usage examples, and impact on affected specs and code. Structure and content align with guidelines.

@TabishB TabishB merged commit 971f8ca into main Dec 22, 2025
6 of 7 checks passed
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
openspec/specs/cli-config/spec.md (1)

1-217: Excellent specification with proper normative language!

The spec consistently uses SHALL for all normative requirements as required by the coding guidelines. The requirements are comprehensive, well-structured, and thoroughly cover all aspects of the config command behavior, including edge cases, error handling, and output formats.

Optional: Minor style refinement

Line 4 uses "CLI interface" which is technically redundant since CLI already means "Command Line Interface." You could simplify to just "CLI" if desired, though this is purely stylistic.

-Provide a user-friendly CLI interface for viewing and modifying global OpenSpec configuration settings without manually editing JSON files.
+Provide a user-friendly CLI for viewing and modifying global OpenSpec configuration settings without manually editing JSON files.
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c8e89fd and 1f16e79.

📒 Files selected for processing (6)
  • openspec/specs/cli-config/spec.md
  • src/cli/index.ts
  • src/commands/config.ts
  • src/core/completions/command-registry.ts
  • src/core/config-schema.ts
  • test/commands/config.test.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/core/completions/command-registry.ts
  • src/core/config-schema.ts
🧰 Additional context used
📓 Path-based instructions (1)
openspec/specs/**/spec.md

📄 CodeRabbit inference engine (openspec/AGENTS.md)

Use SHALL/MUST for normative requirements in spec files; avoid should/may unless intentionally non-normative

Files:

  • openspec/specs/cli-config/spec.md
🧠 Learnings (6)
📚 Learning: 2025-11-25T01:08:19.004Z
Learnt from: CR
Repo: Fission-AI/OpenSpec PR: 0
File: openspec/AGENTS.md:0-0
Timestamp: 2025-11-25T01:08:19.004Z
Learning: Applies to openspec/changes/**/*.md : Scaffold proposal using `proposal.md`, `tasks.md`, optional `design.md`, and delta specs under `openspec/changes/<id>/`

Applied to files:

  • openspec/specs/cli-config/spec.md
📚 Learning: 2025-11-25T01:08:19.004Z
Learnt from: CR
Repo: Fission-AI/OpenSpec PR: 0
File: openspec/AGENTS.md:0-0
Timestamp: 2025-11-25T01:08:19.004Z
Learning: Applies to openspec/changes/*/proposal.md : Ensure `proposal.md` includes sections: Why (1-2 sentences), What Changes (bullet list with breaking change markers), and Impact (affected specs and code)

Applied to files:

  • openspec/specs/cli-config/spec.md
📚 Learning: 2025-11-25T01:08:19.004Z
Learnt from: CR
Repo: Fission-AI/OpenSpec PR: 0
File: openspec/AGENTS.md:0-0
Timestamp: 2025-11-25T01:08:19.004Z
Learning: Applies to openspec/changes/**/specs/**/spec.md : Use `## ADDED|MODIFIED|REMOVED|RENAMED Requirements` headers in spec delta files

Applied to files:

  • openspec/specs/cli-config/spec.md
📚 Learning: 2025-11-25T01:08:02.839Z
Learnt from: CR
Repo: Fission-AI/OpenSpec PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T01:08:02.839Z
Learning: Use `@/openspec/AGENTS.md` to learn how to create and apply change proposals, spec format and conventions, and project structure and guidelines

Applied to files:

  • openspec/specs/cli-config/spec.md
📚 Learning: 2025-11-25T01:08:19.004Z
Learnt from: CR
Repo: Fission-AI/OpenSpec PR: 0
File: openspec/AGENTS.md:0-0
Timestamp: 2025-11-25T01:08:19.004Z
Learning: Check `openspec/project.md` for project conventions before creating specs

Applied to files:

  • openspec/specs/cli-config/spec.md
📚 Learning: 2025-11-25T01:08:19.004Z
Learnt from: CR
Repo: Fission-AI/OpenSpec PR: 0
File: openspec/AGENTS.md:0-0
Timestamp: 2025-11-25T01:08:19.004Z
Learning: Applies to openspec/changes/**/specs/**/spec.md : Use `## ADDED Requirements` for new orthogonal capabilities that can stand alone; use `## MODIFIED Requirements` for behavior changes of existing requirements

Applied to files:

  • openspec/specs/cli-config/spec.md
🧬 Code graph analysis (3)
src/cli/index.ts (1)
src/commands/config.ts (1)
  • registerConfigCommand (27-233)
src/commands/config.ts (1)
src/core/config-schema.ts (8)
  • formatValueYaml (171-210)
  • getNestedValue (64-79)
  • validateConfigKeyPath (31-55)
  • coerceValue (142-162)
  • setNestedValue (89-103)
  • validateConfig (218-230)
  • deleteNestedValue (112-130)
  • DEFAULT_CONFIG (21-23)
test/commands/config.test.ts (2)
src/core/completions/command-registry.ts (1)
  • COMMAND_REGISTRY (35-364)
src/core/config-schema.ts (1)
  • validateConfigKeyPath (31-55)
🪛 LanguageTool
openspec/specs/cli-config/spec.md

[style] ~4-~4: This phrase is redundant (‘I’ stands for ‘interface’). Use simply “CLI”.
Context: ...ion ## Purpose Provide a user-friendly CLI interface for viewing and modifying global OpenSp...

(ACRONYM_TAUTOLOGY)

🔇 Additional comments (12)
src/cli/index.ts (2)

16-16: LGTM!

The import follows the established pattern for command registration functions.


204-204: LGTM!

The config command registration is correctly placed and follows the established pattern for command integration.

test/commands/config.test.ts (3)

6-92: Excellent test isolation and coverage!

The integration test suite properly isolates each test with unique temporary directories, environment variable overrides, and module cache resets. The tests comprehensively cover config path resolution, persistence, defaults, unknown field preservation, and invalid JSON handling.


94-158: LGTM!

The shell completion registry tests thoroughly verify that all config subcommands and their flags are properly registered for completion support.


160-175: LGTM!

The key validation tests properly verify the schema validation rules for top-level keys, nested feature flags, and disallowed deep nesting.

src/commands/config.ts (7)

27-38: LGTM!

The command registration properly enforces global scope and reserves the --scope flag for future project-local configuration support, exactly as specified in the requirements.


41-61: LGTM!

The path and list subcommands are implemented correctly with proper output formatting for both human-readable (YAML-like) and JSON modes.


64-81: LGTM!

The get command correctly implements nested key access with dot notation, appropriate exit codes for missing keys, and proper output formatting for both scalar and object values.


84-123: Excellent defensive implementation!

The set command implements robust validation with copy-before-modify to ensure config integrity. The key validation provides clear error messages and user guidance, while the schema validation prevents invalid configurations from being persisted.


126-139: LGTM!

The unset command correctly handles both existent and non-existent keys, saving only when necessary and providing appropriate user feedback.


142-169: LGTM!

The reset command properly implements the safety requirements with explicit --all flag, confirmation prompt (unless --yes), and clear usage guidance. The spreading of DEFAULT_CONFIG ensures a clean copy is saved.


172-232: LGTM! Windows path handling properly addressed.

The edit command correctly spawns the editor using spawn(editor, [configPath], { shell: false }), which avoids shell parsing issues and properly handles paths with spaces on all platforms including Windows. The post-edit validation ensures config integrity, and comprehensive error handling covers various failure scenarios.

TabishB added a commit that referenced this pull request Dec 22, 2025
The config command (added in #382) reintroduced the pre-commit hook hang
issue that was fixed in #380. The static import of @inquirer/prompts at
module load time causes stdin event listeners to be registered even when
running non-interactive commands, preventing clean process exit when
stdin is piped (as pre-commit does).

Convert the static import to a dynamic import that only loads inquirer
when the `config reset` command is actually used interactively.

Fixes #367
TabishB added a commit that referenced this pull request Dec 22, 2025
…392)

* fix(cli): use dynamic import for @inquirer/prompts in config command

The config command (added in #382) reintroduced the pre-commit hook hang
issue that was fixed in #380. The static import of @inquirer/prompts at
module load time causes stdin event listeners to be registered even when
running non-interactive commands, preventing clean process exit when
stdin is piped (as pre-commit does).

Convert the static import to a dynamic import that only loads inquirer
when the `config reset` command is actually used interactively.

Fixes #367

* chore: add ESLint with no-restricted-imports rule for @InQuirer

Add ESLint configuration that prevents static imports of @inquirer/*
modules. This prevents future regressions of the pre-commit hook hang
issue fixed in this PR.

The rule shows a helpful error message pointing to issue #367 for context.
init.ts is exempted since it's already dynamically imported from the CLI.

* ci: add ESLint step to lint job

Run `pnpm lint` in CI to enforce the no-restricted-imports rule
that prevents static @InQuirer imports.
appboypov added a commit to appboypov/pew-pew-plx that referenced this pull request Dec 24, 2025
* feat(cli): add openspec config command for global configuration management (Fission-AI#382)

* feat(cli): add openspec config command for global configuration management

Implements the `openspec config` command with subcommands:
- `path`: Show config file location
- `list [--json]`: Show all current settings
- `get <key>`: Get a specific value (raw output for scripting)
- `set <key> <value> [--string]`: Set a value with auto type coercion
- `unset <key>`: Remove a key (revert to default)
- `reset --all [-y]`: Reset configuration to defaults
- `edit`: Open config in $EDITOR/$VISUAL

Key features:
- Dot notation for nested key access (e.g., featureFlags.someFlag)
- Auto type coercion (true/false → boolean, numbers → number)
- --string flag to force string storage
- Zod schema validation with unknown field passthrough
- Reserved --scope flag for future project-local config
- Windows-compatible editor spawning with proper path quoting
- Shell completion registry integration

* test(config): add additional unit tests for validation and coercion

- Add tests for unknown fields with various types
- Add test to verify error message path for featureFlags
- Add test for number values rejection in featureFlags
- Add config set simulation tests to verify full coerce → set → validate flow

* fix(config): avoid shell parsing in config edit to handle paths with spaces

Use spawn with shell: false and pass configPath as an argument instead
of building a shell command string. This correctly handles spaces in
both the EDITOR path and config file path on all platforms.

* chore(openspec): archive add-config-command and create cli-config spec

Move completed change to archive and apply spec deltas to create
the cli-config specification documenting the config command interface.

* Validate config keys on set

* Add changeset for config command and shell completions (Fission-AI#388)

* chore(release): version packages (Fission-AI#389)

* Version Packages

* chore: trigger CI

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Tabish Bidiwale <[email protected]>

* feat(ci): migrate to npm OIDC trusted publishing (Fission-AI#390)

Replace classic npm token authentication with OIDC trusted publishing:

- Add `id-token: write` permission for OIDC token generation
- Upgrade to Node 24 (includes npm 11.5.1+ required for OIDC)
- Remove NPM_TOKEN/NODE_AUTH_TOKEN env vars (OIDC replaces them)

This eliminates the need for rotating npm access tokens and provides
cryptographically verified publisher identity with automatic provenance
attestation.

Requires configuring trusted publisher on npmjs.com:
- Organization: Fission-AI
- Repository: OpenSpec
- Workflow: release-prepare.yml

* fix(cli): use dynamic import for @inquirer/prompts in config command (Fission-AI#392)

* fix(cli): use dynamic import for @inquirer/prompts in config command

The config command (added in Fission-AI#382) reintroduced the pre-commit hook hang
issue that was fixed in Fission-AI#380. The static import of @inquirer/prompts at
module load time causes stdin event listeners to be registered even when
running non-interactive commands, preventing clean process exit when
stdin is piped (as pre-commit does).

Convert the static import to a dynamic import that only loads inquirer
when the `config reset` command is actually used interactively.

Fixes Fission-AI#367

* chore: add ESLint with no-restricted-imports rule for @InQuirer

Add ESLint configuration that prevents static imports of @inquirer/*
modules. This prevents future regressions of the pre-commit hook hang
issue fixed in this PR.

The rule shows a helpful error message pointing to issue Fission-AI#367 for context.
init.ts is exempted since it's already dynamically imported from the CLI.

* ci: add ESLint step to lint job

Run `pnpm lint` in CI to enforce the no-restricted-imports rule
that prevents static @InQuirer imports.

* Add changeset for config command dynamic import fix (Fission-AI#393)

* chore(release): version packages (Fission-AI#394)

* Version Packages

* chore: trigger CI

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Tabish Bidiwale <[email protected]>

* fix(cli): respect --no-interactive flag in validate command (Fission-AI#395)

* fix(cli): respect --no-interactive flag in validate command

The validate command's spinner was starting regardless of the
--no-interactive flag, causing hangs in pre-commit hooks.

Changes:
- Pass noInteractive option to runBulkValidation
- Handle Commander.js --no-* flag syntax (sets interactive=false)
- Only start ora spinner when in interactive mode
- Add CI environment variable check to isInteractive() for industry
  standard compliance

* test: add unit tests for interactive utilities and CLI flag

- Export resolveNoInteractive() helper for reuse
- Add InteractiveOptions type export for testing
- Refactor validate.ts to use resolveNoInteractive()
- Add 17 unit tests for isInteractive() and resolveNoInteractive()
- Add CLI integration test for --no-interactive flag

This prevents future regressions where Commander.js --no-* flag
parsing is not properly handled.

* Add changeset for --no-interactive flag fix (Fission-AI#396)

* chore(release): version packages (Fission-AI#397)

* Version Packages

* chore: trigger CI

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Tabish Bidiwale <[email protected]>

* docs: add artifact POC analysis document (Fission-AI#398)

Add internal documentation for the artifact-based approach to OpenSpec
core. This document outlines design decisions, terminology, and the
philosophy behind treating dependencies as enablers rather than gates.

* fix(archive): allow REMOVED requirements when creating new spec files (Fission-AI#403) (Fission-AI#404)

When creating a new spec file, REMOVED requirements are now ignored
with a warning instead of causing archive to fail. This enables
refactoring scenarios where old fields are removed while documenting
a capability for the first time.

Fixes Fission-AI#403

---------

Co-authored-by: Tabish Bidiwale <[email protected]>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Tabish Bidiwale <[email protected]>
Co-authored-by: Eunsong-Park <[email protected]>
appboypov pushed a commit to appboypov/pew-pew-plx that referenced this pull request Dec 24, 2025
…ement (Fission-AI#382)

* feat(cli): add openspec config command for global configuration management

Implements the `openspec config` command with subcommands:
- `path`: Show config file location
- `list [--json]`: Show all current settings
- `get <key>`: Get a specific value (raw output for scripting)
- `set <key> <value> [--string]`: Set a value with auto type coercion
- `unset <key>`: Remove a key (revert to default)
- `reset --all [-y]`: Reset configuration to defaults
- `edit`: Open config in $EDITOR/$VISUAL

Key features:
- Dot notation for nested key access (e.g., featureFlags.someFlag)
- Auto type coercion (true/false → boolean, numbers → number)
- --string flag to force string storage
- Zod schema validation with unknown field passthrough
- Reserved --scope flag for future project-local config
- Windows-compatible editor spawning with proper path quoting
- Shell completion registry integration

* test(config): add additional unit tests for validation and coercion

- Add tests for unknown fields with various types
- Add test to verify error message path for featureFlags
- Add test for number values rejection in featureFlags
- Add config set simulation tests to verify full coerce → set → validate flow

* fix(config): avoid shell parsing in config edit to handle paths with spaces

Use spawn with shell: false and pass configPath as an argument instead
of building a shell command string. This correctly handles spaces in
both the EDITOR path and config file path on all platforms.

* chore(openspec): archive add-config-command and create cli-config spec

Move completed change to archive and apply spec deltas to create
the cli-config specification documenting the config command interface.

* Validate config keys on set
appboypov pushed a commit to appboypov/pew-pew-plx that referenced this pull request Dec 24, 2025
…ission-AI#392)

* fix(cli): use dynamic import for @inquirer/prompts in config command

The config command (added in Fission-AI#382) reintroduced the pre-commit hook hang
issue that was fixed in Fission-AI#380. The static import of @inquirer/prompts at
module load time causes stdin event listeners to be registered even when
running non-interactive commands, preventing clean process exit when
stdin is piped (as pre-commit does).

Convert the static import to a dynamic import that only loads inquirer
when the `config reset` command is actually used interactively.

Fixes Fission-AI#367

* chore: add ESLint with no-restricted-imports rule for @InQuirer

Add ESLint configuration that prevents static imports of @inquirer/*
modules. This prevents future regressions of the pre-commit hook hang
issue fixed in this PR.

The rule shows a helpful error message pointing to issue Fission-AI#367 for context.
init.ts is exempted since it's already dynamically imported from the CLI.

* ci: add ESLint step to lint job

Run `pnpm lint` in CI to enforce the no-restricted-imports rule
that prevents static @InQuirer imports.
appboypov pushed a commit to appboypov/pew-pew-plx that referenced this pull request Dec 24, 2025
…ement (Fission-AI#382)

* feat(cli): add openspec config command for global configuration management

Implements the `openspec config` command with subcommands:
- `path`: Show config file location
- `list [--json]`: Show all current settings
- `get <key>`: Get a specific value (raw output for scripting)
- `set <key> <value> [--string]`: Set a value with auto type coercion
- `unset <key>`: Remove a key (revert to default)
- `reset --all [-y]`: Reset configuration to defaults
- `edit`: Open config in $EDITOR/$VISUAL

Key features:
- Dot notation for nested key access (e.g., featureFlags.someFlag)
- Auto type coercion (true/false → boolean, numbers → number)
- --string flag to force string storage
- Zod schema validation with unknown field passthrough
- Reserved --scope flag for future project-local config
- Windows-compatible editor spawning with proper path quoting
- Shell completion registry integration

* test(config): add additional unit tests for validation and coercion

- Add tests for unknown fields with various types
- Add test to verify error message path for featureFlags
- Add test for number values rejection in featureFlags
- Add config set simulation tests to verify full coerce → set → validate flow

* fix(config): avoid shell parsing in config edit to handle paths with spaces

Use spawn with shell: false and pass configPath as an argument instead
of building a shell command string. This correctly handles spaces in
both the EDITOR path and config file path on all platforms.

* chore(openspec): archive add-config-command and create cli-config spec

Move completed change to archive and apply spec deltas to create
the cli-config specification documenting the config command interface.

* Validate config keys on set
appboypov pushed a commit to appboypov/pew-pew-plx that referenced this pull request Dec 24, 2025
…ission-AI#392)

* fix(cli): use dynamic import for @inquirer/prompts in config command

The config command (added in Fission-AI#382) reintroduced the pre-commit hook hang
issue that was fixed in Fission-AI#380. The static import of @inquirer/prompts at
module load time causes stdin event listeners to be registered even when
running non-interactive commands, preventing clean process exit when
stdin is piped (as pre-commit does).

Convert the static import to a dynamic import that only loads inquirer
when the `config reset` command is actually used interactively.

Fixes Fission-AI#367

* chore: add ESLint with no-restricted-imports rule for @InQuirer

Add ESLint configuration that prevents static imports of @inquirer/*
modules. This prevents future regressions of the pre-commit hook hang
issue fixed in this PR.

The rule shows a helpful error message pointing to issue Fission-AI#367 for context.
init.ts is exempted since it's already dynamically imported from the CLI.

* ci: add ESLint step to lint job

Run `pnpm lint` in CI to enforce the no-restricted-imports rule
that prevents static @InQuirer imports.
Kh05ifr4nD pushed a commit to Kh05ifr4nD/sorapec that referenced this pull request Jan 6, 2026
…ement (Fission-AI#382)

* feat(cli): add openspec config command for global configuration management

Implements the `openspec config` command with subcommands:
- `path`: Show config file location
- `list [--json]`: Show all current settings
- `get <key>`: Get a specific value (raw output for scripting)
- `set <key> <value> [--string]`: Set a value with auto type coercion
- `unset <key>`: Remove a key (revert to default)
- `reset --all [-y]`: Reset configuration to defaults
- `edit`: Open config in $EDITOR/$VISUAL

Key features:
- Dot notation for nested key access (e.g., featureFlags.someFlag)
- Auto type coercion (true/false → boolean, numbers → number)
- --string flag to force string storage
- Zod schema validation with unknown field passthrough
- Reserved --scope flag for future project-local config
- Windows-compatible editor spawning with proper path quoting
- Shell completion registry integration

* test(config): add additional unit tests for validation and coercion

- Add tests for unknown fields with various types
- Add test to verify error message path for featureFlags
- Add test for number values rejection in featureFlags
- Add config set simulation tests to verify full coerce → set → validate flow

* fix(config): avoid shell parsing in config edit to handle paths with spaces

Use spawn with shell: false and pass configPath as an argument instead
of building a shell command string. This correctly handles spaces in
both the EDITOR path and config file path on all platforms.

* chore(openspec): archive add-config-command and create cli-config spec

Move completed change to archive and apply spec deltas to create
the cli-config specification documenting the config command interface.

* Validate config keys on set
Kh05ifr4nD pushed a commit to Kh05ifr4nD/sorapec that referenced this pull request Jan 6, 2026
…ission-AI#392)

* fix(cli): use dynamic import for @inquirer/prompts in config command

The config command (added in Fission-AI#382) reintroduced the pre-commit hook hang
issue that was fixed in Fission-AI#380. The static import of @inquirer/prompts at
module load time causes stdin event listeners to be registered even when
running non-interactive commands, preventing clean process exit when
stdin is piped (as pre-commit does).

Convert the static import to a dynamic import that only loads inquirer
when the `config reset` command is actually used interactively.

Fixes Fission-AI#367

* chore: add ESLint with no-restricted-imports rule for @InQuirer

Add ESLint configuration that prevents static imports of @inquirer/*
modules. This prevents future regressions of the pre-commit hook hang
issue fixed in this PR.

The rule shows a helpful error message pointing to issue Fission-AI#367 for context.
init.ts is exempted since it's already dynamically imported from the CLI.

* ci: add ESLint step to lint job

Run `pnpm lint` in CI to enforce the no-restricted-imports rule
that prevents static @InQuirer imports.
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.

2 participants