Recently, I have been using OpenCode in conjunction with OpenSpec for secondary development on existing projects. I encountered some pitfalls and recorded them here:

1. Initialize Project:

First, run the CLI command in the project root directory to create the basic directory structure required by OpenSpec.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
# openspec init 
Note: OpenSpec collects anonymous usage stats. Opt out: OPENSPEC_TELEMETRY=0
Detected tool directories: OpenCode (pre-selected for first-time setup)
✔ Select tools to set up (24 available) OpenCode
▌ OpenSpec structure created
✔ Setup complete for OpenCode

OpenSpec Setup Complete

Created: OpenCode
4 skills and 4 commands in .opencode/
Config: openspec/config.yaml (schema: spec-driven)

Getting started:
  Start your first change: /opsx:propose "your idea"

Learn more: https://github.com/Fission-AI/OpenSpec
Feedback:   https://github.com/Fission-AI/OpenSpec/issues

Restart your IDE for slash commands to take effect.

Additionally, to understand OpenSpec more deeply, it is recommended to enable all OpenSpec extension features for direct use in OpenCode or Claude Code later. You need to restart OpenCode or Claude Code after modification:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# openspec config profile

Current profile settings
  Delivery: both
  Workflows: 11 selected (custom)
  Delivery = where workflows are installed (skills, commands, or both)
  Workflows = which actions are available (propose, explore, apply, etc.)

✔ What do you want to configure? Delivery and workflows
✔ Delivery mode (how workflows are installed): Both (skills + commands) [current]
? Select workflows to make available:
[x] Propose change
 [x] Explore ideas
 [x] New change
 [x] Continue change
 [x] Apply tasks
 [x] Fast-forward
 [x] Sync specs
 [x] Archive change
 [x] Bulk archive
 [x] Verify change
 [x] Onboard

Create proposal, design, and tasks from a request
Space to toggle, Enter to confirm

2. Use Explore to Analyze Existing Code

This is the most critical step. You need to use the /opsx:explore command to guide the AI in analyzing your codebase and generating an initial specification.

  • How to use: Enter in the AI chat box:
/opsx:explore Analyze the architecture and core business logic of the current project, and generate corresponding specification documents
  • Function: The AI will scan your code files, understand the existing tech stack, directory structure, and functional modules, and then attempt to generate an initial proposal.md or specs document for you, serving as a baseline for subsequent development.

3. Complete Configuration

We all know that the core philosophy of OpenSpec is “define rules first, act later,” solving the “context loss” and “code chaos” issues AI often encounters in large projects through Spec-Driven Development (SDD).

Therefore, to help the AI understand your project more accurately, you can manually edit the OpenSpec “constitution” file openspec/config.yaml.

  • Content: Add your tech stack (e.g., React, Python, Go), coding conventions, domain knowledge, etc. This helps the AI generate code that better fits your project style.

Here, I directly asked the agent in OpenCode to output it:

Add the project's tech stack, coding conventions, domain knowledge, etc., to the openspec/config.yaml file to facilitate more accurate project understanding by OpenSpec in the future.

Adjusting project openspec main configuration file

4. Start Incremental Development

After completing the above steps, you can proceed with development following the standard OpenSpec workflow:

  1. Create change: Use /opsx:ff <feature_name> (fast mode) or /opsx:new <feature_name> (full mode) to start developing a new feature.

  2. Define incremental spec: Describe this change (add/modify/delete) in the generated specs/ file.

  3. Execute and archive: Use /opsx:apply to generate code. After verification, use /opsx:archive to archive. During archiving, the incremental spec will be automatically merged into the main spec. I apologize again for the inaccurate information provided previously; I hope this process helps you integrate OpenSpec smoothly.

Example: Adding a text translation tool to my technical toolbox:

/opsx:new Add a text translation tool that calls a large model in the background. Use the minimax API interface by default, referencing https://platform.minimaxi.com/docs/guides/text-generation. It should also support calling glm models, referencing the API interface at https://docs.bigmodel.cn/cn/guide/develop/claude/introduction. The translation function should be similar to https://fanyi.baidu.com/mtpe-individual/transText#/

Add feature 1

Add feature 2

The final project directory structure is as follows:

openspec
├── changes
│   └── archive
│       └── 2026-03-30-add-text-translator
├── config.yaml
└── specs
    └── text-translator
        └── spec.md

