Agent skill

Openspec Aware

by Chorus-AIDLC in Chorus-AIDLC/Chorus

OpenSpec-mode authoring for Chorus PM workflows in Hermes. An agent skill from Chorus-AIDLC/Chorus.

AGPL-3.0Auto-check: notesAgent Workflows

Install Openspec Aware

skills CLI
$ npx skills add Chorus-AIDLC/Chorus --skill openspec-aware -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install Chorus-AIDLC/Chorus openspec-aware --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/Chorus-AIDLC/Chorus.git skills-src && mkdir -p .claude/skills && cp -r skills-src/packages/chorus-hermes/chorus/skills/openspec-aware .claude/skills/openspec-aware && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
openspec-aware
GitHub stars
1.2k
Token cost
~7.2k tokens
SKILL.md length
3,318 words
Files
1
Skills in repo
64
Repo updated
First seen
Licence
AGPL-3.0

At a glance

OpenSpec-mode authoring for Chorus PM workflows in Hermes. An agent skill from Chorus-AIDLC/Chorus.

  • Works in 3 steps: OpenSpec is not disabled… → The project root contains an openspec/… → The openspec CLI is on PATH.
  • Tasks that involve MCP servers
  • SKILL.md covers §1. Spec mode — already…, §2. ⛔ Two non-negotiable rules, §3. OpenSpec mode authoring and §4. When OpenSpec is not the…, plus 3 more sections
  • Calls jq, npm and bash; needs CHORUS_API_KEY

What it does

Openspec Aware is an agent skill from Chorus-AIDLC/Chorus. OpenSpec-mode authoring for Chorus PM workflows in Hermes. The default whenever OpenSpec is usable; consumes the resolved Spec Mode (never re-detects). Scaffolds openspec/changes/<slug/ on disk, and mirrors Markdown files into Chorus document drafts via chorus mcp call --arg-file (the native Chorus MCP tool as fallback when the chorus CLI is missing). Required reading for the proposal, develop, and yolo skills. When OpenSpec is not the resolved mode, this skill no-ops and the caller follows the resolved mode…

Its SKILL.md is about 7.2k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It sits in Agent Workflows, covering MCP servers, Computer vision and Project scaffolding. It works with Model Context Protocol and Bash. The repository describes itself as: The Agent Harness for AI-Human Collaboration, inspired by the AI-DLC (AI-Driven Development Lifecycle). The licence is AGPL-3.0.

When your agent uses it

  • Tasks that involve MCP servers
  • Tasks that involve Computer vision
  • Tasks that involve Project scaffolding

Example prompts

  • “/openspec-aware”

Requirements

  • Python 3
  • Node.js
  • A credential in CHORUS_API_KEY

Workflow steps

3 steps, taken from the first numbered list in SKILL.md.

  1. OpenSpec is not disabled (CHORUS_OPENSPEC_MODE not off, CHORUS_ENABLE_OPENSPEC not false).
  2. The project root contains an openspec/ directory (i.e. someone ran openspec init here).
  3. The openspec CLI is on PATH.

What it can do on your machine

Read from SKILL.md and the folder at commit 4754822. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Shell commands in SKILL.md call:

    • jq
    • npm
    • bash

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    Links to these hosts (documentation or services it may open):

    • github.com

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names these keys or tokens, usually read from environment variables:

    • CHORUS_API_KEY

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Openspec Aware loads about 7.2k tokens when it runs. Until then it costs about 142 tokens; SKILL.md has 3,318 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~142
When it runs · the whole SKILL.md, loaded when a task matches
~7.2k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check: notes

The automated check noted patterns worth knowing about, such as sudo or a known installer.

  • NoteMentions a .env fileSKILL.md:87
    US_URL`, `CHORUS_API_KEY`) or `~/.hermes/.env`; export them in the `terminal` command if the shell does not see them. If

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from Chorus-AIDLC/Chorus at commit 4754822, republished under its AGPL-3.0 licence (© Chorus-AIDLC). 3,318 words, ~7,238 tokens.

Download SKILL.mdSave it as .claude/skills/openspec-aware/SKILL.md (or your agent's skills folder).
name
openspec-aware
description
OpenSpec-mode authoring for Chorus PM workflows in Hermes. The default whenever OpenSpec is usable; consumes the resolved `## Spec Mode` (never re-detects). Scaffolds `openspec/changes/<slug>/` on disk, and mirrors Markdown files into Chorus document drafts via `chorus mcp call --arg-file` (the native Chorus MCP tool as fallback when the `chorus` CLI is missing). Required reading for the proposal, develop, and yolo skills. When OpenSpec is not the resolved mode, this skill no-ops and the caller follows the resolved mode (spec-lite or free-form).
license
AGPL-3.0
metadata.author
chorus
metadata.version
0.22.0
metadata.category
project-management
metadata.mcp_server
chorus

OpenSpec-aware Authoring (Hermes plugin)

