Skip to content

CLI ​

openspec 터미널 명령어입니다.

명령어 ​

설정

명령어설명
openspec init프로젝트에서 OpenSpec을 초기화합니다.
openspec updateOpenSpec이 설치한 지침 파일을 업데이트합니다.
openspec config전역 설정을 확인하고 변경합니다.

변경 사항 및 스펙

명령어설명
openspec list변경 사항 목록을 표시하며, --specs 옵션으로 스펙 목록을 표시합니다.
openspec show변경 사항이나 스펙을 markdown 또는 JSON 형식으로 출력합니다.
openspec view스펙과 변경 사항을 한 화면에서 볼 수 있는 대시보드를 표시합니다.
openspec validate변경 사항과 스펙의 구조적 문제를 검사합니다.
openspec archive완료된 변경 사항을 아카이브로 이동하고 메인 스펙을 업데이트합니다.

워크플로우 및 스키마

대부분의 명령어는 워크플로우 진행 중 에이전트가 실행합니다.

명령어설명
openspec new새로운 변경 사항 디렉토리를 생성합니다.
openspec status하나 또는 모든 활성 변경 사항의 아티팩트 완료 상태를 표시합니다.
openspec instructions아티팩트 생성, 적용, 또는 아카이빙에 대한 지침을 표시합니다.
openspec templates스키마의 아티팩트에 대한 확인된 템플릿 경로를 표시합니다.
openspec schemas사용 가능한 워크플로우 스키마 목록을 표시합니다.
openspec schema스키마를 검사, 포크, 또는 생성합니다 (실험적).

멀티 저장소 (베타)

명령어설명
openspec store스토어를 생성하고 관리합니다. 스토어는 머신에 등록된 독립형 OpenSpec 저장소입니다.
openspec doctor확인된 OpenSpec 루트의 관계 상태를 보고합니다.
openspec context확인된 OpenSpec 루트의 작업 컨텍스트를 출력합니다.
openspec workset개인 작업 뷰를 구성하고, 유지하고, 엽니다.

유틸리티

명령어설명
openspec version설치된 버전을 표시하며, 선택적으로 업데이트 여부를 확인합니다.
openspec installNode.js 없이 실행되는 독립형 openspec을 설치합니다.
openspec feedbackOpenSpec에 대한 피드백을 제출합니다.
openspec completion셸 자동 완성을 설치하거나 생성합니다.

지원 중단

명령어설명
openspec change변경 사항에 대한 show, list, validate의 명사형입니다. CLI는 경고를 표시하고 동사 우선 명령어를 안내합니다.
openspec spec스펙에 대한 show, list, validate의 명사형으로, 동일한 경고가 표시됩니다.

모든 명령어는 -h, --help 옵션을 지원합니다. 옵션 없이 실행하는 openspec 명령어도 다음 옵션을 지원합니다:

  • -V, --version: CLI 버전을 출력합니다.
  • --no-color: 색상 출력을 비활성화합니다.

openspec init ​

프로젝트에서 OpenSpec을 초기화합니다.

bash
openspec init                        # 현재 디렉터리, 대화형 도구 선택기
openspec init --tools claude,cursor  # 특정 도구 설정, 프롬프트 없음
openspec init --tools none           # openspec/ 구조만, 도구 파일 없음

--tools가 없으면 init은 대화형 터미널에서 도구를 선택하라는 프롬프트를 표시합니다. 대화형 터미널이 아니면 프로젝트에서 감지한 도구를 설정합니다. 감지된 도구가 없으면 종료 코드 1로 종료하고 유효한 id를 나열합니다.

스토어 전용 저장소

openspec/config.yaml에 store: 줄이 있고 저장소에 로컬 스펙이나 변경 사항이 없으면 저장소 루트에서 init을 실행하세요:

bash
# 코드 저장소에 Claude Code 통합 파일 설치
openspec init --tools claude
  • 통합 파일: 코드 저장소에 기록됩니다.
  • openspec/config.yaml: 바이트 단위로 그대로 보존됩니다.
  • openspec/specs/ 및 openspec/changes/: 코드 저장소에 생성되지 않습니다.

하위 디렉터리에서 init을 실행하면 종료 코드 1로 종료되고 저장소 루트에서 실행하라고 안내합니다. --language도 종료 코드 1로 종료됩니다. 언어는 외부 스토어의 구성에 속하기 때문입니다. 스토어 루트에서 init을 실행하거나 해당 구성을 직접 편집하세요.

인수

인수설명
path초기화할 프로젝트 디렉터리입니다. 기본값: 현재 디렉터리. 없으면 생성됩니다.

옵션

플래그효과
--tools <tools>쉼표로 구분된 도구 id, all 또는 none. 선택기를 건너뜁니다. id는 지원되는 도구에 나열되어 있습니다.
--language <language>새 프로젝트 구성에 언어 지침을 추가합니다. 저장소의 store: 줄이 외부 스토어를 가리키면 거부됩니다.
--force이전 OpenSpec 레이아웃의 파일을 묻지 않고 제거합니다. 그 외의 경우 대화형 실행에서는 정리 작업을 먼저 확인합니다.
--profile <profile>이번 실행에 한해 전역 구성 프로필을 재정의합니다: core(표준 워크플로 세트) 또는 custom(전역 구성에 저장된 워크플로).
--no-animation애니메이션 환영 화면 대신 정적 환영 화면을 표시합니다.

출력

선택된 각 도구는 자체 디렉터리에 OpenSpec의 스킬과 명령을 받습니다:

▌ OpenSpec structure created
✔ Setup complete for Claude Code

OpenSpec Setup Complete

Created: Claude Code
6 skills and 6 commands in .claude/
Config: openspec/config.yaml (schema: spec-driven)

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

Restart your IDE for the new commands to take effect.

--tools none은 openspec/config.yaml만 생성합니다. 이미 초기화된 프로젝트에서 init은 설치된 파일을 제자리에서 다시 작성하며, 요약에는 Refreshed: Claude Code와 Config: openspec/config.yaml (exists)가 표시됩니다.

종료 코드

  • 0: 설정이 완료되었습니다.
  • 1: 유효하지 않은 --tools 또는 --profile 값, 도구가 감지되지 않았고 --tools도 없는 비대화형 실행, 또는 유효하지 않은 스토어 전용 호출입니다.

openspec update ​

설치된 OpenSpec 지침 파일을 업데이트합니다.

bash
openspec update             # CLI보다 파일이 오래된 도구 새로 고침
openspec update --force     # 파일이 최신이어도 다시 작성
openspec update --dry-run   # 업데이트로 변경될 내용을 나열하고 아무것도 변경하지 않음

update는 init이 구성한 도구를 찾아 생성된 파일을 CLI 버전과 비교합니다. 더 새로운 OpenSpec 릴리스가 있으면 먼저 CLI 업그레이드를 제안한 다음 업그레이드된 버전으로 다시 실행합니다. 검사를 건너뛰려면 OPENSPEC_NO_UPDATE_CHECK=1을 설정하세요.

인수

인수설명
path업데이트할 프로젝트 디렉터리입니다. 기본값: 현재 디렉터리.

옵션

플래그효과
--force구성된 모든 도구의 파일이 최신이어도 다시 작성합니다.
--dry-run업데이트가 추가, 변경 또는 삭제할 모든 파일을 보고하고 아무것도 기록하지 않습니다. CLI 업그레이드 검사와 프롬프트는 없습니다. --force와 함께 사용하면 강제 업데이트를 미리 볼 수 있습니다.
--json--dry-run과 함께 사용하면 계획을 JSON으로 출력합니다. --dry-run 없이 사용하면 종료 코드 1로 종료됩니다.

업데이트 미리 보기

--dry-run은 비대화형 실행이 수행할 업데이트를 계획합니다. 동일한 코드 경로를 사용하되 모든 쓰기와 삭제를 실제로 수행하는 대신 기록합니다. 실제 업데이트가 건드릴 모든 파일이 나열되며, 다음이 포함됩니다:

  • 도구의 이전 디렉터리에서 OpenSpec 파일 이동(.kimi/에서 .kimi-code/, .windsurf/에서 .devin/, .codex/ 및 .agent/에서 .agents/);
  • 프로필 이전 버전의 설치가 전역 구성을 갖추게 될 때 해당 구성 저장;
  • GitHub Copilot 클라우드 에이전트 파일 동기화;
  • --force 사용 시 레거시 아티팩트에서만 발견된 도구를 설정하고 해당 아티팩트를 정리하며, 여기에는 사용 중단된 전역 Codex 프롬프트도 포함됩니다.
bash
openspec update --dry-run
2 file(s) would change:
  update  .claude/skills/openspec-propose/SKILL.md  (claude)
  add     ~/.config/openspec/config.json  (openspec)

--dry-run --json은 동일한 계획을 하나의 JSON 문서로 출력합니다:

json
{
  "changes": [
    { "path": ".claude/skills/openspec-propose/SKILL.md", "action": "update", "tool": "claude" },
    { "path": "~/.config/openspec/config.json", "action": "add", "tool": "openspec" }
  ],
  "notes": [],
  "failures": []
}
필드설명
changes[].path프로젝트 기준 상대 경로입니다. 전역 스킬이나 전역 구성처럼 프로젝트 외부에 있는 파일은 홈 디렉터리 기준 ~/...로 표시되며, 홈 디렉터리 외부에 있으면 절대 경로로 표시됩니다.
changes[].actionadd, update 또는 delete. 새 바이트가 이전 바이트와 동일한 파일은 나열되지 않습니다.
changes[].tool파일이 속한 구성된 도구입니다(예: claude). 특정 도구가 아니라 OpenSpec 자체에 속한 파일, 전역 구성 및 레거시 아티팩트 정리는 openspec입니다.
notes[]터미널 사용자에게 질문할 단계에 대한 { code, message }입니다. legacy-tool-directories: 대화형 실행에서 먼저 확인하는 이동입니다. changes에는 수행된 것으로 나열됩니다. legacy-artifacts: OpenSpec의 이전 레이아웃에서 나온 파일이 발견된 경우입니다. 예를 들어 openspec-proposal.md 슬래시 명령이나 AGENTS.md의 OpenSpec 마커 블록이 있습니다. --force가 없으면 비대화형 업데이트는 해당 파일을 그대로 두므로 changes도 그대로 둡니다. --dry-run --force는 해당 파일의 정리를 나열합니다. 일반 새로 고침에서는 비어 있습니다.
failures[]실제 업데이트가 실패할 각 도구에 대한 { tool, error }입니다. 수행할 수 없는 쓰기도 포함됩니다. 파일이 있어야 할 위치에 디렉터리가 있거나, 디렉터리가 있어야 할 위치에 파일이 있거나, 쓰기 권한이 없는 파일 또는 폴더가 있는 경우입니다. 해당 도구의 경우 changes는 실제 업데이트가 중단되는 지점에서 중단되며, 다른 도구는 계속 계획됩니다. 디스크 공간 부족처럼 쓰는 동안에만 디스크가 보고하는 실패는 미리 예측할 수 없습니다.

계획 수립 전의 실패(예: OpenSpec 디렉터리 없음)도 정확히 하나의 JSON 문서를 출력합니다. 빈 계획과 severity, code(update_error), message가 포함된 status 배열입니다. 종료 코드는 1입니다.

출력

모든 도구의 파일이 CLI 버전과 일치할 때:

✓ All 1 tool(s) up to date (v1.7.0)
  Tools: claude

Use --force to refresh files anyway.

도구의 파일이 이전 CLI에서 생성된 경우(또는 --force 사용 시, 이때는 대신 Force updating 1 tool(s): claude가 출력됨):

Updating 1 tool(s): claude (1.6.0 → 1.7.0)

✔ Updated Claude Code

✓ Updated: Claude Code (v1.7.0)
Tools: Claude Code

Restart your IDE for changes to take effect.

OpenSpec이 없는 디렉터리에서는 update가 거부합니다:

✖ Error: No OpenSpec directory found. Run 'openspec init' first.

종료 코드

  • 0: 파일이 업데이트되었거나 모두 이미 최신 상태입니다.
  • 1: 해당 경로에 OpenSpec 디렉터리가 없거나 업데이트가 실패했습니다.

openspec config ​

전역 구성을 조회하고 변경합니다.