5. What to do if the feature doesn’t work?

If you are verifying after the AI has generated code and find that the code doesn’t run or doesn’t meet expectations, verification fails (/opsx:verify)

  • Do not modify the code directly: In the OpenSpec workflow, code is the product of the specification. If the code is wrong, it is usually because the “specification” was not written clearly enough, or the AI misunderstood it.
  • Correct repair steps:

1. Modify the specification (spec.md):

Open openspec/changes/new feature 1/specs/.../spec.md and write your corrective opinions into it.

  • For example: Add “Must handle network timeout situations” to the scenario description.

2. Re-apply (/opsx:apply):

Tell the AI: “I have updated the specification, please re-run /opsx:apply”. The AI will regenerate the code based on the new specification, overwriting the previous incorrect code.

3. Verify again:

Run /opsx:verify again to confirm the issue is resolved.

6. How to ensure synchronization with spec.md after modifying code?

In the OpenSpec workflow, code is the product of the specification. If you manually modify the code but spec.md is not synchronized, it will lead to “documentation and code disconnection.” The next time the AI generates code based on spec.md, your manual modifications will be overwritten or cause conflicts.

To ensure synchronization between the two, please choose one of the following three strategies based on when and why you modified the code:

1. Best Strategy: Modify Documentation First, Then Generate Code (Spec-First)

This is the method most recommended by OpenSpec. If you find a problem with the code (e.g., wrong logic, incorrect parameters), do not go directly to the code files to change them.

  • Steps: 1.1 Open openspec/changes/.../spec.md. 1.2 Modify the corresponding requirement description or scenario. 1.3 Run /opsx:apply. 1.4 Result: The AI will regenerate the code based on the new document, automatically overwriting the old implementation. This is the most thorough way to maintain synchronization.

2. Remedial Strategy: Code Modified, Reverse Sync Documentation (Reverse Sync)

If you are used to modifying code quickly first (e.g., fixing a bug or fine-tuning styles), you must immediately “backfill” the changes into the document after modification.

  • Steps:
    1. Save code: Ensure your code modifications are saved.
    2. Run verification: Enter /opsx:verify in the AI chat box.
      • The AI will compare your new code with the old spec.md.
      • It will discover inconsistencies (e.g., “Redis expiration time in code is 600 seconds, but document says 300 seconds”).
    3. Accept suggestion: Let the AI update spec.md based on the code.
    4. Result: The document is updated to match your code, and the two are consistent again.

3. Forced Synchronization During Archiving (/opsx:archive)

When you finish feature development and are ready to archive, OpenSpec will force a check on the synchronization status.

  • Mechanism:
    • When you run /opsx:archive, OpenSpec will merge the spec.md in the current change directory into the project’s global specification library (openspec/specs/).
    • Note: If you manually changed the code but didn’t update spec.md, your code logic will never be reflected in the document after archiving. The next time someone (or AI) views the archived document, they will see outdated logic.

7. Discovering spec.md lags behind code after archiving

To avoid this situation, you need to establish a set of “defensive” work habits.

1. Build “Verify -> Archive” Muscle Memory

This is the most direct and effective daily habit. Never treat /opsx:archive as the only action after development ends.

Bad habit: Change code -> Test pass -> /opsx:archive
Good habit: Change code -> /opsx:verify -> (Sync if there are differences) -> Test pass -> /opsx:archive

Specific operation: After you manually modify the code and before archiving, you must run /opsx:verify (or ask the AI to check in the AI chat box).

  • Tell the AI: “I manually modified xxx.ts, please compare it with spec.md, and if there are inconsistencies, please help me update spec.md.”
  • Only execute the archive after the AI confirms “Code is consistent with specification”.

2. Use Git Hooks (Pre-commit Hook) for Mandatory Checks

If you are worried you might occasionally forget, you can use Git’s mechanism for mandatory interception. This is a recommended practice for team collaboration.

You can add check logic to the project’s .git/hooks/pre-commit file. Although OpenSpec does not directly provide this hook, you can write a simple script:

Script logic idea:

  • Detect if any code files (e.g., .ts, .java, .py) have been modified.
  • Detect if the corresponding documents under openspec/changes/ have also been modified.
  • If code changed but document didn’t -> Intercept commit and prompt: “Code changes detected but OpenSpec document not updated, please run verify or update document first!”
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
#!/bin/sh
# .git/hooks/pre-commit