This skill is a shared sub-procedure invoked by the Chorus stage skills (proposal, develop, yolo) when the resolved spec mode is a usable OpenSpec — spec-driven authoring through the OpenSpec CLI:

  • Activates when the resolved spec mode is a usable OpenSpec (see §1): CHORUS_SPEC_MODE=openspec or unset, and CHORUS_OPENSPEC_MODE not off, an openspec/ directory exists at the project root, and the openspec CLI is on PATH.
  • Otherwise the calling skill follows the resolved mode — spec-lite (the default when OpenSpec isn't usable) or free-form (CHORUS_SPEC_MODE=off).

See also — spec-lite (the lightweight fallback): OpenSpec (this skill) stays the default whenever usable. When OpenSpec is absent or disabled — or CHORUS_SPEC_MODE=lite — the mode resolves to spec-lite: a durable local .chorus/specs/<slug>/spec.md (never synced) + per-change dated folders <slug>/<YYYY-MM-DD>-<change-slug>/ of Chorus-typed docs mirrored 1:1 into Chorus via the same --arg-file transport. See skill_view("chorus:spec-lite").

When you reach a point in proposal / develop / yolo where this skill is referenced, read the resolved mode from the ## Spec Mode section (see §1) and branch on it. Do not re-derive the detection — the Chorus Hermes plugin's pre_llm_call session-start check-in has already resolved it once for this session.

Hermes specifics: the document-mirror transport is the chorus CLI (chorus mcp call … --arg-file content=<file>, §2 Rule 1), run through the terminal tool. When chorus is not on PATH, the fallback is the native Chorus MCP tool (mcp__chorus__chorus_pm_add_document_draft, mcp__chorus__chorus_pm_update_document_draft, mcp__chorus__chorus_pm_update_document) with content read from the file via read_file. There is no bundled shell wrapper on Hermes. The helper snippets below are Bash; run multi-line blocks under bash -lc (or save them as a .sh script with a Bash shebang) if the terminal shell is not Bash.


§1. Spec mode — already resolved at session start

The Chorus Hermes plugin's pre_llm_call hook resolves the spec mode on the first turn of each session (and again after /reset or context compression) via its spec_mode.py — the single source of truth, a Python port of the canonical resolver with the same rules — and writes a ## Spec Mode section into the injected context stating CHORUS_SPEC_MODE=<lite|openspec|off>; when the resolved mode is a usable OpenSpec it also carries a CHORUS_OPENSPEC_ACTIVE=1 line. That line is present only when CHORUS_SPEC_MODE is openspec or unset, and all three of these hold:

  1. OpenSpec is not disabled (CHORUS_OPENSPEC_MODE not off, CHORUS_ENABLE_OPENSPEC not false).
  2. The project root contains an openspec/ directory (i.e. someone ran openspec init here).
  3. The openspec CLI is on PATH.

Both signals (2) and (3) are required because the OpenSpec authoring path needs the working directory and the CLI. If signal (2) holds but (3) does not, the ## Spec Mode section carries an install hint (npm i -g @fission-ai/openspec); pass it through if asked.

How to read the value

You should already see something like this in your context (look for the ## Spec Mode section near the top of the conversation):

## Spec Mode

CHORUS_SPEC_MODE=openspec (default — openspec/ directory + openspec CLI both present)

CHORUS_OPENSPEC_ACTIVE=1 (openspec/ directory + openspec CLI both present)

or (resolved to lite / off — no CHORUS_OPENSPEC_ACTIVE=1 line):

## Spec Mode

CHORUS_SPEC_MODE=lite (default — OpenSpec not usable: no openspec/ directory at /path/to/repo/openspec)

Branch:

  • CHORUS_OPENSPEC_ACTIVE=1 line present → follow §3 (OpenSpec authoring).
  • No CHORUS_OPENSPEC_ACTIVE=1 line → this skill is a no-op; return to the caller, which follows the resolved CHORUS_SPEC_MODE (spec-lite or free-form). Do not scaffold openspec/changes/. Do not add the slug line to the proposal description.

If the ## Spec Mode section shows an explicit CHORUS_SPEC_MODE=openspec that cannot be honored (OpenSpec disabled or not installed — it carries a config-conflict / not-installed reason and no CHORUS_OPENSPEC_ACTIVE=1 line), the caller MUST halt and surface it — do not silently fall back.

Manual fallback

The mode is resolved by the Chorus Hermes plugin (spec_mode.py) at session start — there is no resolver for you to source, and you must not hand-roll the rule (a hand-rolled OpenSpec-only check ignores CHORUS_SPEC_MODE and the lite/off cases). If the ## Spec Mode section is genuinely absent:

  • You are a delegate_task child (children start with an isolated context): the parent must pass the resolved ## Spec Mode lines verbatim in your context. If it did not, report back to the parent that the spec mode is missing and stop, rather than guessing.
  • Otherwise (e.g. the checkin/connection failed): set CHORUS_SPEC_MODE explicitly (lite | openspec | off) and start a fresh session (/reset, or restart hermes gateway for Chorus-woken sessions) so the plugin re-resolves it — rather than guessing.

§2. ⛔ Two non-negotiable rules

Both are enforced at review time. Both have caused incidents in past releases.

Rule 1 — Fill content from the file (CLI preferred, native-tool fallback); never re-type document content from agent output

Document/draft mirror calls (chorus_pm_add_document_draft, chorus_pm_update_document_draft, chorus_pm_update_document) MUST fill the content field from the local file's bytes, never from a hand-typed body. Calling these tools directly from the native MCP tools with a hand-typed content field is a protocol violation for OpenSpec mode and will fail review. Use whichever transport is available, preferred first:

  • Primary — the chorus CLI: chorus mcp call <tool_name> '<json-without-content>' --arg-file content=<file>. --arg-file content=<path> reads the file's raw bytes and injects them as the JSON content string, byte-exact, so no encoding helper is needed. See §3.6. Requires chorus >= 0.17.0 (the chorus mcp subcommand was added then; an older CLI errors with "unknown command"); on any version or unknown-command failure, upgrade with npm install -g @chorus-aidlc/chorus.
  • Primary transport runs through terminal. The chorus CLI is a Node binary on PATH; run it with the Hermes terminal tool so the file bytes never pass through model context.
  • Fallback — the native Chorus MCP tool, when chorus is not on PATH: read the file with read_file and call mcp__chorus__chorus_pm_add_document_draft / mcp__chorus__chorus_pm_update_document_draft / mcp__chorus__chorus_pm_update_document with content set to the file's text exactly as read — no edits, no reflow, no "fixes", and none of any line-number prefix the reader adds for display. This is a degraded path: the body does pass through model context (token cost) and loses the byte-exact guarantee, so after each call spot-check the round-trip (§3.9 step 4) and prefer installing the CLI (npm install -g @chorus-aidlc/chorus) before any multi-document mirror. There is no bundled shell wrapper on Hermes.

New to the chorus CLI? See skill_view("chorus:chorus-cli") for install, configuring agents (chorus agents add|remove|list), the connection env vars, and chorus mcp basics.

Acting identity — which agent the call acts as. chorus mcp call resolves the agent from, in order: CHORUS_AGENT_PROFILE (a name or UUID) → CHORUS_URL + CHORUS_API_KEY in the environment → the single agent configured in ~/.chorus/daemon.json. On Hermes the credentials come from the environment (CHORUS_URL, CHORUS_API_KEY) or ~/.hermes/.env; export them in the terminal command if the shell does not see them. If a mirror call fails with Multiple agents … specify --agent (several agents configured and no profile/creds in the env), pass your own identity explicitly: chorus mcp call <tool> … --agent <your-agentUuid> — your UUID is in your chorus_checkin result, and chorus agents lists every configured name/UUID.

Reasons (they are why the CLI path is preferred, and why the fallback must copy the file text verbatim):

  1. Token cost. Re-typing a multi-thousand-line markdown body through the LLM burns input + output tokens for every draft. The CLI's --arg-file streams the file's bytes into the JSON string — content never enters LLM context. A typical 3-doc proposal mirror costs roughly zero content-tokens this way; via direct MCP with a re-typed body it routinely costs 20k+.
  2. Byte-equality. The CLI's --arg-file is a byte-faithful encoder: backslashes, quotes, newlines, code-fence content, zero-width chars all survive. LLM re-emission has a non-zero failure rate on long markdown — table alignment drifts, fence escapes get "fixed", long URLs wrap. The exact byte-equality guarantee holds only on the --arg-file path, never on LLM re-emission — which is why the native-tool fallback needs a round-trip spot check.
  3. Single source of truth. With a file-fill mirror, the local openspec/changes/<slug>/*.md is authoritative and Chorus is a mirror. With agent re-typing, authority splits between local file and whatever the LLM happened to output — a future diff cannot tell which one is correct.
Rule 2 — Halt on error via chorus_check_response

Every chorus mcp call must check three signals: exit code, "error": in body, empty body. Bare RC=$? is defense in depth only — an auth failure or a tool-level error can surface in the body rather than the exit code, so a single-signal check can silently miss the most common runtime failure. See §6 for the helper definition. On the native-tool fallback, treat any error result (or an empty/unexpected result) from the tool as a halt.


§3. OpenSpec mode authoring

3.1 Pick a slug

openspec/changes/<slug>/ is the local change folder. The slug must be:

  • kebab-case (add-export-csv, not addExportCsv or add_export_csv),
  • derived from the source Idea title,
  • unique within openspec/changes/.

Record it for later steps:

bash
SLUG="add-export-csv"
3.2 Scaffold the change folder
bash
openspec new change "$SLUG" --description "<one-line idea summary>"

This creates openspec/changes/$SLUG/ with README.md and .openspec.yaml. Then author by hand:

Local filePurposeMirror as Document.type
proposal.mdWhy + What Changes + Capabilities + Impactprd
design.mdArchitecture, contracts, riskstech_design
specs/<capability>/spec.mdDelta spec (## ADDED Requirements + Scenarios)spec (one draft per capability)
tasks.mdOpenSpec tasks list(not mirrored — Chorus task drafts are source of truth)

Use openspec instructions <artifact> --change "$SLUG" (artifacts: proposal, specs, design, tasks) for templates.

3.3 Spec file shape (verified against openspec instructions specs)

A delta spec lists one or more block headers — ## ADDED Requirements, ## MODIFIED Requirements, ## REMOVED Requirements, ## RENAMED Requirements — and within each, ### Requirement: entries. Mix freely in the same file; only include the blocks you actually need.

## ADDED Requirements

Append a brand-new Requirement to the long-term spec.

## ADDED Requirements

### Requirement: <name>
<requirement text — use SHALL / MUST for normative behavior>

#### Scenario: <name>
- **WHEN** <condition>
- **THEN** <expected outcome>
## MODIFIED Requirements

Whole-block replacement, not merge. Whatever you write here completely replaces the existing same-named Requirement in the long-term spec — title, description, and all scenarios. Half-writing it deletes the rest.

## MODIFIED Requirements

### Requirement: <existing name>
<full updated requirement text>

#### Scenario: <name>
- **WHEN** <condition>
- **THEN** <expected outcome>

#### Scenario: <other name>
- **WHEN** <condition>
- **THEN** <expected outcome>

Always include every scenario you want the post-archive spec to have, even ones that were already present and unchanged.

## REMOVED Requirements

Delete a Requirement from the long-term spec. The block under the heading is just the requirement name(s) you're removing — no scenarios needed.

## REMOVED Requirements

### Requirement: <existing name>
## RENAMED Requirements

Rename a Requirement's title. Body and scenarios are preserved as-is in the long-term spec; use MODIFIED instead if you need to change anything besides the title.

## RENAMED Requirements

### Requirement: <old name> -> <new name>

Critical formatting rules (verified):

  • Scenarios MUST use exactly 4 hashtags (#### Scenario:). 3 hashtags or a bullet list silently fail validation.
  • Every ### Requirement: under ADDED or MODIFIED MUST have at least one #### Scenario:.
  • MODIFIED blocks MUST include the full updated content — they overwrite, not patch.
  • Use SHALL / MUST for normative requirements; avoid should / may.
  • The merge into openspec/specs/<capability>/spec.md happens at openspec archive time (§3.9), not at proposal time. While the proposal is in flight, Chorus only sees the delta file as one spec Document — there is no half-merged state for the skill to reason about.

Optional:

bash
openspec validate "$SLUG"
3.4 Filling the content field byte-exact

The document content must be inserted byte-for-byte from the local file — never re-typed by the LLM. Two mechanisms, preferred first:

  • Primary — chorus mcp call … --arg-file content=<path> (§3.6). The CLI reads the file's raw bytes and injects them as the JSON content string. This is byte-faithful, so no encoding helper is needed — pass the base JSON without a content field and let --arg-file fill it.
  • Fallback — the native MCP tool (§3.6 fallback, used only when chorus is not on PATH). content is the read_file text copied verbatim; verify the round-trip afterwards.

Round-trip verification is exact: a trailing newline difference is real drift and MUST NOT be normalized or ignored.

3.5 Create the proposal container with the slug provenance line

Use the regular chorus_pm_create_proposal MCP tool (no CLI required for this single call — the description is short, the LLM-emitted version is fine). The description must carry exactly one line:

OpenSpec change slug: <slug>
  • on its own line (no other text on that line),
  • literal prefix OpenSpec change slug: (capital O, capital S, single space after colon),
  • no trailing punctuation,
  • value matches the slug passed to openspec new change.

This line is machine-grep-able by future runs of this skill and by the §3.9 archive trigger.

3.6 Mirror each document draft (CLI primary, native-tool fallback)

Rule 1 reminder: content comes from the file's bytes, never a hand-typed body. The agent must not retype the document body.

Define the halt-on-error helper from §6 once at the top. Primary path — the chorus CLI: pass the base JSON without a content field and let --arg-file content=<file> fill it byte-exact. One call per file:

bash
# PRD draft — --arg-file fills content byte-exact from the file; no encoding helper needed.
RESULT=$(chorus mcp call chorus_pm_add_document_draft \
  "{\"proposalUuid\":\"$PROPOSAL_UUID\",\"type\":\"prd\",\"title\":\"PRD: $HUMAN_TITLE\"}" \
  --arg-file content="openspec/changes/$SLUG/proposal.md")
RC=$?
chorus_check_response "chorus_pm_add_document_draft (prd)" "$RC" "$RESULT"
PRD_DRAFT_UUID=$(printf '%s' "$RESULT" | grep -o '"draftUuid"[[:space:]]*:[[:space:]]*"[^"]*"' | head -1 | sed 's/.*"\([^"]*\)"$/\1/')

Repeat with type: "tech_design" for design.md, and one call per capability with type: "spec" for each specs/<capability>/spec.md. Do not mirror tasks.md — Chorus task drafts (created via the chorus_pm_add_task_draft MCP tool, no CLI needed) are the source of truth for tasks.

Why parsing uses printf '%s' "$RESULT" | grep not echo "$RESULT" | jq: echo interprets backslash sequences inside the captured JSON, turning embedded \n into a real newline. jq then aborts with Invalid string: control characters from U+0000 through U+001F must be escaped. printf '%s' emits the captured bytes verbatim. Same pattern applies to all CLI-result parsing in this skill.

Show full SKILL.md (1,262 more words)Show less
Fallback — when the chorus CLI is not on PATH

If command -v chorus fails, mirror through the native Chorus MCP tool instead. There is no shell wrapper or encoding helper on Hermes. Per file:

  1. read_file("openspec/changes/<slug>/proposal.md") — take the file text exactly as stored (drop any display-only line-number prefix).

  2. Call the native tool with that text as content:

    mcp__chorus__chorus_pm_add_document_draft({
      proposalUuid: "<proposalUuid>",
      type: "prd",
      title: "PRD: <human title>",
      content: "<the file text, verbatim>"
    })
  3. Treat any error (or empty) result as a halt (§6). Record the returned draftUuid.

Repeat for design.md (tech_design) and each specs/<capability>/spec.md (spec). Because this path re-emits the body, spot-check the round-trip once the drafts materialize (§3.9 step 4), and install the chorus CLI before the next mirror if you can.

3.7 Editing a draft after the first mirror

Local file changes propagate via chorus_pm_update_document_draft — same primary/fallback split as §3.6, same halt check. Primary (CLI):

bash
RESULT=$(chorus mcp call chorus_pm_update_document_draft \
  "{\"proposalUuid\":\"$PROPOSAL_UUID\",\"draftUuid\":\"$PRD_DRAFT_UUID\"}" \
  --arg-file content="openspec/changes/$SLUG/proposal.md")
RC=$?
chorus_check_response "chorus_pm_update_document_draft" "$RC" "$RESULT"

Fallback (no chorus on PATH) — the native tool, same rules as the §3.6 fallback:

mcp__chorus__chorus_pm_update_document_draft({
  proposalUuid: "<proposalUuid>",
  draftUuid: "<prdDraftUuid>",
  content: "<read_file text of openspec/changes/<slug>/proposal.md, verbatim>"
})
3.8 Editing a Document after proposal approval

Once the proposal is approved, drafts materialize into Documents with their own UUIDs. To keep openspec/changes/$SLUG/ and the Chorus Document in sync, mirror file edits via chorus_pm_update_document. Primary (CLI):

bash
RESULT=$(chorus mcp call chorus_pm_update_document \
  "{\"documentUuid\":\"$SPEC_DOCUMENT_UUID\"}" \
  --arg-file content="openspec/changes/$SLUG/specs/<capability>/spec.md")
RC=$?
chorus_check_response "chorus_pm_update_document" "$RC" "$RESULT"

Fallback (no chorus on PATH) — the native tool, same rules as the §3.6 fallback:

mcp__chorus__chorus_pm_update_document({
  documentUuid: "<specDocumentUuid>",
  content: "<read_file text of openspec/changes/<slug>/specs/<capability>/spec.md, verbatim>"
})

To re-derive $SPEC_DOCUMENT_UUID from a fresh shell, look it up via chorus_get_documents for the proposal's project and match by title + type. Re-derive $SLUG by grepping the proposal's description for ^OpenSpec change slug: .

3.9 Archive after the last task is verified

When the LAST task of an OpenSpec-mode idea is admin-verified via chorus_admin_verify_task, the Chorus Hermes plugin's transform_tool_result hook appends an OpenSpec Archive Trigger reminder (branch A of its post-verify reminders) to the tool result. It contains the literal substring openspec archive <slug> and the project/proposal UUIDs, so you can act without re-reading the slug.

The reminder is only a reminder — the plugin does not archive anything; you (the agent) perform the archive:

  1. Run archive locally. Use --yes for non-interactive mode. Do NOT pass --skip-specs (defeats the mirror-back) or --no-validate (lets malformed deltas corrupt cumulative specs).

    bash
    openspec archive "$SLUG" --yes

    This moves openspec/changes/$SLUG/ under openspec/changes/archive/<date>-<slug>/ and emits/updates openspec/specs/<capability>/spec.md for each capability. (Run openspec archive --help against your installed version to confirm the current flag set — flags can drift between releases.)

  2. Mirror each updated openspec/specs/<capability>/spec.md back to the matching post-approval Chorus Document (§3.8 contract). chorus_get_documents only supports projectUuid + type server-side filters; filter by title client-side. One chorus_pm_update_document call per capability.

  3. Halt on any error from openspec archive or chorus_pm_update_document. Print stderr verbatim, post a comment on the proposal recording the failure (chorus_add_comment with targetType: "proposal", targetUuid: <proposalUuid>), then stop. No retry. Matches §6 "no silent errors." (Comment on the proposal, not the idea: the failure is in archiving proposal-derived specs, and proposals can be inputType: "document" with no idea attached.)

  4. Confirm success. For each capability, verify that openspec/specs/<capability>/spec.md round-trips byte-equal with its Chorus Document. The --arg-file mirror path already guarantees this, so a spot check is enough: fetch the Document with chorus mcp call chorus_get_document '{"documentUuid":"<uuid>"}', write its content to a temp file, and cmp (or compare SHA-256 of) both files. Do NOT use jq -r to extract the content — it appends a trailing newline and manufactures a phantom 1-byte drift (a spec that mirrored correctly will read as 1 byte longer on the server). Use jq -j (no trailing newline), and never rely on recursive jq, head, command substitution, or newline normalization. On mismatch report only byte counts and hashes. (The Chorus Hermes plugin ships no round-trip verifier script — the --arg-file byte-equality guarantee makes it unnecessary.) If the mirror went through the native-tool fallback (no chorus CLI), fetch with chorus_get_document and compare the content against the local file as closely as you can; flag any visible drift and recommend a CLI re-mirror.

Strict opt-in: if the verified task is not the last of its idea, OR the proposal description carries no OpenSpec change slug: <slug> line, OR the local shell has no openspec CLI, the plugin appends no archive reminder (branch A stays silent; the code-review and report reminders, branches C and B, are independent). Existing free-form behavior is preserved.


§4. When OpenSpec is not the resolved mode

When the resolved mode is not a usable OpenSpec (no CHORUS_OPENSPEC_ACTIVE=1 line), this skill is a no-op — return to the calling skill, which follows the resolved CHORUS_SPEC_MODE: spec-lite (the default when OpenSpec isn't usable) or free-form (=off). From this skill's side:

  • No openspec/changes/ folder is created or referenced.
  • No OpenSpec change slug: … line is added to the proposal description.
  • In spec-lite, the caller follows skill_view("chorus:spec-lite") (durable .chorus/specs/<slug>/spec.md + dated per-change folders mirrored via --arg-file); in free-form, document drafts are authored via direct MCP chorus_pm_add_document_draft calls with inline content — same as before this skill existed.
  • Rule 1 (file-fill mirror) still applies in spec-lite (mirror from the local file); in free-form there is no local file source of truth.
  • The §3.9 archive reminder never fires (no slug → branch A silent); spec-lite has no archive step at all.

§5. Document type mapping (reference table)

Local fileChorus Document.typeMirrored?
openspec/changes/<slug>/proposal.mdprdyes
openspec/changes/<slug>/design.mdtech_designyes
openspec/changes/<slug>/specs/<capability>/spec.mdspecyes (one draft per capability)
openspec/changes/<slug>/tasks.md(not mapped)no — Chorus task drafts are source of truth

prd, tech_design, spec are pre-existing valid Document.type values — no schema change required.


§6. Failure visibility — the chorus_check_response helper

This helper guards every chorus mcp call on the primary path. chorus mcp call exits non-zero on tool/transport errors, so RC is usually reliable — but an error can also arrive as an "error" object in an otherwise successful body, and an empty body means the call produced nothing usable. Run the three-signal check after every call, as defense in depth. (On the native-tool fallback there is no shell result to check: halt on any error or empty tool result.)

Define this helper once at the top of the authoring session and use it after every chorus mcp call mirror:

bash
chorus_check_response() {
  local _tool="$1"
  local _rc="$2"
  local _body="$3"
  local _has_error=0
  local _is_empty=0

  local _trimmed
  _trimmed=$(printf '%s' "$_body" | tr -d ' \t\n\r')
  [ -z "$_trimmed" ] && _is_empty=1

  if [ "$_is_empty" -eq 0 ]; then
    if command -v jq >/dev/null 2>&1; then
      if printf '%s' "$_body" | jq -e 'try ([.. | objects | has("error")] | any) catch false' >/dev/null 2>&1; then
        _has_error=1
      fi
    else
      printf '%s' "$_body" | grep -qE '"error"[[:space:]]*:' && _has_error=1
    fi
  fi

  if [ "$_rc" -ne 0 ] || [ "$_has_error" -eq 1 ] || [ "$_is_empty" -eq 1 ]; then
    echo "ERROR: $_tool failed (exit=$_rc, error_in_body=$_has_error, empty_body=$_is_empty)" >&2
    echo "Output: $_body" >&2
    [ "$_rc" -ne 0 ] && exit "$_rc" || exit 1
  fi
}

Anti-patterns — do not:

  • Collapse to || true.
  • Redirect stderr to /dev/null.
  • Bury the chorus mcp call inside a pipeline (masks $?).
  • Skip capturing $RESULT into a variable; the helper needs the body.
  • Use only if [ "$RC" -ne 0 ]; then ... — that misses the HTTP-error path.

Minimal call site shape:

bash
RESULT=$(chorus mcp call <tool_name> '<json-without-content>' --arg-file content=<file>)
RC=$?
chorus_check_response "<tool_name>" "$RC" "$RESULT"
# ...if we reach here, the call succeeded; parse RESULT and continue.

This is project-wide policy: no silent errors.


§7. Quick reference checklist

When invoked from a stage skill (proposal / develop / yolo):

  1. Read the ## Spec Mode section injected by the Chorus Hermes plugin at session start (§1) — proceed only if it carries the CHORUS_OPENSPEC_ACTIVE=1 line. If the section is absent, use the fallback in §1 (parent-forwarded mode, or set CHORUS_SPEC_MODE explicitly + /reset).
  2. No CHORUS_OPENSPEC_ACTIVE=1 line → no-op; return to the caller per the resolved CHORUS_SPEC_MODE (spec-lite or free-form) — see §4.
  3. Otherwise: a. Pick $SLUG (§3.1). b. openspec new change "$SLUG" (§3.2). c. Author proposal.md, design.md, specs/<capability>/spec.md (§3.2–§3.3). Mix ADDED / MODIFIED / REMOVED / RENAMED blocks as needed; remember MODIFIED overwrites the whole Requirement. d. Optional: openspec validate "$SLUG". e. chorus_pm_create_proposal (direct MCP) with the OpenSpec change slug: $SLUG line in description (§3.5). f. Define the chorus_check_response helper. Use chorus mcp call … --arg-file content=<file> via terminal for mirrors (§3.6). Only when chorus is not on PATH, fall back to the native MCP tool with the read_file text verbatim (§2 Rule 1). g. For each row in §5 with "yes" — mirror via chorus mcp call chorus_pm_add_document_draft … --arg-file content=<file> (§3.6; fallback = native mcp__chorus__chorus_pm_add_document_draft). Record each $DRAFT_UUID. h. On any failed chorus_check_response — halt, surface the error, do NOT proceed.
  4. Edits before approval → §3.7. Edits after approval → §3.8.
  5. Last task verified → the plugin's post-verify reminder (branch A) appears → run §3.9 archive flow.

© Chorus-AIDLC, AGPL-3.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in packages/chorus-hermes/chorus/skills/openspec-aware of Chorus-AIDLC/Chorus.

Open the folder on GitHubat commit 4754822

Compare with similar skills

Openspec Aware next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Openspec Aware compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Openspec Aware this skillChorus-AIDLC/Chorus1.2k—~7.2kAutomated safety check: NotesAGPL-3.0
Chatgpt AppsHaohao-end/openagent8071 repos~4.9kAutomated safety check: PassApache-2.0
Crush Configurationcharmbracelet/crush29k—~3.7kAutomated safety check: PassCustom licence
Record Demoapify/mcpc983—~3.3kAutomated safety check: NotesApache-2.0
MCP Scaffoldtimothywarner-org/claude-code224—~940Automated safety check: PassMIT
AI Bomcdxgen/cdxgen1.1k—~2.5kAutomated safety check: PassApache-2.0

Similar skills

  • Chatgpt Apps

    Haohao-end/openagent

    Build, scaffold, refactor, and troubleshoot ChatGPT Apps SDK applications that combine an MCP server and widget UI.

    807 GitHub starsUsed in 1 repo~4.9k tokens
    Agent WorkflowsAuto-check passed
  • Crush Configuration

    charmbracelet/crush

    Explains how to configure the Crush coding agent with crushrc or crush.json, covering providers, models, LSPs, MCP servers, hooks, permissions and config precedence.

    29k GitHub stars~3.7k tokensUpdated yesterday
    Agent WorkflowsAuto-check passed
  • Record Demo

    apify/mcpc

    Official

    Record or regenerate the mcpc demo GIFs (the README hero docs/images/mcpc-demo.gif and the focused tapes in docs/vhs/) with VHS.

    983 GitHub stars~3.3k tokensUpdated yesterday
    Agent WorkflowsAuto-check: notes
  • MCP Scaffold

    timothywarner-org/claude-code

    Scaffold production-ready Python MCP servers using FastMCP. An agent skill from timothywarner-org/claude-code.

    224 GitHub stars~940 tokensUpdated 2 mo ago
    Agent WorkflowsAuto-check passed
  • AI Bom

    cdxgen/cdxgen

    Generates AI-BOM, MCP inventory, AI skill inventory, and AI authorship provenance documents with cdxgen, cataloging models, inference services, Hugging Face purls, MCP servers and their…

    1.1k GitHub stars~2.5k tokensUpdated today
    Agent WorkflowsAuto-check passed
  • Stitch Upload To Stitch

    majiayu000/claude-skill-registry

    Upload local assets (images, mockups, extracted HTML, design markdown) to a Stitch project.

    666 GitHub starsUsed in 1 repo~1.1k tokens
    Agent WorkflowsAuto-check: notes

More from Chorus-AIDLC/Chorus

All 64 skills in this repo
  • E2E Verification

    Chorus-AIDLC/Chorus

    A skill your agent uses when manually verifying a Chorus frontend change in a real browser — finding local login credentials, driving the running dev server with the Playwright MCP, logging in…

    1.2k GitHub stars~1.5k tokensUpdated yesterday
    Auto-check: notes
  • Blog

    Chorus-AIDLC/Chorus

    Write release blog posts for Chorus — problem-first narrative, bilingual (zh/en), following the project's editorial style.

    1.2k GitHub stars~1.2k tokensUpdated yesterday
    Auto-check passed
  • Brainstorm

    Chorus-AIDLC/Chorus

    Optional divergent-then-convergent dialogue for fuzzy ideas on Hermes.

    1.2k GitHub stars~3.6k tokensUpdated yesterday
    Auto-check passed
  • Brainstorm

    Chorus-AIDLC/Chorus

    Optional divergent-then-convergent dialogue for fuzzy ideas.

    1.2k GitHub stars~2.5k tokensUpdated yesterday
    Auto-check passed
  • Brainstorm Chorus

    Chorus-AIDLC/Chorus

    Optional divergent-then-convergent dialogue for fuzzy ideas.

    1.2k GitHub stars~2.5k tokensUpdated yesterday
    Auto-check passed
  • Chorus Brainstorm

    Chorus-AIDLC/Chorus

    Optional divergent-then-convergent dialogue for fuzzy ideas.

    1.2k GitHub stars~2.3k tokensUpdated yesterday
    Auto-check passed

Questions about Openspec Aware

What does Openspec Aware do?

OpenSpec-mode authoring for Chorus PM workflows in Hermes. An agent skill from Chorus-AIDLC/Chorus. Openspec Aware is an agent skill from Chorus-AIDLC/Chorus. OpenSpec-mode authoring for Chorus PM workflows in Hermes.

When should I use Openspec Aware?

Openspec Aware fits situations like: tasks that involve MCP servers; tasks that involve Computer vision; tasks that involve Project scaffolding.

How do I install Openspec Aware in Claude Code?

Run `npx skills add Chorus-AIDLC/Chorus --skill openspec-aware -a claude-code`. Or copy the skill folder (packages/chorus-hermes/chorus/skills/openspec-aware in Chorus-AIDLC/Chorus) into .claude/skills/openspec-aware in your project. Claude Code loads it when a task matches its description.

How do I install Openspec Aware in Codex?

Run `npx skills add Chorus-AIDLC/Chorus --skill openspec-aware -a codex`. Or copy the skill folder (packages/chorus-hermes/chorus/skills/openspec-aware in Chorus-AIDLC/Chorus) into .agents/skills/openspec-aware in your project. Codex loads it when a task matches its description.

Can I use Openspec Aware in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add Chorus-AIDLC/Chorus --skill openspec-aware -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/openspec-aware, .gemini/skills/openspec-aware, .github/skills/openspec-aware and .opencode/skills/openspec-aware in your project.

What does Openspec Aware need to run?

Going by SKILL.md and its folder, Openspec Aware needs the command-line tools its instructions call (jq, npm and bash) and credentials named CHORUS_API_KEY. Our summary lists: Python 3; Node.js; A credential in CHORUS_API_KEY.

Does Openspec Aware access the network?

SKILL.md names 1 domain. As links in the text: github.com. This is read from the text; nothing was executed.

Is Openspec Aware safe to install?

Our automated static check of SKILL.md found notes only (mentions a .env file), nothing it rates as a warning. It is not a guarantee. Review the folder before installing.

What licence does Openspec Aware use?

Openspec Aware is published under the AGPL-3.0 licence (declared in SKILL.md). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Openspec Aware use?

About 7.2k tokens (SKILL.md is roughly 29k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Openspec Aware?

Skills that share tags, products or a category with Openspec Aware: Chatgpt Apps (Haohao-end/openagent, 807 stars), Crush Configuration (charmbracelet/crush, 29k stars), Record Demo (apify/mcpc, 983 stars) and MCP Scaffold (timothywarner-org/claude-code, 224 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Openspec Aware?

Chorus-AIDLC (a GitHub organization) maintains it in Chorus-AIDLC/Chorus, which has 1,192 GitHub stars. The repository holds 64 skills in this directory. The repository was last updated on October 7, 2026.

Source: Chorus-AIDLC/Chorus on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.