bash
openspec config list                  # 현재 설정 보기
openspec config set delivery skills   # 값 하나 변경
openspec config profile               # 대화형 워크플로 선택기
하위 명령설명
path구성 파일 위치를 출력합니다.
list현재의 모든 설정을 표시합니다.
get <key>값 하나를 원시 형태로 출력하며 스크립트에서 사용할 수 있습니다.
set <key> <value>값을 설정하며 유형을 강제 변환합니다.
unset <key>키를 제거하여 기본값이 적용되게 합니다.
reset모든 구성을 기본값으로 재설정합니다.
edit$EDITOR에서 구성 파일을 엽니다.
profile [preset]delivery 모드와 워크플로를 구성합니다.

구성은 머신 전역이며 config path가 가리키는 위치에 JSON으로 저장됩니다. $XDG_CONFIG_HOME이 설정되어 있으면 $XDG_CONFIG_HOME/openspec/config.json, 그렇지 않으면 ~/.config/openspec/config.json(macOS, Linux) 또는 %APPDATA%\openspec\config.json(Windows)입니다. 모든 하위 명령은 --scope <scope>를 받지만 현재는 global만 작동합니다. 다른 스코프는 Error: Project-local config is not yet implemented와 함께 종료 코드 1로 종료됩니다.

openspec config path ​

bash
openspec config path
/Users/you/.config/openspec/config.json

openspec config list ​

bash
openspec config list          # 읽기 쉬운 설정과 프로필 요약
openspec config list --json   # JSON 형식의 원시 구성

옵션

플래그효과
--json구성 객체를 JSON으로 출력합니다.

출력

각 설정을 표시한 다음, 값이 명시적인지 기본값인지 표시하는 프로필 요약을 표시합니다:

featureFlags: {}
profile: core
delivery: both

Profile settings:
  profile: core (default)
  delivery: both (default)
  workflows: propose, explore, apply, update, sync, archive (from core profile)

openspec config get ​

bash
openspec config get delivery

인수

인수설명
key읽을 키입니다. 점을 사용하면 중첩 값에 접근할 수 있습니다(featureFlags.workspaces).

출력

스크립트에서 사용할 수 있는 원시 값입니다. 객체는 압축 JSON으로 출력됩니다:

both

종료 코드

  • 0: 값이 출력되었습니다.
  • 1: 키에 값이 없으며 아무것도 출력되지 않습니다.

openspec config set ​

bash
openspec config set delivery skills
openspec config set featureFlags.workspaces true

인수

인수설명
key기록할 키입니다. 중첩 값에는 점 표기법을 사용합니다.
value새 값입니다. true/false는 불리언이 되고, 숫자 문자열은 숫자가 됩니다.

옵션

플래그효과
--string유형 강제 변환을 건너뛰고 값을 문자열로 저장합니다.
--allow-unknown스키마가 알지 못하는 키를 허용합니다.

출력

Set featureFlags.workspaces = true

알 수 없는 키와 유효하지 않은 값은 아무것도 저장되기 전에 종료 코드 1로 실패합니다:

Error: Invalid configuration key "bogus.key". Unknown top-level key "bogus".
Use "openspec config list" to see available keys.
Pass --allow-unknown to bypass this check.
Error: Invalid configuration - delivery: Invalid option: expected one of "both"|"skills"|"commands"

구성 파일이 존재하지만 JSON 객체를 담고 있지 않은 경우, 즉 전혀 유효한 JSON이 아니거나 루트가 null 또는 배열과 같은 다른 것인 경우 config set, config unset, config profile은 종료 코드 1로 종료되고 파일을 변경하지 않습니다. openspec config edit로 수정하거나 openspec config reset --all로 교체하세요:

Error: /home/you/.config/openspec/config.json could not be parsed, so it was left unchanged.
Fix it with "openspec config edit", or reset it with "openspec config reset --all".

수정될 때까지 텔레메트리와 업데이트 검사는 꺼진 상태로 유지됩니다.

openspec config unset ​

bash
openspec config unset delivery

키를 제거하여 기본값이 다시 적용되게 합니다. 내장 기본값이 있는 키는 항상 설정된 것으로 간주되므로, 설정한 적이 없어도 성공으로 보고합니다:

Unset delivery (reverted to default)

값이 전혀 없는 키는 Key "featureFlags.nothere" was not set를 출력합니다. 두 경우 모두 종료 코드 0으로 종료됩니다. 구문 분석할 수 없는 구성 파일은 config set과 마찬가지로 대신 종료 코드 1로 종료됩니다.

openspec config reset ​

bash
openspec config reset --all      # 확인 요청
openspec config reset --all -y   # 프롬프트 없음

옵션

플래그효과
--all필수입니다. 모든 항목을 재설정합니다.
-y, --yes확인 프롬프트를 건너뜁니다.

출력

Configuration reset to defaults

--all 없이 실행하면 종료 코드 1로 종료되고 사용법 줄을 출력합니다.

종료 코드

  • 0: 재설정이 완료되었거나 프롬프트에서 아니요를 선택했습니다.
  • 1: --all이 누락되었습니다.
  • 130: Ctrl-C로 프롬프트가 취소되었습니다.

openspec config edit ​

bash
openspec config edit

$EDITOR(없으면 $VISUAL)에서 구성 파일을 엽니다. 파일이 없으면 먼저 기본값으로 생성합니다. 편집기가 닫히면 파일이 검증됩니다. 유효하지 않은 JSON 또는 유효하지 않은 구성은 종료 코드 1로 종료됩니다.

편집기 값에는 인수와 따옴표로 묶인 경로가 포함될 수 있습니다. 예: code --wait 또는 "/Applications/Sublime Text.app/Contents/SharedSupport/bin/subl" -w. 이 값은 셸 없이 단어로 분리되므로 $VAR, ~, ;는 문자 그대로 전달됩니다. 시작할 수 없거나 0이 아닌 값으로 종료되는 편집기는 한 줄 오류를 출력하고 종료 코드 1로 종료됩니다.

편집기가 구성되지 않은 경우 종료 코드 1로 종료됩니다:

Error: No editor configured
Set the EDITOR or VISUAL environment variable to your preferred editor
Example: export EDITOR=vim

openspec config profile ​

bash
openspec config profile        # 대화형 선택기(터미널 필요)
openspec config profile core   # core 프리셋을 직접 적용

인수

인수설명
preset선택적 프리셋 이름입니다. core만 존재합니다. core 워크플로를 선택하고 delivery 설정은 유지합니다.

프리셋이 없으면 대화형 선택기가 현재 delivery와 워크플로를 표시하고, 둘 중 하나 또는 모두를 변경할 수 있게 합니다(delivery: both, skills only, commands only; workflows: 체크박스 목록). 그런 다음 차이를 출력하고, OpenSpec 프로젝트 내부라면 openspec update 실행을 제안합니다. 터미널이 아니면 종료 코드 1로 종료됩니다:

Interactive mode required. Use `openspec config profile core` or set config via environment/flags.

출력

변경된 구성은 프로젝트가 업데이트하기 전까지 프로젝트에 적용되지 않습니다:

Config updated. Run `openspec update` in your projects to apply.

종료 코드

  • 0: 프로필이 저장되었거나 현재 설정을 유지했습니다.
  • 1: 알 수 없는 프리셋, 터미널 없음, 또는 제안된 openspec update 실패입니다.
  • 130: Ctrl-C로 선택기가 취소되었습니다.

openspec list ​

변경 사항 또는 --specs 사용 시 spec을 나열합니다.

bash
openspec list                    # 활성 변경 사항, 가장 최근에 수정된 것부터
openspec list --archived         # 보관된 변경 사항
openspec list --all              # 활성 및 보관된 변경 사항
openspec list --specs            # requirement 개수가 포함된 spec
openspec list --json             # 기계 판독 가능, 확인된 루트 포함

행은 확인된 루트 아래의 openspec/changes/ 및 openspec/specs/에서 가져옵니다. 기본 변경 사항 목록은 openspec/changes/archive/를 건너뜁니다.

옵션

플래그효과
--specs변경 사항 대신 spec을 나열합니다.
--changes변경 사항을 나열합니다. 기본값입니다.
--archived보관된 변경 사항만 나열합니다. --specs와 함께 사용할 수 없습니다.
--all활성 및 보관된 변경 사항을 나열합니다. --specs와 함께 사용할 수 없습니다. --archived보다 우선합니다.
--sort <order>recent (최근 수정된 것부터) 또는 name. 기본값: recent. spec은 항상 이름순으로 정렬됩니다.
--json테이블 대신 JSON을 출력합니다.
--store <id>현재 프로젝트 대신 등록된 스토어를 OpenSpec 루트로 사용합니다.

출력

변경 사항당 하나의 행: 이름, 작업 상태, 마지막 수정일. 상태 열은 No tasks, 2/5 tasks, 또는 ✓ Complete로 표시됩니다.

Changes:
  add-rate-limit     No tasks      just now

--all은 활성 및 보관된 변경 사항을 별도의 제목 아래에 그룹화합니다. 각 그룹은 선택된 정렬 순서를 사용합니다:

Changes:
  add-rate-limit     No tasks      just now

Archived Changes:
  2026-08-10-add-login     ✓ Complete    2d ago
Specs:
  api     requirements 1

--json은 작업 개수와 no-tasks, in-progress, complete 상태를 추가합니다:

json
{
  "changes": [
    {
      "name": "add-rate-limit",
      "completedTasks": 0,
      "totalTasks": 0,
      "lastModified": "2026-08-11T13:44:40.171Z",
      "status": "no-tasks"
    }
  ],
  "root": {
    "path": "/Users/you/projects/my-app",
    "source": "nearest"
  }
}

--archived 또는 --all을 사용하면 모든 변경 사항 객체에 archived 불리언이 포함됩니다. 결합된 배열은 선택된 정렬 순서를 사용합니다. 보관된 변경 사항은 추적 중인 작업 파일에 확인되지 않은 작업이 있을 때 in-progress 상태를 가질 수 있습니다. 두 플래그 모두 없이 사용하면 JSON 형태는 변경되지 않습니다.

빈 목록은 No active changes found., No archived changes found., No changes found., 또는 No specs found.를 출력하고 종료 코드 0으로 종료됩니다.

변경 사항은 openspec/changes/ 바로 아래의 디렉토리입니다. spec과 달리 변경 사항은 네임스페이스 폴더에 중첩될 수 없습니다. 변경 사항만 감싸는 changes/mobile/과 같은 폴더(changes/mobile/refresh-token/)는 not a change 상태로 나열되고, 중첩된 디렉토리 이름을 지정하는 경고가 이어집니다. --json은 해당 항목에 nested 배열로 표시하고 최상위 warnings 배열을 추가합니다. show, status, validate 및 archive는 동일한 메시지로 해당 폴더를 거부합니다. 수정하려면 변경 사항을 위로 이동하고 네임스페이스를 이름에 포함하세요:

bash
mv openspec/changes/mobile/refresh-token openspec/changes/mobile-refresh-token
rmdir openspec/changes/mobile

종료 코드

  • 0: 목록이 출력됨, 비어 있어도.
  • 1: OpenSpec 루트를 찾을 수 없음 (프로젝트 외부, --store 없음).

openspec show ​

변경 사항 또는 spec을 markdown 또는 JSON으로 출력합니다.

bash
openspec show add-rate-limit              # 변경 사항: proposal.md 출력
openspec show add-rate-limit --diff       # 변경 사항: requirement diff 추가
openspec show api                         # spec: spec.md 출력
openspec show api --json --no-scenarios   # 시나리오 텍스트 없는 spec JSON

이름이 없으면 show가 변경 사항 또는 spec을 묻고 선택할 항목을 나열합니다. 대화형 터미널 외부에서는 종료 코드 1로 종료되고 직접 형식을 출력합니다.

인수

인수설명
item-name폴더 이름(add-rate-limit, api)으로 표시할 변경 사항 또는 spec.

옵션

플래그효과
--json원시 markdown 대신 구조화된 JSON을 출력합니다.
--type <change|spec>변경 사항과 spec이 같은 이름을 공유할 때 유형을 선택합니다.
--no-interactive프롬프트 없음: 누락된 이름은 오류가 됩니다.
--deltas-onlyJSON, 변경 사항: 출력을 delta로 제한합니다. 변경 사항 JSON은 이미 delta만 포함하므로 출력은 일반 --json과 일치합니다.
--requirements-only--deltas-only의 더 이상 사용되지 않는 별칭입니다. stderr에 경고합니다.
--diff변경 사항: requirement별 delta diff를 추가합니다. spec의 경우 경고와 함께 무시됩니다.
--requirementsJSON, spec: requirement 텍스트를 유지하고 scenarios 배열을 비웁니다.
--no-scenariosJSON, spec: --requirements와 동일한 출력.
-r, --requirement <id>JSON, spec: 1부터 시작하는 위치로 하나의 requirement를 출력합니다. --requirements와 함께 사용할 수 없습니다.
--store <id>현재 프로젝트 대신 등록된 스토어를 OpenSpec 루트로 사용합니다.