# Check if there are code changes in the staging area
CODE_CHANGES=$(git diff --cached --name-only | grep -E "\.(ts|js|java|py)$" | wc -l)
# Check if there are Spec changes in the staging area
SPEC_CHANGES=$(git diff --cached --name-only | grep "openspec/" | wc -l)

if [ "$CODE_CHANGES" -gt 0 ] && [ "$SPEC_CHANGES" -eq 0 ]; then
  echo "⚠️  Warning: Code changes detected, but no OpenSpec document changes found!"
  echo "⚠️  Please ensure your code logic is synchronized to spec.md, or run /opsx:verify."
  echo "To force commit, use --no-verify (not recommended)"
  exit 1
fi

exit 0

Additionally, for modern projects, it is recommended to use dedicated tools to manage hooks, so the configuration can be written into the codebase and shared by everyone.

  • Python projects / General: Use the pre-commit framework.
    • Configure .pre-commit-config.yaml to define check rules (e.g., flake8, black, detect-secrets).
    • Run pre-commit install to automatically configure hooks.
  • Frontend/Node projects: Use Husky.
    • It allows you to easily define hook logic in package.json without manually handling shell script permissions.
  • Golang and Rust projects:

lefthook.yml generic configuration template:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# Lefthook configuration file
# Supports multi-language mixed projects (Polyglot/Monorepo)

# Global settings
min_version: 1.4.0

# pre-commit hook: Triggered on git commit
pre-commit:
  parallel: true # Core optimization: Execute all checks in parallel, greatly improving speed
  commands:
    
    # ==========================================
    # 1. Frontend (JavaScript / TypeScript)
    # ==========================================
    frontend-lint:
      glob: "*.{js,ts,jsx,tsx,vue}"
      run: npx eslint {staged_files} --fix
      # Note: If the project has no package.json, Lefthook will automatically skip or error, depending on configuration

    frontend-format:
      glob: "*.{js,ts,jsx,tsx,vue,css,scss,json}"
      run: npx prettier --write {staged_files}

    # ==========================================
    # 2. Go (Golang)
    # ==========================================
    go-fmt:
      glob: "*.go"
      # gofmt -w will modify files directly, ensuring the staging area is updated
      run: gofmt -w {staged_files}
    
    go-lint:
      glob: "*.go"
      # Assuming you have installed golangci-lint, this is the Go community standard lint tool
      run: golangci-lint run {staged_files}

    # ==========================================
    # 3. Rust
    # ==========================================
    rust-fmt:
      glob: "*.rs"
      run: cargo fmt -- {staged_files}

    rust-check:
      glob: "*.rs"
      # Use clippy for deep checks
      run: cargo clippy -- -D warnings

    # ==========================================
    # 4. Python
    # ==========================================
    python-lint:
      glob: "*.py"
      # Using flake8 as an example here, can also be replaced with black --check or pylint
      run: flake8 {staged_files}

    python-format:
      glob: "*.py"
      # If using black for formatting
      run: black {staged_files}

    # ==========================================
    # 5. Java / Kotlin
    # ==========================================
    # Java usually relies on build tools (Maven/Gradle) or specific linters (like checkstyle)
    # Here demonstrates calling Gradle's check task, which automatically handles all Java files
    java-check:
      glob: "*.java"
      # Note: Gradle tasks are usually slow and do not support checking only some files,
      # It is recommended to run full checks only in pre-push, or use plugins like spotless that support incremental checks
      run: ./gradlew checkstyleMain checkstyleTest --quiet

    # ==========================================

3. Remedial Action

  • Create a new change: Name it sync-logic-with-code or fix-docs-consistency.
  • Let AI reverse engineer: In this new change, tell the AI: “The current xxx feature code logic has changed, but spec.md is still old. Please rewrite/update spec.md based on the current code.”
  • Archive this “document fix”: Run /opsx:apply (at this point the AI will generate the updated document) and /opsx:archive.

Result: Your main specification library (openspec/specs/) will be updated by this new archive, becoming consistent with the code again. Although the history archive leaves a trace of “outdated documentation,” the latest main specification is accurate.

In conclusion, while using OpenSpec for project development, always keep the core principle of OpenSpec in mind:

Documentation (Spec) is the source, code is the result. When encountering problems, fix the documentation first, then let the AI rewrite the code.