확인된 유형에 적용되지 않는 플래그는 stderr에 경고와 함께 무시됩니다.

출력

텍스트 모드는 원시 패스스루입니다: 변경 사항은 proposal.md를 출력하고, spec은 spec.md를 출력합니다.

# Add rate limiting

## Why
Unauthenticated clients can exhaust the API.

## What Changes
- Add per-client rate limiting to the public API.

변경 사항의 경우 --diff는 먼저 제안(proposal)을 출력한 다음 Specifications Changed (diffs) 섹션을 출력합니다. ADDED 요구사항은 전체 텍스트를 포함합니다. REMOVED 요구사항은 작성된 Reason과 Migration을 유지합니다. RENAMED 요구사항은 FROM과 TO를 표시합니다. MODIFIED 요구사항은 일치하는 메인 요구사항에 대한 unified diff를 표시합니다.

MODIFIED 헤더가 대소문자나 공백 차이를 무시한 후에야 일치하는 경우, 출력에는 diff와 함께 아카이브 매칭은 정확히 일치해야 한다는 경고가 포함됩니다. 메인 스펙이나 요구사항이 없는 경우, 출력은 경고를 표시하고 전체 델타 블록을 출력합니다. 텍스트상 차이가 없는 MODIFIED 블록은 (no textual changes)를 출력합니다.

--json으로 조회한 변경 사항은 델타 형태입니다:

json
{
  "id": "add-rate-limit",
  "title": "Add rate limiting",
  "deltaCount": 1,
  "deltas": [
    {
      "spec": "api",
      "operation": "ADDED",
      "description": "Add requirement: The API SHALL limit each client to 100 requests per minute.",
      "requirement": {
        "name": "Rate limit",
        "text": "The API SHALL limit each client to 100 requests per minute.",
        "scenarios": [
          {
            "name": "Client exceeds the limit",
            "rawText": "- **WHEN** a client sends its 101st request within a minute\n- **THEN** the API responds 429"
          }
        ]
      },
      ...
    }
  ],
  "root": {
    "path": "/Users/you/projects/my-app",
    "source": "nearest"
  }
}

각 요구사항은 name을 가지며, 이는 Requirement: 뒤에 오는 헤더 텍스트입니다. 이 이름이 archive가 MODIFIED, REMOVED, RENAMED 항목을 매칭할 때 비교 기준으로 사용하는 이름입니다. 각 시나리오는 name을 가지며, 이는 Scenario: 뒤에 오는 헤더 텍스트입니다. 어느 쪽 헤더든 뒤에 붙는 # 문자열은 이름의 일부가 아닙니다.

--json --diff는 이 최상위 구조를 유지합니다. MODIFIED 델타에는 diff 문자열, warning 문자열 또는 둘 모두가 추가됩니다. 다른 연산은 변경되지 않습니다. 빈 diff 문자열은 메인 블록과 델타 블록이 텍스트상 동일함을 의미합니다.

--json으로 조회한 스펙은 시나리오와 함께 요구사항을 나열합니다. 요구사항과 시나리오는 변경 사항 JSON과 동일한 name 필드를 가집니다:

json
{
  "id": "api",
  "title": "api",
  "overview": "Public HTTP API behavior.",
  "requirementCount": 1,
  "requirements": [
    {
      "name": "Health endpoint",
      "text": "The API SHALL expose a health endpoint.",
      "scenarios": [
        {
          "name": "Health check succeeds",
          "rawText": "- **WHEN** a client requests GET /health\n- **THEN** the API responds 200"
        }
      ]
    }
  ],
  "metadata": {
    "version": "1.0.0",
    "format": "openspec"
  },
  "root": {
    "path": "/Users/you/projects/my-app",
    "source": "nearest"
  }
}

알 수 없는 이름에 대해서는 유사한 후보를 제안합니다: Unknown item 'does-not-exist'. Did you mean: add-rate-limit, api?. 변경 사항과 스펙 양쪽 모두에 매칭되는 이름은 오류를 발생시키며 --type을 요구합니다.

종료 코드

  • 0: 항목이 출력됨.
  • 1: 알 수 없거나 모호한 이름, 터미널이 아닌 환경에서 이름이 지정되지 않음, 범위를 벗어난 -r 인덱스, -r과 함께 사용된 --requirements, 또는 --diff를 위해 읽어야 할 델타나 메인 스펙을 읽을 수 없는 경우.

openspec view ​

스펙과 변경 사항에 대한 한 화면 분량의 대시보드를 출력합니다.

bash
openspec view   # 한 화면에 프로젝트 요약

view는 대시보드를 한 번 출력한 뒤 종료합니다. 키 입력은 전혀 읽지 않습니다. 변경 사항은 작업 진행 상황에 따라 그룹화됩니다: Draft(아직 작업 없음), Active(작업 진행 중, 진행 표시줄과 퍼센트 표시), Completed(모든 작업 체크 완료). 스펙은 요구사항 수와 함께 나열되며, 요구사항이 가장 많은 것부터 표시됩니다.

옵션

플래그효과
--store <id>현재 프로젝트 대신 등록된 스토어를 OpenSpec 루트로 사용합니다.

출력

OpenSpec Dashboard

════════════════════════════════════════════════════════════
Summary:
  ● Specifications: 1 specs, 1 requirements
  ● Draft Changes: 1
  ● Active Changes: 0 in progress
  ● Completed Changes: 0

Draft Changes
────────────────────────────────────────────────────────────
  ○ add-rate-limit

Specifications
────────────────────────────────────────────────────────────
  ▪ api                            1 requirement

════════════════════════════════════════════════════════════

Use openspec list --changes or openspec list --specs for detailed views

변경 사항 중 하나라도 진행 중인 작업이 있으면 Task Progress 요약 줄이 나타납니다.

각 활성 변경 사항은 작업 진행 표시줄 아래에 자체 스키마와 아티팩트 상태도 함께 표시합니다:

text
    └─ [spec-driven] proposal✓ specs→ design→ tasks✓
마커아티팩트 상태
✓출력물이 존재합니다. 기존 tasks 아티팩트는 체크리스트가 끝나지 않았어도 완료로 간주됩니다.
→생성할 준비가 된 상태입니다.
마커 없음필요한 의존성이 없어 차단된 상태입니다.
(skipped)해당 변경 사항이 이 아티팩트를 건너뜁니다.

워크플로우를 로드할 수 없는 경우, view는 경고를 출력하면서 해당 변경 사항의 작업 진행 상황은 계속 보여줍니다. 워크플로우를 별도로 확인하려면 openspec status --change <name>을 실행하세요. openspec view --store <id>를 실행한 후에는 status에 동일한 --store <id>를 전달하세요.

종료 코드

  • 0: 대시보드가 출력됨.
  • 1: OpenSpec 루트를 찾을 수 없음 (프로젝트 밖, --store 없음).

openspec validate ​

변경 사항과 스펙의 구조적 문제를 검사합니다.

bash
openspec validate add-rate-limit   # 이름으로 하나의 변경 사항 또는 스펙
openspec validate --all            # 모든 변경 사항과 스펙

이름과 벌크 플래그가 모두 없으면 validate는 항목을 선택하라는 프롬프트를 표시합니다. 대화형 터미널이 아닌 환경에서는 종료 코드 1로 종료하며 그 대신 벌크 플래그들을 출력합니다.

인자

인자설명
item-name검증할 변경 사항 또는 스펙의 폴더 이름 (add-rate-limit, api).

옵션

플래그효과
--all모든 변경 사항과 스펙을 검증합니다.
--changes모든 변경 사항을 검증합니다.
--specs모든 스펙을 검증합니다.
--archived아카이브된 변경 사항에서 작업 완료 여부를 검사하되, 적용된 스펙 델타는 검증하지 않습니다.
--strict경고를 실패로 처리합니다.
--type <change|spec>변경 사항과 스펙이 이름을 공유할 때 타입을 선택합니다.
--json텍스트 대신 구조화된 보고서를 출력합니다.
--report <mode>벌크 출력: full(기본값) 또는 findings. 명시적인 벌크 범위가 필요합니다.
--concurrency <n>벌크 실행에서 최대 병렬 검증 수. 기본값: OPENSPEC_CONCURRENCY, 없는 경우 6.
--no-interactive절대 프롬프트를 표시하지 않음: 없거나 모호한 이름은 오류가 됩니다.
--store <id>현재 프로젝트 대신 등록된 스토어를 OpenSpec 루트로 사용합니다.

출력

벌크 실행은 항목마다 상태 줄을 하나씩 출력하고, 그 뒤에 발견 사항이 있다면 이어서 출력하며, 마지막에 총계로 끝납니다:

✓ change/add-rate-limit
✓ spec/api
Totals: 2 passed, 0 failed (2 items)

작업 체크박스 발견 사항

진행 상황 계산은 체크박스만 세며 그 외에는 아무것도 세지 않습니다. 따라서 일반 불릿으로만 작성된 작업 파일은 작업 0개로 읽힙니다: openspec list와 openspec status는 할 일이 없다고 보고하고, openspec archive는 미완료로 표시할 항목이 없게 됩니다. Validate는 체크박스 없이 작업을 나열하는 추적된 각 작업 파일에 대해 WARNING을 보고합니다:

text
⚠ [WARNING] tasks.md: This change counts as 0 tasks: no line in its tracked task files is a checkbox, so "openspec list" and "openspec status" report no work and "openspec archive" has nothing to flag as incomplete. Write each task as "- [ ] 1.1 Description".

이 경고는 변경 사항의 추적 대상 전체에 체크박스가 전혀 없을 때에만 발생합니다. 실제 체크리스트 옆에 있는 산문으로 된 파일 하나는 보고되지 않으며, 작성 도중인 변경 사항은 체크박스가 하나라도 존재하는 즉시 진행 상황을 유지합니다. --strict는 이 경고를 실패로 바꿉니다. 줄 번호는 --json 보고서에 들어 있습니다.

펜스로 감싼 블록, HTML 주석, YAML 프론트매터, 들여쓰기된 코드는 스캔 대상이 아니므로, 붙여넣은 터미널 출력 예제가 작업 목록으로 잘못 인식되는 일은 없습니다.

아카이브 병합 발견 사항

변경 사항에 대해서는, validate가 파일을 쓰지 않고 현재 메인 스펙을 대상으로 archive의 병합 빌더를 실행합니다. 누락된 MODIFIED 대상이나 충돌하는 ADDED 요구사항과 같은 병합 충돌을 INFO로 보고합니다:

text
ℹ [INFO] api/spec.md: Archive would refuse this delta: api MODIFIED failed for header "### Requirement: Rate limiting" - not found

이러한 발견 사항은 검증이 통과한 경우에도 텍스트와 JSON 출력 모두에 나타납니다. INFO는 --strict 하에서도 종료 코드를 절대 변경하지 않습니다: 누락된 대상은 아직 아카이브되지 않은 형제(sibling) 변경 사항에 속해 있을 수 있기 때문입니다. 이미 메인 스펙에 동기화된 델타에는 archive의 기존 병합 규칙이 그대로 적용됩니다.

이 검사는 archive의 이후 단계인 병합된 스펙 검증이나 retirement 검사를 실행하지 않습니다. 문제 없는 보고서가 archive의 성공을 보장하지는 않습니다.

병합 사전 점검(merge preflight)을 시작할 수 없는 경우, INFO 발견 사항이 그 이유를 설명합니다. 기존 검증 발견 사항과 종료 코드는 변경되지 않은 채 유지됩니다.

실패한 항목은 각 문제와 해결 방법을 나열합니다:

Change 'add-rate-limit' has issues
✗ [ERROR] api/spec.md: ADDED "Rate limiting" must include at least one scenario
Next steps:
  - Ensure change has deltas in specs/: use headers ## ADDED/MODIFIED/REMOVED/RENAMED Requirements
  - Each requirement MUST include at least one #### Scenario: block
  - Debug parsed deltas: openspec show add-rate-limit --json --deltas-only

--json은 실행 전체에 대한 하나의 보고서를 출력합니다:

json
{
  "items": [
    {
      "id": "add-rate-limit",
      "type": "change",
      "valid": true,
      "issues": [],
      "durationMs": 2
    }
  ],
  "summary": {
    "totals": {
      "items": 1,
      "passed": 1,
      "failed": 0
    },
    "byType": {
      "change": {
        "items": 1,
        "passed": 1,
        "failed": 0
      }
    }
  },
  "version": "1.0",
  "root": {
    "path": "/Users/you/projects/my-app",
    "source": "nearest"
  }
}

issues 항목은 ERROR, WARNING 또는 INFO 중 하나의 level을 가집니다.

종료 코드

  • 0: 검증된 모든 항목이 통과함 (빈 벌크 범위 포함).
  • 1: 항목 실패, 보고서 요청이 잘못됨, openspec/config.yaml을 읽을 수 없거나 유효한 YAML이 아님, 또는 실행 실패 (예: 알 수 없는 이름 또는 OpenSpec 루트 없음). 읽거나 파싱할 수 없는 설정은 어떤 항목도 검사하기 전에 실행을 중단시킵니다; --json 사용 시 unreadable_config 또는 unparseable_config 코드를 가진 단일 status 항목으로 보고됩니다.

--report full|findings ​

명시적인 벌크 검증 범위에 대한 출력을 선택합니다:

  • full: 모든 항목. 기본값입니다. 명시적인 --report full은 보고서 메타데이터를 추가하지 않고 기존 출력 구조를 유지합니다.
  • findings: 문제가 있는 항목만 포함하며, 경고나 정보가 있는 통과 항목도 포함됩니다. 모든 항목은 여전히 검증됩니다. 총계, strict 모드 동작, 종료 코드는 변경되지 않습니다.
bash
openspec validate --all --report findings
openspec validate --archived --report findings --json

범위

플래그findings report.scope
--allall
--changeschanges
--specsspecs
--changes --specs, 또는 이 플래그들 중 하나와 함께 사용된 --allall
--archivedarchived

두 명시적 보고서 모드 모두 위치 인자 형태의 항목 이름, 누락된 벌크 범위, 또는 아카이브 범위와 활성 범위의 조합을 거부합니다.

findings 텍스트 출력 ​

휴먼 출력: stdout은 Scope: <scope> (<count> items)를 출력한 뒤 총계를 출력합니다. 문제가 있는 항목이 하나도 없는 경우:

text
Scope: all (2 items)
No item findings.
Totals: 2 passed, 0 failed (2 items)

문제가 있는 항목의 레이블, 심각도 레이블, 경로, 메시지는 stderr로 출력됩니다. 활성 범위에서의 실패는 총계 뒤에 Details: 재실행 힌트를 그대로 유지합니다. 기존 루트 배너와 진행 상황 출력은 보고서 앞에 나올 수 있습니다.

findings JSON 출력 ​

--report findings --json은 하나의 문서를 출력합니다. 이 예제에는 문제가 없는 항목이 두 개 있습니다:

json
{
  "report": {
    "kind": "validation-findings",
    "version": "1.0",
    "scope": "all",
    "returnedItems": 0,
    "totalItems": 2
  },
  "itemFindings": [],
  "summary": {
    "totals": { "items": 2, "passed": 2, "failed": 0 },
    "byType": {
      "change": { "items": 1, "passed": 1, "failed": 0 },
      "spec": { "items": 1, "passed": 1, "failed": 0 }
    }
  },
  "root": { "path": "/Users/you/projects/my-app", "source": "nearest" }
}
  • report.kind와 report.version: validation-findings 구조, 버전 1.0을 식별합니다. 최상위 수준의 version이나 items는 없습니다.
  • report.returnedItems와 report.totalItems: 각각 반환된 레코드 수와 검증된 전체 항목 수를 셉니다.
  • itemFindings: issues 배열이 비어 있지 않은 항목들의 전체 레코드. ERROR, WARNING, INFO 문제를 포함합니다. 각 레코드는 id, type, valid, issues, durationMs를 그대로 유지합니다. 아카이브된 항목은 type: "change"를 사용합니다.
  • summary: 전체 실행에 대한 총계와 타입별 집계이며, 반환된 부분 집합에 대한 집계가 아닙니다. 빈 범위는 총계 0으로 종료 코드 0을 반환합니다.
  • root: 전체 보고서와 동일한 선택된 루트 메타데이터입니다.

레코드 보존: 반환된 항목은 전체 보고서에서의 순서와 항목이나 문제에 대한 추가 필드들을 유지합니다. 필터링은 선택적 line, column 필드를 포함해 메시지나 위치를 재작성하지 않습니다.

명령 실패: 루트 선택이나 항목 탐색 실패는 기존의 status 진단을 유지하며 종료 코드 1로 종료됩니다. 이 경우 완성된 findings 보고서나 성공적인 빈 보고서를 반환하지 않습니다.

잘못된 보고서 요청 ​

두 명시적 보고서 모드 모두 루트 선택이나 항목 탐색에 앞서 다음 요청들을 거부합니다:

  • 지원되지 않는 보고서 값 (빈 문자열 포함).
  • 위치 인자 형태의 항목 이름 (벌크 플래그가 있더라도).
  • 명시적인 벌크 범위가 없는 경우.
  • --archived를 --all, --changes, --specs 중 하나와 조합한 경우.

JSON 모드에서 거부된 요청은 요소가 하나뿐인 status 배열만 담아 종료 코드 1로 종료됩니다. root나 보고서 페이로드는 포함되지 않습니다:

bash
openspec validate --all --report bogus --json
json
{
  "status": [
    {
      "severity": "error",
      "code": "invalid_validation_report_request",
      "message": "Unknown validation report 'bogus'.",
      "fix": "Use --report full|findings with --all, --changes, --specs, or --archived, without an item name. Do not combine archived and active scopes."
    }
  ]
}

휴먼 모드에서는 오류가 stderr로 출력됩니다. 값 없이 --report만 입력하면 --json과 함께 사용하는 경우를 포함해 stderr에 Commander 구문 오류가 발생하며, 이 진단 봉투(diagnostic envelope)는 사용되지 않습니다.

전체 보고서를 외부에서 필터링하기 ​

사용자 정의 JSON 뷰가 필요하면 jq나 PowerShell로 전체 보고서를 필터링할 수 있습니다. 이 스크립트 예제들은 검증 종료 코드를 유지하고 명령 오류 문서도 그대로 유지합니다.

jq를 사용하는 Bash의 경우:

bash
if validation_json=$(openspec validate --all --json); then
  validation_exit=0
else
  validation_exit=$?
fi
printf '%s\n' "$validation_json" |
  jq 'if has("items") then .items |= map(select(.issues | length > 0)) else . end'
exit "$validation_exit"

PowerShell의 경우:

powershell
$validationJson = openspec validate --all --json
$validationExit = $LASTEXITCODE
$validationReport = $validationJson | ConvertFrom-Json
if ($validationReport.PSObject.Properties.Name -contains 'items') {
  $validationReport.items = @($validationReport.items | Where-Object { $_.issues.Count -gt 0 })
}
$validationReport | ConvertTo-Json -Depth 100
exit $validationExit

이러한 사용자 정의 뷰는 전체 보고서의 키는 유지하지만 문제가 없는 항목은 생략합니다. 이들은 완전한 full-v1 보고서도, 버전이 지정된 --report findings 구조도 아닙니다.

openspec archive ​

완료된 변경을 아카이브로 이동하고 메인 스펙을 업데이트합니다.

bash
openspec archive add-rate-limit -y                # 변경 하나를 아카이브하고 델타를 병합합니다
openspec archive add-rate-limit -y --skip-specs   # 스펙을 건드리지 않고 아카이브합니다

이름을 지정하지 않으면 archive는 변경을 선택하라는 메시지를 표시합니다. 대화형 터미널이 아닌 경우에는 종료 코드 1로 종료하고 대신 다시 실행할 명령을 출력합니다.

인수

인수설명
change-name아카이브할 변경의 폴더 이름입니다(add-rate-limit).

옵션

플래그효과
-y, --yes모든 확인 질문에 예라고 답합니다: 스펙 업데이트, 미완료 작업, 검증 건너뛰기.
--skip-specs메인 스펙을 건드리지 않고 아카이브합니다(인프라, 도구 또는 문서 전용 변경).
--no-validate검증을 건너뜁니다. archive는 먼저 확인을 요청하며, -y가 이에 답합니다.
--json텍스트 대신 구조화된 결과를 출력합니다. 스펙 업데이트를 확인하려면 --yes가 필요합니다.
--store <id>현재 프로젝트 대신 등록된 스토어를 OpenSpec 루트로 사용합니다.

출력

성공적으로 실행되면 작업 상태를 보고하고, 스펙 업데이트 미리 보기를 표시하고, 이를 적용한 뒤 아카이브 폴더 이름을 알려줍니다:

Task status: ✓ Complete

Specs to update:
  api: update
Applying changes to openspec/specs/api/spec.md:
  + 1 added
Totals: + 1, ~ 0, - 0, → 0
Specs updated successfully.
Change 'add-rate-limit' archived as '2026-08-11-add-rate-limit'.

변경 폴더는 이름 앞에 오늘 날짜가 접두사로 붙은 채 openspec/changes/archive/2026-08-11-add-rate-limit/로 통째로 이동합니다. 각 델타는 해당 메인 스펙에 병합됩니다. 위의 ADDED 요구 사항은 openspec/specs/api/spec.md에 추가되었습니다. -y 없이 실행하면 archive는 미리 보기를 표시하고 업데이트 전에 묻습니다. 거절해도 변경은 아카이브되고 스펙은 그대로 둡니다.

--json --yes를 사용하면:

json
{
  "archive": {
    "change": "add-rate-limit",
    "archivedAs": "2026-08-11-add-rate-limit",
    "path": "/Users/you/projects/my-app/openspec/changes/archive/2026-08-11-add-rate-limit",
    "specsUpdated": true,
    "totals": {
      "added": 1,
      "modified": 0,
      "removed": 0,
      "renamed": 0
    }
  },
  "root": {
    "path": "/Users/you/projects/my-app",
    "source": "nearest"
  }
}

archive는 변경을 먼저 검증하고 실패하는 변경은 거부합니다:

Validation errors in change delta specs:
  ✗ ADDED "Rate limiting" must include at least one scenario

Validation failed. Please fix the errors before archiving.
To skip validation (not recommended), use --no-validate flag.

미완료 작업은 경고하지만 차단하지 않습니다. 대화형 실행에서는 archive가 계속할지 묻고, -y는 자체적으로 계속합니다:

Task status: 1/2 tasks
Warning: 1 incomplete task(s) found. Continuing due to --yes flag.

종료 코드

  • 0: 스펙 업데이트 여부와 관계없이 변경이 아카이브되었습니다.
  • 1: 검증에 실패했거나, 변경 이름을 알 수 없거나, 확인이 필요했지만 답변을 읽을 수 없었습니다.

openspec new ​

새 변경 디렉터리를 생성합니다.

bash
openspec new change add-caching                                # 메타데이터만 생성
openspec new change add-search --goal "Users can search docs"  # 목표 기록

new에는 하위 명령이 하나 있으며, 바로 new change <name>입니다. 이 명령은 단일 .openspec.yaml 메타데이터 파일을 포함하는 openspec/changes/<name>/을 생성합니다:

yaml
schema: spec-driven
created: 2026-08-11

아티팩트(제안서, 스펙, 설계, 작업)는 여기에서 스캐폴딩되지 않습니다. 나중에 직접 작성하며, openspec status가 다음에 작성할 아티팩트를 알려줍니다.

인수

인수설명
name변경의 폴더 이름입니다(add-caching).

옵션

플래그효과
--description <text>변경 디렉터리에 이 텍스트를 담은 README.md도 생성합니다.
--goal <text>.openspec.yaml에 goal: 줄을 저장합니다.
--schema <name>변경의 워크플로 스키마입니다. 기본값: spec-driven이며, 함께 제공되는 유일한 스키마입니다.
--json생성된 변경을 텍스트 대신 JSON으로 출력합니다.
--store <id>현재 프로젝트 대신 등록된 스토어를 OpenSpec 루트로 사용합니다.

출력

Created change 'add-caching' at openspec/changes/add-caching/
Schema: spec-driven
Next: openspec status --change add-caching

openspec/ 디렉터리가 발견되지 않으면 new change는 현재 위치에 해당 디렉터리를 생성하고 그 사실을 알려줍니다:

Created change 'add-caching' at openspec/changes/add-caching/
Schema: spec-driven
Next: openspec status --change add-caching

Note: no OpenSpec root was found here, so one was created at openspec/.
Run `openspec init` to finish setting this project up, or delete that directory if you meant a different project.

이 안내는 나머지 사람이 읽는 출력과 함께 stdout으로 전달되며, --json 사용 시에는 나타나지 않습니다.

openspec/이 이미 있는 프로젝트에서 --json을 사용하면:

json
{
  "change": {
    "id": "add-caching",
    "path": "/Users/you/projects/my-app/openspec/changes/add-caching",
    "metadataPath": "/Users/you/projects/my-app/openspec/changes/add-caching/.openspec.yaml",
    "schema": "spec-driven"
  },
  "root": {
    "path": "/Users/you/projects/my-app",
    "source": "nearest"
  }
}

openspec/ 디렉터리가 발견되지 않아 new change가 해당 디렉터리를 생성한 경우에도 JSON은 같은 형태입니다. root.path는 명령을 실행한 디렉터리이고, root.source는 implicit로 표시됩니다:

json
"root": {
  "path": "/Users/you/projects/my-app",
  "source": "implicit"
}

종료 코드

  • 0: 변경이 생성되었습니다.
  • 1: 변경이 이미 존재하거나 스키마를 알 수 없습니다.

openspec status ​

하나의 변경 사항 또는 모든 활성 변경 사항에 대한 아티팩트 완료 상태를 보고합니다.

bash
openspec status --change add-rate-limit          # checklist view
openspec status --change add-rate-limit --json   # structured report
openspec status --all                            # every active change
openspec status --all --json                     # one batch report

활성 변경 사항이 있으면 --change 또는 --all 중 정확히 하나를 사용하세요. 둘 중 하나도 없으면 status는 종료 코드 1로 종료하고 사용 가능한 변경 사항을 나열합니다. 변경 사항이 하나만 있어도 마찬가지입니다:

text
✖ Error: Missing required option --change (or --all for every active change). Available changes:
  add-rate-limit

프로젝트에 활성 변경 사항이 없으면 status는 No active changes. Create one with: openspec new change <name>를 출력하고 플래그 없이도 종료 코드 0으로 종료합니다. --all --json을 사용하면 동일한 빈 상태는 { "changes": [], "message": "No active changes.", "root": ... }입니다.

옵션

FlagEffect
--change <id>보고할 변경 사항 (폴더 이름 기준).
--all모든 활성 변경 사항을 이름순으로 보고합니다. --change와 함께 사용할 수 없습니다.
--schema <name>openspec/config.yaml에서 자동 감지된 스키마를 재정의합니다. 알 수 없는 이름은 오류입니다.
--json텍스트 대신 구조화된 보고서를 출력합니다.
--store <id>현재 프로젝트 대신 등록된 스토어를 OpenSpec 루트로 사용합니다.

출력

스키마의 아티팩트 체크리스트: [x] 완료, [ ] 작성 준비됨, [-] 의존하는 아티팩트가 존재할 때까지 차단됨.

Change: add-rate-limit
Schema: spec-driven
Change root: /Users/you/projects/my-app/openspec/changes/add-rate-limit
Progress: 2/4 artifacts complete

[x] proposal
[x] specs
[ ] design
[-] tasks (blocked by: design)

Next: openspec instructions design --change "add-rate-limit" --json

Next: 줄은 변경 사항을 진행시키는 하나의 명령을 지정하므로, 새 세션에서 변경 사항을 다시 선택하려면 openspec status만으로 충분합니다. 계획이 끝나지 않은 동안에는 다음 준비된 아티팩트를 지정하고, 모든 계획 아티팩트가 존재하면 openspec instructions apply를 지정합니다:

[x] proposal
[x] specs
[x] design
[x] tasks

All planning artifacts complete!
Next: openspec instructions apply --change "add-rate-limit" --json

해결된 루트가 스토어인 경우 --store <id>를 포함하며, JSON nextSteps 문장과 동일한 명령을 지정합니다.

--json은 아티팩트별 의존성, 해결된 파일 경로, 제안된 다음 단계를 추가합니다. 축약된 예시:

json
{
  "changeName": "add-rate-limit",
  "schemaName": "spec-driven",
  "isComplete": false,
  "nextSteps": [
    "Run openspec instructions design --change \"add-rate-limit\" --json before writing that artifact."
  ],
  "artifacts": [
    {
      "id": "proposal",
      "outputPath": "proposal.md",
      "status": "done",
      "requires": []
    },
    {
      "id": "design",
      "outputPath": "design.md",
      "status": "ready",
      "requires": [
        "proposal"
      ]
    },
    {
      "id": "tasks",
      "outputPath": "tasks.md",
      "status": "blocked",
      "requires": [
        "specs",
        "design"
      ],
      "missingDeps": [
        "design"
      ]
    }
  ]
}

--all --json을 사용하면 changes는 각 변경 사항에 대해 동일한 상태 객체를 포함하며, 변경 사항별 root는 없습니다. 선택된 루트는 봉투에 한 번만 나타납니다. 이 예시는 위에 표시된 변경 사항별 상태 필드를 축약한 것입니다:

json
{
  "changes": [
    {
      "changeName": "add-rate-limit",
      "schemaName": "spec-driven",
      "artifacts": []
    }
  ],
  "root": {
    "path": "/Users/you/projects/my-app",
    "source": "nearest"
  }
}

하나의 변경 사항을 로드할 수 없으면 배치는 계속됩니다. 해당 항목에는 changeName과 status 진단이 포함되며 다른 항목은 계속 사용할 수 있습니다. 명령은 JSON 모드에서도 종료 코드 1로 종료하므로 CI는 불완전한 보고서를 성공으로 받아들이지 않습니다. JSON 출력은 여전히 하나의 파싱 가능한 문서로 유지됩니다.

종료 코드

  • 0: 요청된 모든 상태가 출력됨; 빈 --all 보고서도 종료 코드 0으로 종료.
  • 1: 요청된 변경 사항을 로드하지 못함, --change 또는 --all이 누락됨, 두 플래그가 함께 사용됨, 변경 사항이 존재하지 않음, 또는 스키마 재정의가 알 수 없음.

openspec instructions ​

아티팩트 생성, 적용, 또는 아카이빙에 대한 지침을 출력합니다. 에이전트는 워크플로 중에 이 명령을 실행하여 다음 단계의 지침 텍스트를 가져옵니다.

bash
openspec instructions proposal --change add-rate-limit   # how to write one artifact
openspec instructions apply --change add-rate-limit      # how to implement the change
openspec instructions archive --change add-rate-limit    # inputs for archiving

인자

ArgumentWhat it is
artifact스키마의 아티팩트 ID (spec-driven의 proposal, specs, design, tasks) 또는 예약어 apply와 archive.

옵션

FlagEffect
--change <id>지침을 생성할 변경 사항. 필수.
--schema <name>스키마를 재정의합니다. 그렇지 않으면 config.yaml에서 자동 감지됩니다.
--json텍스트 대신 구조화된 객체를 출력합니다.
--store <id>현재 프로젝트 대신 등록된 스토어를 OpenSpec 루트로 사용합니다.

출력

아티팩트 형식은 하나의 지침 블록을 출력합니다: 작업, 작성할 파일, 작성 방법, 아티팩트의 템플릿, 그리고 완료 시 잠금 해제되는 내용.

<artifact id="proposal" change="add-rate-limit" schema="spec-driven">

<task>
Create the proposal artifact for change "add-rate-limit".
Initial proposal document outlining the change
</task>

<output>
Write to: /Users/you/projects/my-app/openspec/changes/add-rate-limit/proposal.md
</output>

<instruction>
Create the proposal document that establishes WHY this change is needed.
...

apply는 컨텍스트 파일, 작업 진행 상황, 작업 지침을 출력합니다:

## Apply: add-rate-limit
Schema: spec-driven

### Context Files
- proposal: /Users/you/projects/my-app/openspec/changes/add-rate-limit/proposal.md
- specs: /Users/you/projects/my-app/openspec/changes/add-rate-limit/specs/api/spec.md
- tasks: /Users/you/projects/my-app/openspec/changes/add-rate-limit/tasks.md

### Progress
1/3 complete

### Tasks
- [x] 1.1 Add rate limit middleware
- [ ] 1.2 Return 429 with Retry-After header
- [ ] 1.3 Add tests for burst traffic

### Instruction
Read context files, work through pending tasks, mark complete as you go.
Pause if you hit blockers or need clarification.

No project context or operation guidance configured.

필수 아티팩트가 없으면 apply는 ### ⚠️ Blocked를 보고하고 대신 해당 아티팩트를 나열합니다. archive는 변경 사항 이름과 config의 프로젝트 컨텍스트 및 운영 지침을 출력합니다. 구성된 것이 없으면 그렇게 말하고 더 이상 출력하지 않습니다.

--json을 사용하면 각 형식은 하나의 객체를 반환합니다. 아티팩트 형식은 다음과 같이 시작합니다:

json
{
  "changeName": "add-rate-limit",
  "artifactId": "proposal",
  "schemaName": "spec-driven",
  "changeDir": "/Users/you/projects/my-app/openspec/changes/add-rate-limit",
  ...

그리고 outputPath, existingOutputPaths, 전체 instruction 및 template 문자열, dependencies, unlocks, root가 이어집니다. apply 형식은 contextFiles, progress, tasks, taskTrackingConfigured, state (blocked, ready, all_done), instruction을 포함합니다.

각 tasks 항목은 id, description, done, sourcePath, line을 포함합니다. sourcePath는 작업을 제공한 추적 파일의 절대 경로입니다. line은 해당 파일에서 작업 체크박스의 1부터 시작하는 줄 번호입니다.

taskTrackingConfigured는 항상 불리언입니다: 스키마가 null이 아닌 apply.tracks를 설정하면 일치하는 파일이 없어도 true이고, 그 외에는 false입니다. 일치하는 추적 파일을 읽을 수 없으면 unavailableTrackingFiles에 해당 파일의 절대 path와 오류 reason이 포함됩니다. 이 필드는 모든 일치 파일을 읽을 수 있을 때 생략됩니다. 읽을 수 있는 파일은 여전히 tasks와 progress에 기여하지만, 모든 일치 파일을 읽을 때까지 state는 all_done이 될 수 없습니다.

종료 코드

  • 0: 지침이 출력됨.
  • 1: 알 수 없는 아티팩트, 알 수 없는 변경 사항, 알 수 없는 스키마, 또는 --change 누락. 각 오류는 유효한 값을 나열합니다.

openspec templates ​

스키마 아티팩트에 대해 확인된(resolved) 템플릿 경로를 출력합니다.

bash
openspec templates          # 기본 스키마: spec-driven
openspec templates --json   # 아티팩트 id를 경로로 매핑

옵션

플래그효과
--schema <name>확인할 스키마. 기본값: spec-driven.
--json아티팩트 id를 템플릿 경로로 매핑한 JSON을 출력합니다.

출력

Schema: spec-driven
Source: package

proposal:
  /usr/local/lib/node_modules/@fission-ai/openspec/schemas/spec-driven/templates/proposal.md
specs:
  /usr/local/lib/node_modules/@fission-ai/openspec/schemas/spec-driven/templates/spec.md
design:
  /usr/local/lib/node_modules/@fission-ai/openspec/schemas/spec-driven/templates/design.md
tasks:
  /usr/local/lib/node_modules/@fission-ai/openspec/schemas/spec-driven/templates/tasks.md

Source는 스키마가 확인된 위치를 나타냅니다: project (프로젝트의 openspec/schemas/), user (전역 오버라이드), 또는 package (CLI에 내장). 우선순위는 project가 user보다, user가 package보다 높습니다.

json
{
  "proposal": {
    "path": "/usr/local/lib/node_modules/@fission-ai/openspec/schemas/spec-driven/templates/proposal.md",
    "source": "package"
  },
  "specs": {
    "path": "/usr/local/lib/node_modules/@fission-ai/openspec/schemas/spec-driven/templates/spec.md",
    "source": "package"
  },
  "design": {
    "path": "/usr/local/lib/node_modules/@fission-ai/openspec/schemas/spec-driven/templates/design.md",
    "source": "package"
  },
  "tasks": {
    "path": "/usr/local/lib/node_modules/@fission-ai/openspec/schemas/spec-driven/templates/tasks.md",
    "source": "package"
  }
}

종료 코드

  • 0: 경로가 출력됨.
  • 1: 알 수 없는 스키마. 오류 메시지에 사용 가능한 스키마 목록이 표시됩니다.

openspec schemas ​

사용 가능한 워크플로 스키마를 나열합니다.

bash
openspec schemas          # 이름, 설명, 아티팩트 순서
openspec schemas --json   # 머신 리더블, 에이전트 사용용

옵션

플래그효과
--jsonJSON으로 출력합니다 (에이전트 사용용).

출력

Available schemas:

  spec-driven
    Default OpenSpec workflow - proposal → specs → design → tasks
    Artifacts: proposal → specs → design → tasks

프로젝트의 스키마에는 (project) 레이블이 붙고, 전역 오버라이드에는 (user override) 레이블이 붙습니다.

json
[
  {
    "name": "spec-driven",
    "description": "Default OpenSpec workflow - proposal → specs → design → tasks",
    "artifacts": [
      "proposal",
      "specs",
      "design",
      "tasks"
    ],
    "source": "package"
  }
]

종료 코드

  • 0: 스키마가 나열됨.
  • 1: 스키마 목록을 읽을 수 없음.

openspec schema ​

스키마를 검사, 포크, 또는 생성합니다 (실험적 기능). 모든 하위 명령은 먼저 stderr에 Note: Schema commands are experimental and may change.를 출력합니다.

bash
openspec schema which spec-driven          # where a schema resolves from
openspec schema fork spec-driven my-flow   # copy a schema into the project
openspec schema init my-schema             # create a schema from scratch
하위 명령설명
which스키마가 확인되는 위치를 표시합니다.
validate스키마의 구조와 템플릿을 확인합니다.
fork사용자 정의를 위해 기존 스키마를 프로젝트에 복사합니다.
init새로운 프로젝트 로컬 스키마를 생성합니다.

스키마는 세 가지 위치에서 확인됩니다. 첫 번째 일치 항목이 우선합니다:

소스위치
project현재 프로젝트의 openspec/schemas/.
user~/.local/share/openspec/schemas/ (XDG_DATA_HOME 및 Windows %LOCALAPPDATA% 준수).
packageCLI와 함께 제공되는 스키마. spec-driven이 여기에 있습니다.

openspec schema which ​

CLI가 사용할 스키마 사본을 표시합니다.

bash
openspec schema which spec-driven
openspec schema which --all        # every schema, grouped by source

인수

인수설명
name조회할 스키마. --all이 설정되지 않은 경우 필수입니다. 둘 다 없으면 which가 1로 종료됩니다.

옵션

플래그효과
--all모든 스키마를 확인 소스와 함께 나열합니다.
--json확인 결과를 JSON으로 출력합니다.

출력

Schema: spec-driven
Source: package
Path: /usr/local/lib/node_modules/@fission-ai/openspec/schemas/spec-driven

우선순위가 더 높은 사본이 다른 사본을 숨기는 경우, Shadows: 섹션에 숨겨진 사본이 나열됩니다. --json 사용 시:

json
{
  "name": "my-flow",
  "source": "project",
  "path": "/Users/you/projects/my-app/openspec/schemas/my-flow",
  "shadows": []
}

알 수 없는 이름은 1로 종료되고 사용 가능한 스키마를 나열합니다.

openspec schema validate ​

스키마의 구조와 템플릿을 확인합니다.

bash
openspec schema validate spec-driven   # one schema, from any source
openspec schema validate               # every project-local schema

schema.yaml이 존재하고 파싱되는지, 구조가 스키마 형식과 일치하는지, 모든 아티팩트의 템플릿 파일이 스키마의 templates/ 디렉토리 내에 존재하는지, 그리고 의존성 그래프에 주기나 알 수 없는 참조가 없는지(특히 apply.requires에서) 확인합니다. apply.tracks 값이 어떤 아티팩트의 generates 값과 정확히 일치하지 않으면 warning: 줄을 출력하지만 유효성 검사에 실패하지는 않습니다. OpenSpec가 해당 파일이 어떤 아티팩트의 진행 상황에 속하는지 판단할 수 없기 때문입니다.

옵션

플래그효과
--json텍스트 대신 구조화된 보고서를 출력합니다.
--verbose각 유효성 검사 단계를 출력합니다.

출력

✓ Schema 'spec-driven' is valid

이름이 없으면 각 프로젝트 스키마가 Validation Results: 헤더 아래에 한 줄씩 표시됩니다. 실패한 스키마는 문제를 나열하고 실행이 1로 종료됩니다:

✗ Schema 'my-schema' has errors:
  error: Template file 'tasks.md' not found for artifact 'tasks'

openspec schema fork ​

사용자 정의할 수 있도록 기존 스키마를 프로젝트에 복사합니다.

bash
openspec schema fork spec-driven my-flow

인수

인수설명
source복사할 스키마, 모든 소스 위치에서 가능.
name복사본의 이름. 케밥 케이스 (my-workflow). 기본값: <source>-custom.

옵션

플래그효과
--force기존 대상 스키마를 덮어씁니다.
--json결과를 JSON으로 출력합니다.

출력

✔ Forked 'spec-driven' to 'my-flow'

Source: /usr/local/lib/node_modules/@fission-ai/openspec/schemas/spec-driven (package)
Destination: /Users/you/projects/my-app/openspec/schemas/my-flow

포크는 openspec/schemas/에 생성되고, schema.yaml의 name: 필드가 새 이름으로 다시 작성됩니다:

openspec/schemas/my-flow/
├── schema.yaml
└── templates/
    ├── design.md
    ├── proposal.md
    ├── spec.md
    └── tasks.md

기존 대상은 --force를 전달하지 않으면 오류입니다. 소스와 같은 이름을 유지하는 포크는 원본을 숨깁니다.

openspec schema init ​

시작 템플릿으로 새로운 프로젝트 로컬 스키마를 생성합니다.

bash
openspec schema init my-schema --description "Lightweight flow" --artifacts proposal,tasks

대화형 터미널에서 --description과 --artifacts가 모두 없으면 init이 설명, 아티팩트 체크리스트, 그리고 스키마를 프로젝트 기본값으로 만들지 여부를 묻습니다. 터미널 외부에서는 아래 기본값을 사용합니다.

인수

인수설명
name새 스키마의 이름. 케밥 케이스 (my-workflow).

옵션

플래그효과
--description <text>스키마 설명. 기본값: Custom workflow schema for <name>.
--artifacts <list>proposal, specs, design, tasks에서 쉼표로 구분된 아티팩트 ID. 기본값: 네 가지 모두.
--default기존 openspec/config.yaml 또는 openspec/config.yml에 schema: <name>을 씁니다. 둘 다 없으면 openspec/config.yaml을 생성합니다. 새 변경 사항은 이 스키마를 사용합니다.
--no-default기본값에 대한 프롬프트를 건너뜁니다.
--force같은 이름의 기존 스키마를 덮어씁니다.
--json결과를 JSON으로 출력합니다.

스키마 생성과 --default 구성 업데이트는 하나의 작업입니다. OpenSpec가 구성을 확인하거나 쓸 수 없으면 구성과 기존 스키마를 모두 변경하지 않습니다.

출력

✔ Created schema 'my-schema'

Schema created at: /Users/you/projects/my-app/openspec/schemas/my-schema

Artifacts: proposal, tasks

디스크의 레이아웃:

openspec/schemas/my-schema/
├── schema.yaml
└── templates/
    ├── proposal.md
    └── tasks.md

schema.yaml은 선택한 아티팩트를 의존성과 함께 연결합니다. tasks가 포함되면 tasks.md를 추적하는 apply 단계도 함께 제공됩니다. openspec new --schema my-schema로 이 스키마를 사용하세요.

openspec store ​

스토어를 생성하고 관리합니다: 사용자의 머신에 등록된 독립 실행형 OpenSpec 저장소.

bash
openspec store setup team-context --path ~/openspec/team-context   # create and register
openspec store register ~/stores/design-system                     # register an existing checkout
openspec store list                                                # see what's registered

등록 정보는 머신별 레지스트리에 저장됩니다: ~/.local/share/openspec/stores/registry.yaml, 또는 XDG_DATA_HOME이 설정된 경우 $XDG_DATA_HOME/openspec/stores/registry.yaml. 모든 하위 명령은 --json을 받아 텍스트 대신 구조화된 보고서를 출력합니다. 누락되거나 알 수 없는 하위 명령으로 openspec store를 실행하면 1로 종료되고 하위 명령을 나열합니다.

하위 명령설명
setup [id]스토어 폴더를 생성하고 등록합니다.
register [path]기존 스토어 폴더를 등록합니다.
unregister <id>등록을 잊습니다. 폴더는 디스크에 남아 있습니다.
remove <id>등록을 잊고 폴더를 삭제합니다.
list (별칭 ls)등록된 스토어를 나열합니다.
doctor [id]등록된 스토어의 등록, 메타데이터, Git 상태를 확인합니다.

openspec store setup ​

스토어 폴더를 생성하고 등록합니다.

bash
openspec store setup team-context --path ~/openspec/team-context

대화형 터미널에서 setup은 누락된 이름과 위치를 묻고 생성하기 전에 확인합니다. 터미널 외부에서는 누락된 이름이나 --path가 1로 종료되고 전달할 플래그를 표시합니다. 등록된 스토어에 대해 setup을 다시 실행하면 Registry: already registered를 보고합니다.

--path가 다른 Git 저장소 내부에 있으면 setup이 store_setup_inside_git_repo와 함께 1로 종료됩니다. 거기서 스토어를 초기화하면 한 저장소 안에 다른 저장소가 중첩되기 때문입니다. --no-init-git은 저장소를 생성하지 않으므로 이 검사를 건너뜁니다. 홈 디렉토리 자체가 dotfiles 저장소와 같은 Git 저장소인 경우 ~/openspec/<id>에 스토어를 유지하려면 이 옵션을 사용하세요.

인수

인수설명
id스토어 이름. --store에 전달하는 id가 됩니다.

옵션

플래그효과
--path <path>스토어가 위치할 폴더 (~ 확장).
--init-git초기 커밋으로 Git 저장소를 초기화합니다. 기본값.
--no-init-git모든 Git 작업을 건너뜁니다: 초기화 없음, 초기 커밋 없음.
--remote <url>store.yaml에 기록되는 표준 복제 소스.

출력

Store ready: team-context
Location: /Users/you/stores/team-context
OpenSpec root: ready
Registry: registered

Next: run normal OpenSpec commands against this store, for example:
  openspec new change <change-id> --store team-context
Share this store by committing and pushing it like any Git repo.

--json은 생성된 항목과 등록된 위치를 보고합니다:

json
{
  "store": {
    "id": "design-system",
    "root": "/Users/you/stores/design-system",
    "metadata_path": "/Users/you/stores/design-system/.openspec-store/store.yaml"
  },
  "registry": {
    "path": "/Users/you/.local/share/openspec/stores/registry.yaml",
    "registered": true,
    "already_registered": false
  },
  "git": {
    "is_repository": true,
    "initialized": true,
    "committed": true
  },
  "created_files": [
    "openspec/",
    "openspec/specs/",
    "openspec/changes/",
    "openspec/changes/archive/",
    "openspec/config.yaml",
    "openspec/specs/.gitkeep",
    "openspec/changes/archive/.gitkeep",
    ".openspec-store/store.yaml"
  ],
  "status": []
}

openspec store register ​

기존 스토어 폴더를 등록합니다. 예를 들어 복제한 팀원의 스토어.

bash
openspec store register ~/stores/design-system

폴더에는 정상적인 openspec/ 루트가 포함되어야 합니다. .openspec-store/store.yaml이 있으면 register는 기록된 id를 재사용합니다. 없으면 register는 해당 메타데이터를 생성하기 전에 확인을 요청합니다. 대화형 터미널 외부에서는 대신 --yes를 전달하세요. 한 머신은 스토어 id당 하나의 체크아웃만 등록할 수 있습니다. 같은 id에 두 번째 경로를 등록하거나 두 번째 id에 같은 경로를 등록하면 1로 종료됩니다.

인수

인수설명
path등록할 스토어 폴더 (~ 확장). 필수.

옵션

플래그효과
--id <id>스토어 id. 기본값은 메타데이터 또는 폴더 이름.
--yes정상적인 OpenSpec 루트에 대한 스토어 식별 메타데이터 생성을 확인합니다.

출력

Store registered: design-system
Location: /Users/you/stores/design-system
OpenSpec root: ready
Registry: registered

--json은 store setup --json과 동일한 문서 형식을 출력합니다.

openspec store unregister ​

등록을 잊습니다. 폴더는 디스크에 남아 있습니다.

bash
openspec store unregister design-system
Unregistered store: design-system
Files kept at: /Users/you/stores/design-system

openspec store remove ​

등록을 잊고 폴더를 삭제합니다.

bash
openspec store remove design-system --yes

대화형으로는 remove가 삭제 전에 확인을 요청합니다. --json 또는 대화형 터미널 외부에서는 삭제에 --yes가 필요합니다:

Error: Pass --yes to delete store files non-interactively.
Fix: openspec store remove design-system --yes

폴더에 일치하는 스토어 메타데이터가 없거나 다른 등록된 스토어를 포함하는 경우(예: Git 서브모듈로 포함된 스토어) remove는 1로 종료되고 아무것도 삭제하지 않습니다. 이 경우 오류는 store_remove_contains_registered_store입니다: 먼저 openspec store unregister <nested-id>를 실행하거나, 파일을 삭제하지 않고 스토어를 잊으려면 openspec store unregister <id>를 실행하세요.

옵션

플래그효과
--yes로컬 스토어 폴더 삭제를 확인합니다.

출력

Removed store: design-system
Deleted: /Users/you/stores/design-system

openspec store list ​

등록된 스토어를 나열합니다. ls는 별칭입니다.

bash
openspec store list
OpenSpec stores (2)

ID              Location
design-system   /Users/you/stores/design-system
team-context    /Users/you/stores/team-context

등록된 것이 없으면 list는 No stores registered.와 다음에 실행할 setup 및 register 명령을 출력합니다.

openspec store doctor ​

등록된 스토어의 등록, 메타데이터, Git 상태를 확인합니다.

bash
openspec store doctor                # every registered store
openspec store doctor team-context  # one store

출력

Store doctor

team-context
  Location: /Users/you/stores/team-context
  OpenSpec root: ok
  Metadata: ok
  Git: repository detected (commits: yes, uncommitted changes: no, remote: none)
  Issues: none

종료 코드

  • 0: 보고서가 출력되었습니다. 스토어가 문제를 보고하더라도 마찬가지입니다.
  • 1: 보고서를 실행할 수 없었습니다 (예: 알 수 없는 스토어 id).

openspec doctor ​

해석된 OpenSpec 루트의 관계 상태를 보고합니다.

bash
openspec doctor                       # cwd 위에서 가장 가까운 openspec/ 루트
openspec doctor --store team-context  # 등록된 스토어를 루트로 사용

Doctor는 읽기 전용입니다. 절대로 클론, 동기화, 복구를 수행하지 않습니다. 루트가 정상 상태인지, 그리고 openspec/config.yaml에 선언된 각 참조가 이 머신에서 해석되는지를 보고합니다. 현재 작업 디렉터리(cwd) 위에 루트가 없고 --store도 지정되지 않으면 종료 코드 1로 종료되며, 등록된 스토어의 이름을 표시합니다.

옵션

플래그효과
--store <id>현재 프로젝트 대신 등록된 스토어를 OpenSpec 루트로 사용합니다.
--json상태 보고서를 JSON으로 출력합니다.

출력

Doctor

Root
  Location: /Users/you/projects/my-app
  OpenSpec root: ok

References
  - team-context: ok (/Users/you/stores/team-context)

--store를 사용하면 루트가 스토어가 되며, 보고서에 스토어 줄이 추가됩니다:

Using OpenSpec root: team-context (/Users/you/stores/team-context)
Doctor

Root
  Location: /Users/you/stores/team-context
  OpenSpec root: ok
  Store: team-context (metadata ok)

References
  (none declared)
json
{
  "root": {
    "path": "/Users/you/projects/my-app",
    "source": "nearest",
    "healthy": true,
    "status": []
  },
  "store": null,
  "references": [
    {
      "store_id": "team-context",
      "root": "/Users/you/stores/team-context",
      "status": []
    }
  ],
  "status": []
}

종료 코드

  • 0: 보고서가 출력된 경우입니다. 문제가 나열된 경우도 포함됩니다.
  • 1: 루트가 해석되지 않은 경우(cwd 위에 openspec/가 없고 --store도 없음) 또는 알 수 없는 --store id인 경우.

openspec context ​

해석된 OpenSpec 루트의 작업 컨텍스트를 출력합니다. 여기에는 루트와 openspec/config.yaml에 선언된 모든 참조된 스토어가 포함되며, 각 항목에 fetch 명령어가 함께 제공됩니다.

bash
openspec context                       # cwd 위에서 가장 가까운 openspec/ 루트
openspec context --store team-context  # 등록된 스토어를 루트로 사용
openspec context --json                # 에이전트 브리프

이 머신에서 해석되지 않는 참조는 Not available on this machine 섹션에 표시되며, 각 항목에 해결 방법이 함께 제공됩니다.

옵션

플래그효과
--store <id>현재 프로젝트 대신 등록된 스토어를 OpenSpec 루트로 사용합니다.
--json에이전트 브리프를 JSON으로 출력합니다.
--code-workspace <path>이 집합에 대한 VS Code 워크스페이스 파일도 작성합니다.
--force기존 --code-workspace 파일을 덮어씁니다.

출력

Working context for my-app (/Users/you/projects/my-app)

OpenSpec root
  my-app  /Users/you/projects/my-app

Referenced stores
  team-context  /Users/you/stores/team-context
    Fetch: openspec show <spec-id> --type spec --store team-context

--store를 사용하면 스토어가 집합 전체가 됩니다:

Using OpenSpec root: team-context (/Users/you/stores/team-context)
Working context for team-context (/Users/you/stores/team-context)

OpenSpec root
  team-context  /Users/you/stores/team-context

No references declared; the working set is this root alone.
json
{
  "root": {
    "path": "/Users/you/projects/my-app",
    "source": "nearest",
    "role": "openspec_root"
  },
  "members": [
    {
      "role": "referenced_store",
      "id": "team-context",
      "path": "/Users/you/stores/team-context",
      "fetch": "openspec show <spec-id> --type spec --store team-context",
      "status": []
    }
  ],
  "status": []
}

워크스페이스 파일 작성

--code-workspace는 지정한 경로에 VS Code 워크스페이스 파일을 작성합니다. 루트를 위한 폴더 하나, 그리고 사용 가능한 참조된 스토어마다 ref:<id> 폴더 하나가 포함됩니다. 사용할 수 없는 참조는 건너뛰어지며, 그 이름은 요약 줄에 표시됩니다(예: Wrote /Users/you/projects/my-app/openspec.code-workspace (2 folders)). 이 요약은 stderr에 출력되므로, --json 사용 시 stdout은 하나의 JSON 문서로 유지됩니다. 기존 파일이 있으면 --force를 지정하지 않는 한 종료 코드 1로 종료됩니다.

json
{
  "folders": [
    {
      "name": "my-app",
      "path": "/Users/you/projects/my-app"
    },
    {
      "name": "ref:team-context",
      "path": "/Users/you/stores/team-context"
    }
  ]
}

종료 코드

  • 0: 보고서가 출력된 경우입니다.
  • 1: 루트가 해석되지 않은 경우(cwd 위에 openspec/가 없고 --store도 없음) 또는 --code-workspace 파일 작성이 거부된 경우.

openspec workset ​

개인 작업 뷰를 구성하고 유지하며 엽니다. 워크셋은 함께 작업하는 폴더를 저장하고 이름을 붙인 목록입니다.

bash
openspec workset create checkout --member ~/projects/checkout-api --member web=~/projects/checkout-web
openspec workset list
openspec workset remove checkout --yes
하위 명령하는 일
create [name]선택한 폴더로 이름 있는 작업 뷰를 구성하고 저장합니다.
list, ls저장된 워크셋과 해당 멤버를 표시합니다.
open <name>저장된 워크셋을 도구(편집기 창 또는 에이전트 세션)에서 엽니다.
remove <name>저장된 워크셋을 삭제합니다(멤버 폴더는 절대 건드리지 않습니다).

워크셋은 완전히 로컬입니다:

  • 상태는 폴더 하나에 저장됩니다: ~/.local/share/openspec/worksets/ ($XDG_DATA_HOME/openspec/worksets/가 설정된 경우 해당 경로, Windows에서는 %LOCALAPPDATA%\openspec\worksets\).
  • 멤버 폴더에는 아무것도 기록되지 않으며, 커밋되거나 공유되는 것도 없습니다.
  • 그 폴더 하나를 삭제하면 모든 흔적이 사라집니다.

openspec workset create ​

폴더의 이름 있는 작업 뷰를 저장합니다.

bash
openspec workset create checkout \
  --member ~/projects/checkout-api \
  --member web=~/projects/checkout-web

대화형 터미널에서 create는 플래그로 지정하지 않은 항목을 묻습니다. 즉 이름, 폴더(하나씩), 도구를 묻고, 그다음 지금 워크셋을 열지 제안합니다. 대화형 터미널이 아니면 이름이나 멤버가 누락된 경우 오류입니다. 이미 저장된 이름은 항상 오류입니다. 먼저 해당 워크셋을 제거하세요.

인수

인수설명
name워크셋 이름입니다. kebab-case: 소문자, 숫자, 단일 하이픈. 대화형 터미널이 아니면 필수입니다.

옵션

플래그효과
--member <member>멤버 폴더를 <path> 또는 <name>=<path> 형식으로 지정하며 반복할 수 있습니다. 첫 번째가 기본 멤버입니다. 경로는 기존 폴더여야 하며, 레이블은 기본적으로 폴더 자체의 이름을 사용합니다.
--tool <id>이 워크셋을 열 때 사용할 기본 도구입니다. 기본 제공 ID: code(VS Code), cursor(Cursor). claude 및 codex는 일시적으로 비활성화되어 있습니다.
--json저장된 워크셋을 JSON으로 출력합니다.

출력

Saved workset 'checkout' (2 members) to your machine.
Open it any time with: openspec workset open checkout

openspec workset list ​

저장된 워크셋과 해당 멤버를 이름순으로 표시합니다.

bash
openspec workset list   # 별칭: ls

옵션

플래그효과
--json워크셋을 JSON으로 출력합니다.

출력

워크셋마다 블록 하나를 표시합니다. 이름, 도구가 있으면 해당 도구, 그다음 멤버마다 name path 행 하나를 표시합니다. 저장된 워크셋이 없으면 list는 No worksets saved. Create one with: openspec workset create를 출력합니다.

checkout
  checkout-api  /Users/you/projects/checkout-api
  web           /Users/you/projects/checkout-web
checkout-tool  (opens in VS Code)
  checkout-api  /Users/you/projects/checkout-api

--json 사용 시:

json
{
  "worksets": [
    {
      "name": "checkout",
      "members": [
        {
          "name": "checkout-api",
          "path": "/Users/you/projects/checkout-api"
        },
        {
          "name": "web",
          "path": "/Users/you/projects/checkout-web"
        }
      ]
    }
  ],
  "status": []
}

openspec workset open ​

저장된 워크셋을 도구에서 엽니다. 편집기 도구(code, cursor)에는 생성된 .code-workspace 파일이 제공됩니다. 창이 열리고 명령이 반환됩니다. CLI 에이전트 도구(claude, codex)는 모든 멤버를 연결한 상태로 이 터미널을 넘겨받습니다. 해당 흐름을 재작업하는 동안 이 도구들은 일시적으로 비활성화되어, 현재 워크셋은 IDE에서 열립니다.

bash
openspec workset open checkout                # 저장된 도구 또는 프롬프트
openspec workset open checkout --tool cursor  # 이번 한 번만 이 도구 사용

인수

인수설명
name열 워크셋입니다.

옵션

플래그효과
--tool <id>이번 한 번만 이 도구로 엽니다.

--tool이 없고 저장된 도구도 없으면 open은 설치된 도구를 선택하라는 메시지를 표시합니다. 대화형 터미널이 아니면 대신 종료 코드 1로 종료됩니다.

  • 더 이상 존재하지 않는 멤버 폴더는 경고와 함께 건너뜁니다. 기본 멤버가 없으면 남아 있는 다음 멤버가 이번 open의 기본 멤버가 됩니다. 멤버 폴더가 하나도 없으면 open이 실패합니다.
  • --json은 거부됩니다. open은 터미널을 도구에 넘겨주며 JSON 모드가 없습니다.
  • 실행이 실패하면 오류 메시지는 수동 실행 안내(워크스페이스 파일의 경로와 멤버 목록)로 끝납니다.

종료 코드

  • 도구의 종료 코드를 그대로 반영합니다. 명령은 도구 자체의 종료 코드로 종료되며, 시그널은 128+n(Ctrl-C 후에는 130)이 됩니다.
  • 1: 알 수 없는 워크셋, 사용 가능한 멤버 폴더 없음, 또는 사용 가능한 도구 없음.

openspec workset remove ​

저장된 워크셋과 생성된 .code-workspace 파일을 삭제합니다. 멤버 폴더는 절대 건드리지 않습니다.

bash
openspec workset remove checkout --yes

대화형 터미널에서 remove는 워크셋을 표시하고 확인을 요청합니다. --json을 사용하거나 터미널 밖에서는 --yes가 필요하며, 없으면 종료 코드 1로 종료됩니다.

옵션

플래그효과
--yes비대화형으로 제거를 확인합니다.
--json제거 결과를 JSON으로 출력합니다.

출력

Removed workset 'checkout'. Member folders were not touched.

openspec version ​

실행 중인 OpenSpec 버전과 이 복사본이 설치된 방식을 보고합니다.

bash
openspec version                 # 로컬 버전 및 설치 세부 정보
openspec version --json          # 구조화된 로컬 보고서
openspec version --check         # 레지스트리에서 업데이트도 확인
openspec version --check --json  # 구조화된 로컬 및 업데이트 보고서

--check가 없으면 이 명령은 로컬에서 실행되며 레지스트리에 접속하지 않습니다. OpenSpec 프로젝트 밖에서도 작동합니다. 기존 openspec --version 플래그는 여전히 가장 짧은 형태이며 버전 번호만 그대로 출력합니다.

옵션

플래그효과
--json텍스트 대신 버전이 지정된 JSON 문서 하나를 출력합니다.
--check설정된 레지스트리에서 더 새로운 릴리스가 있는지 확인합니다.

출력

전역 npm 설치의 경우:

text
OpenSpec 1.13.2 (npm, global)

설치 범위는 global, project, npx 같은 임시 실행기의 경우 temporary, 체크아웃의 경우 source, 독립 실행형 설치의 경우 standalone입니다. OpenSpec은 식별할 수 없는 세부 정보를 추측하지 않고 생략합니다.

--json은 알 수 없는 세부 정보를 명시적인 null 값으로 유지합니다:

json
{
  "schemaVersion": 1,
  "version": "1.13.2",
  "install": {
    "location": "/opt/homebrew/lib/node_modules/@fission-ai/openspec",
    "packageManager": "npm",
    "scope": "global"
  }
}

--check 사용 시 업데이트가 있으면 최신 버전과, OpenSpec이 해당 설치에 안전한 명령을 식별할 수 있을 때 그 명령을 추가합니다:

text
OpenSpec 1.13.2 (npm, global)
Update available: 1.14.0
  npm install -g @fission-ai/openspec@latest
json
{
  "schemaVersion": 1,
  "version": "1.13.2",
  "install": {
    "location": "/opt/homebrew/lib/node_modules/@fission-ai/openspec",
    "packageManager": "npm",
    "scope": "global"
  },
  "update": {
    "status": "available",
    "latest": "1.14.0",
    "command": "npm install -g @fission-ai/openspec@latest",
    "canSelfUpgrade": true
  }
}

업데이트 상태 값:

상태의미
available레지스트리가 실행 중인 버전보다 새로운 안전한 버전을 반환했습니다.
current검사가 완료되었고 더 새로운 버전이 없습니다.
disabled기존 개인정보 보호 또는 업데이트 확인 설정이 레지스트리 접근을 차단했습니다. latest는 null입니다.
offline레지스트리를 사용할 수 없었거나 사용할 수 없는 응답을 반환했습니다. latest는 null입니다.

독립 실행형 설치에서는 업데이트 명령이 openspec install입니다.

DO_NOT_TRACK, 텔레메트리 옵트아웃, OPENSPEC_NO_UPDATE_CHECK, CI 감지, 그리고 HTTPS가 아닌 레지스트리 재정의 거부는 검사를 비활성화합니다. 비활성화되거나 오프라인인 검사도 업데이트 가능 여부는 참고용이므로 여전히 종료 코드 0으로 종료됩니다. 이 명령은 OpenSpec을 절대 업그레이드하지 않습니다. canSelfUpgrade는 기존 openspec update 경로가 이 복사본을 안전하게 업그레이드할 수 있는지만 보고합니다.

종료 코드

  • 0: 로컬 보고서가 출력되었습니다. 업데이트 확인이 비활성화되었거나 오프라인이어도 마찬가지입니다.
  • 1: 지원되지 않는 --upgrade 옵션과 같이 명령 구문이 유효하지 않았습니다.

openspec install ​

독립 실행형 openspec을 설치합니다. npm 또는 Homebrew 설치에서 실행하여 전환하거나, 독립 실행형 설치에서 실행하여 제자리에서 업그레이드할 수 있습니다.

bash
openspec install          # 최신 릴리스
openspec install 1.15.0   # 특정 릴리스

설치 스크립트를 실행하여 모든 파일이 첨부된 최신 릴리스와 사용자의 기계에 맞는 파일을 선택하고, 해당 릴리스의 SHA256SUMS으로 검증합니다:

  • 패키지 관리자에서: ~/.local/bin(Windows: %LOCALAPPDATA%\Programs\openspec)에 설치하고 이전 사본을 제거하는 명령을 출력합니다(예: npm uninstall -g @fission-ai/openspec). 이 명령은 직접 제거하지 않습니다.
  • 독립 실행형 설치에서: 실행 중인 파일을 같은 이름으로 제자리에서 교체합니다.

이후 패키지 관리자 사본이 PATH에서 우선하여 제거하기 전까지 계속 실행되므로, 현재 openspec이 어떤 사본을 실행하는지 알려줍니다.

인자

인자설명
version설치할 릴리스(예: 1.15.0). 선택 사항; 기본값은 최신 버전.

OPENSPEC_INSTALL_DIR과 OPENSPEC_INSTALL_NAME으로 다른 폴더 또는 파일 이름을 지정할 수 있습니다.

종료 코드

  • 0: 설치 완료.
  • 1: 버전이 릴리스 버전이 아니거나 다운로드 또는 설치 실패. 현재 사본은 그대로 유지됩니다.

openspec feedback ​

OpenSpec에 대한 피드백을 제출합니다.

bash
openspec feedback "Validate output is hard to scan"
openspec feedback "Archive fails on Windows" --body "Steps: init, propose, archive. Error: EPERM."

CLI는 gh CLI를 통해 Fission-AI/OpenSpec 저장소에 GitHub 이슈로 메시지를 등록합니다. 제목은 Feedback: <message>가 됩니다. 본문은 버그 양식의 제목을 사용합니다: 메시지는 What happened 아래에, --body 텍스트는 Details 아래에 배치되며, CLI가 직접 채울 수 없으므로 단계를 추가하라는 Minimal steps to reproduce 섹션이 포함됩니다. 바닥글에는 CLI 버전, 플랫폼, 타임스탬프가 추가됩니다. 이슈에는 feedback 라벨이 지정됩니다. 저장소에 해당 라벨이 정의되어 있지 않으면 라벨 없이 재시도하고 이를 알립니다.

인자

인자설명
message한 줄 요약. 이슈 제목이 됩니다. 필수.

옵션

플래그효과
--body <text>이슈 본문에 추가되는 상세 설명.

출력

성공 시:

✓ Feedback submitted successfully!
Issue URL: https://github.com/Fission-AI/OpenSpec/issues/1234

gh가 설치되어 있지 않거나 로그인하지 않은 경우 아무것도 제출되지 않습니다. CLI는 --- FORMATTED FEEDBACK --- 마커 사이에 형식이 지정된 피드백을 출력한 다음, 제목, 발생한 일(메시지 및 --body 텍스트), CLI 버전, 환경(플랫폼 및 Node 버전)이 채워진 버그 신고 양식을 여는 링크를 표시합니다. 나머지 양식은 브라우저에서 작성합니다. 로그인하지 않은 경로에는 To auto-submit in the future: gh auth login이 추가됩니다.

종료 코드

  • 0: 이슈 생성 또는 수동 제출 폴백 실행(gh 없음 또는 gh 미로그인).
  • 1: 메시지가 제공되지 않음.
  • gh 고유 코드: 인증 후 gh 실패(네트워크, 속도 제한, 이슈 비활성화). CLI가 피드백과 수동 제출 URL을 먼저 다시 출력합니다.

openspec completion ​

셸 자동 완성을 설치하거나 생성합니다.

bash
openspec completion install        # 셸 감지, 설치, 구성 연결
openspec completion generate zsh   # 스크립트를 stdout으로 출력

지원 셸: zsh, bash, fish, powershell. 모든 하위 명령은 선택적 셸 인자를 받습니다. 생략하면 CLI가 환경에서 셸을 감지합니다.

하위 명령설명
generate [shell]자동 완성 스크립트를 stdout으로 출력.
install [shell]스크립트를 작성하고 셸 시작 파일을 구성.
uninstall [shell]스크립트와 구성 블록을 제거.

Nix로 설치한 경우 자동 완성이 이미 준비되어 있습니다: flake 패키지가 표준 위치에 Bash, Fish, Zsh 스크립트를 제공하므로 install이 필요하지 않습니다(설치).

openspec completion generate ​

스크립트를 출력하고 아무것도 작성하지 않습니다.

#compdef openspec

# Zsh completion script for OpenSpec CLI
# Auto-generated - do not edit manually

_openspec() {
  local context state line
  typeset -A opt_args
...

openspec completion install ​

스크립트를 작성하고 셸 구성을 편집합니다. 구성 편집은 # OPENSPEC:START와 # OPENSPEC:END 마커 사이에 배치됩니다. 기존 스크립트는 먼저 백업됩니다(.backup-<timestamp> 사본).

셸스크립트 위치편집되는 구성
zsh~/.zsh/completions/_openspecZDOTDIR이 절대 경로일 때 $ZDOTDIR/.zshrc, 그렇지 않으면 ~/.zshrc
bash~/.local/share/bash-completion/completions/openspec~/.bashrc
fish~/.config/fish/completions/openspec.fish없음: fish가 자동으로 로드합니다.
powershell프로필 옆의 OpenSpecCompletion.ps1$PROFILE

Oh My Zsh가 설치된 경우 스크립트는 $ZSH_CUSTOM/completions/_openspec(기본 ~/.oh-my-zsh/custom/completions/_openspec)에 배치됩니다.

상대 경로 또는 ~로 시작하는 ZDOTDIR은 무시되고 대신 ~/.zshrc가 편집됩니다. 스크립트가 이미 최신 상태일 때 다시 설치를 실행해도 zsh가 읽는 .zshrc에 블록이 추가됩니다.

옵션

플래그효과
--verbose설치된 경로, 백업 경로, 편집된 구성 파일을 추가로 출력.

출력

✓ Completion script installed and .zshrc configured successfully

Restart your shell or run: exec zsh

openspec completion uninstall ​

스크립트와 표시된 구성 블록을 제거합니다. 구성을 수정하기 전에 확인을 요청합니다(기본값: No).

zsh의 경우 install이 편집하는 .zshrc를 정리하고, ZDOTDIR 아래에 이전 설치가 블록을 남겨둔 경우 ~/.zshrc도 함께 정리합니다. 블록을 제거할 수 없으면 uninstall이 파일 이름을 지정하고 1로 종료합니다.

옵션

플래그효과
-y, --yes확인 프롬프트를 건너뜁니다.

출력

✓ Completion script removed from /Users/you/.zsh/completions/_openspec. Removed OpenSpec configuration from ~/.zshrc

종료 코드

  • 0: 스크립트 생성, 설치 또는 제거 완료. 취소된 uninstall도 0으로 종료됩니다.
  • 1: 셸이 지원되지 않거나 감지되지 않았거나 설치 또는 제거 단계 실패.

openspec change ​

show, list, validate의 비권장 명사형입니다. 실행 시마다 경고를 표시하고 동사형 명령을 안내한 후에도 실행됩니다:

Warning: The "openspec change ..." commands are deprecated. Prefer verb-first commands (e.g., "openspec list", "openspec validate --changes").
Warning: "openspec change list" is deprecated. Use "openspec list".
add-rate-limit
비권장대신 사용
openspec change show <name>openspec show <name>
openspec change listopenspec list
openspec change validate <name>openspec validate <name> (모든 변경 사항: openspec validate --changes)

플래그는 동사형 섹션에서 설명합니다.

openspec spec ​

show, list, validate의 비권장 명사형입니다. 실행 시마다 경고를 표시하고 동사형 명령을 안내한 후에도 실행됩니다:

Warning: The "openspec spec ..." commands are deprecated. Prefer verb-first commands (e.g., "openspec show", "openspec validate --specs").
api
비권장대신 사용
openspec spec show <id>openspec show <id>
openspec spec listopenspec list --specs
openspec spec validate <id>openspec validate <id> (모든 스펙: openspec validate --specs)

플래그는 동사형 섹션에서 설명합니다.