Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 96 additions & 0 deletions skills/doorstop/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# Doorstop Skill

An Agent Skill that gives any compatible AI coding agent (Claude Code, Cursor,
Gemini CLI, Codex CLI, Antigravity) comprehensive, lazily-loaded knowledge of
the [Doorstop](https://github.com/doorstop-dev/doorstop) requirements-management
system.

## What it covers

- Every `doorstop` CLI subcommand and flag
- The Python API (`Tree`, `Document`, `Item`, `build`, `find_document`,
`find_item`, `exporter`, `importer`, `publisher`) and its exception hierarchy
- `.doorstop.yml` and item YAML / Markdown-frontmatter schemas, including
extended attributes, `attributes.reviewed`, `attributes.publish`, and
`!include` composition
- End-to-end workflows: bootstrap, add/link/review/publish, CSV/XLSX round-trip,
suspect-link resolution, release publishing
- The validation engine — full severity matrix and when each flag (`-L`, `-R`,
`-C`, `-Z`, `-S`, `-W`, `-w`, `-e`) is safe
- The `doorstop-server` REST API
- Custom validators (`extensions.item_validator`), programmatic hooks, and
`item_sha_required`
- A JSON snapshot script for agent loops and a CI-friendly lint wrapper

## Install

This skill uses the [OpenSkills](https://github.com/numman-ali/openskills)
universal installer so one package works across Claude Code, Cursor, Gemini
CLI, Codex CLI, and Antigravity.

```sh
# Install from a published GitHub repo, project-local (./.claude/skills/doorstop)
npx openskills install doorstop-dev/doorstop

# Install globally (~/.claude/skills/doorstop)
npx openskills install doorstop-dev/doorstop --global

# Install from a local checkout while developing this skill
npx openskills install ./skills/doorstop --global
```

After install, agents automatically discover the skill via its description in
`SKILL.md` — no further wiring required.

> **Note on `npx skills add`**: some docs use the shorthand `npx skills add …`;
> in April 2026 the working command is `npx openskills install …`. If an alias
> is added to `openskills` later, both forms will work.

## Layout

```
skills/doorstop/
├── SKILL.md # entry point (always-on description, lean body)
├── README.md # this file
├── references/ # lazy-loaded deep references
│ ├── cli-commands.md
│ ├── python-api.md
│ ├── file-formats.md
│ ├── workflows.md
│ ├── validation.md
│ ├── publishing.md
│ ├── import-export.md
│ ├── server-api.md
│ ├── extensions.md
│ └── troubleshooting.md
├── scripts/
│ ├── doorstop_snapshot.py # JSON snapshot for agents
│ └── doorstop_lint.sh # CI-friendly validation
└── assets/
└── example_reqs/ # tiny two-document example tree
```

## Design

This skill follows the **Thin Harness, Fat Skills** principle:

- The always-on surface (SKILL.md frontmatter) is compact.
- Domain judgment lives in `references/*.md`, loaded only when the task needs
it.
- Deterministic truth (flag tables, schemas, REST routes) is expressed as
tables and example files — never as unbounded prose.
- The skill never tries to control harness runtime (scheduling, tool
orchestration). It describes *what* to do; the harness decides *how*.

## Requirements

- Python 3.9+ with Doorstop installed (`pip install doorstop`)
- `git` (Doorstop requires a VCS root)
- Optional: `openpyxl` for XLSX round-trip (installed automatically with
Doorstop), `bottle` for the REST server (same)

## Contributing

This skill lives inside the `doorstop` source repository so it versions with the
tool itself. When Doorstop's CLI surface, file format, or Python API changes,
update the matching reference in `references/` in the same PR.
153 changes: 153 additions & 0 deletions skills/doorstop/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
---
name: doorstop
description: Use for Doorstop requirements work — creating/linking/validating/reviewing/publishing items, editing .doorstop.yml, authoring validators, or driving the doorstop CLI, Python API, or REST server.
---

# Doorstop

Doorstop is a version-controlled requirements management system. It stores
requirements as YAML or Markdown files (one file per item, one directory per
document), linked bidirectionally into a tree, validated for consistency, and
published to text/Markdown/HTML/LaTeX. Every state change has an exact
representation on disk, so git is the source of truth.

## When to use

- Creating, editing, linking, or deleting requirement items
- Bootstrapping a new `reqs/` or `tests/` tree in a repo
- Writing or updating `.doorstop.yml`, item YAML, or Markdown-frontmatter items
- Validating a tree (`doorstop`) and fixing warnings/errors
- Clearing suspect links or marking reviews (`doorstop clear`, `doorstop review`)
- Importing/exporting via CSV/TSV/XLSX for spreadsheet round-trip
- Publishing HTML, Markdown, LaTeX, or text snapshots
- Authoring a custom validator or validation hook
- Calling Doorstop from a Python script or using the REST server

## When not to use

- General Python, YAML, or Markdown authoring with no requirements-management
dimension — use the base tools directly.
- Editing the internal `doorstop/` package code of this repo — that is software
development on Doorstop itself, not *use* of Doorstop. Read the project's
`CONTRIBUTING.md` instead.
- Driving the desktop GUI (`doorstop-gui`) — it is a Tkinter app and not agent-
drivable.

## Core concepts (internalize these)

- **Tree** → **Document** → **Item** → **Link**. Each *document* is a directory
holding a `.doorstop.yml` config and one item file per requirement. Items link
*upward* (child → parent); the tree is bidirectional at runtime.
- **UID** = `<prefix><sep><number-or-name>`, e.g. `REQ001`, `REQ-001`, `TST_007`.
`prefix`, `sep`, and `digits` are set in `.doorstop.yml`.
- **Fingerprint (reviewed)**: SHA-256 of `uid + text + ref + references + links`
(plus any extended attrs listed under `attributes.reviewed`). Stored in the
item's `reviewed:` field. *Never hand-edit it — use `doorstop review`.*
- **Suspect link**: a child's stored parent-fingerprint no longer matches the
parent's current fingerprint. Clear with `doorstop clear`, not by re-reviewing.
- **Level**: outline position like `1.2.3`. `*.0` + `normative: false` ⇒ heading.
- Items are referenced by UID, not by filename. **UIDs are immutable** — renaming
is delete + re-add + re-link.

## First move

When the user asks for any doorstop task, before mutating anything:

1. `git rev-parse --show-toplevel` — Doorstop requires a VCS root. If the user is
outside one, say so and stop.
2. `doorstop` (no args) — if it prints a tree and exits 0, you have a working
tree. If it errors with "no documents found", user is bootstrapping.
3. If you need a structured view, run
`python scripts/doorstop_snapshot.py` (shipped with this skill) to get JSON.
4. Pick the right reference from the map below, read it, then act.

## Workflow map

| Task | Reference |
|---|---|
| Bootstrap a project / create a document | `references/workflows.md` |
| Add / edit / remove items | `references/cli-commands.md` + `references/file-formats.md` |
| Link items across documents | `references/workflows.md` |
| Validate / fix warnings / clear suspects / mark reviewed | `references/validation.md` |
| Publish HTML / Markdown / LaTeX / text | `references/publishing.md` |
| Round-trip via spreadsheet (CSV / TSV / XLSX) | `references/import-export.md` |
| Drive Doorstop from Python / write a script | `references/python-api.md` |
| REST API / integrations | `references/server-api.md` |
| Custom validator / hook / extension | `references/extensions.md` |
| Suspect links / unreviewed / cycles / skipped levels | `references/troubleshooting.md` |
| Every CLI flag + exact subcommand semantics | `references/cli-commands.md` |
| `.doorstop.yml` and item YAML/Markdown schemas | `references/file-formats.md` |

## Non-negotiables

- **Always `doorstop review` after editing item content.** Never write a
`reviewed:` hash yourself — the hash function is SHA-256 over a specific
ordered value set and *will* drift if you compute it wrong.
- **Prefer the CLI for mutations**, not manual YAML edits. `doorstop add` /
`edit` / `link` / `unlink` / `remove` / `clear` / `review` enforce invariants
that hand-edits skip.
- **Run `doorstop` after every batch of changes.** Validation is fast and the
failure modes (suspect links, orphaned children, level gaps) are cheap to fix
when caught immediately.
- **Never mix item formats within a single document.** A document's `itemformat`
is set at `create` time and is effectively read-only after the first item.
- **Never rename an item's file.** The filename *is* the UID.
- **Level `X.0` + `normative: false` is a heading**, not a requirement. Don't
link requirements to headings — validation will warn.
- **Derived items don't need parent links**; mark `derived: true` when the
requirement has no upstream source.
- When generating a wave of items, use `doorstop add -c N` rather than looping —
`add` reserves UIDs atomically through the server when one is running.

## Output expectations

A task is complete when:

- `doorstop` exits 0 (or only with `INFO`-level messages you explicitly accept).
- Every edited item has been passed through `doorstop review`.
- If the task called for publication, the publish artifact exists and contains
the expected items (`index.html` + per-document files for `publish all`).
- Item files and `.doorstop.yml` files are committed (or staged) — remind the
user to commit; doorstop state is meaningless outside version control.

## Reference map

Load references on demand — they are progressive-disclosure files, not always-on
context.

- `references/cli-commands.md` — every `doorstop` subcommand, every flag, canonical
invocations, exit semantics, and when each command is (and isn't) the right tool.
- `references/python-api.md` — `doorstop.build`, `Tree`/`Document`/`Item`, exception
hierarchy, iteration patterns, scripting examples, validation-hook signatures.
- `references/file-formats.md` — `.doorstop.yml` schema, YAML item schema,
Markdown-frontmatter item schema, UID grammar, `references:` block, extended
attributes, publish-list, `!include` tag.
- `references/workflows.md` — end-to-end recipes: bootstrap, add-child-document,
link, review-after-churn, publish-release, bulk-import.
- `references/validation.md` — full INFO/WARNING/ERROR matrix, suspect-link
mechanics, what each `-L/-R/-C/-Z/-S/-W/-w/-e` flag does, when skipping is OK.
- `references/publishing.md` — format matrix, `--template`, `--index`,
`--no-child-links`, `--no-levels`, publish-all layout, traceability matrix.
- `references/import-export.md` — export formats, round-trip via XLSX, the
"blank UID" new-item convention, `--map` for column renames.
- `references/server-api.md` — every REST endpoint with JSON shapes, how the
`--server`/`--port`/`-f/--force` client flags affect item-number reservation.
- `references/extensions.md` — `extensions.item_validator` in `.doorstop.yml`,
`tree.validate(document_hook=, item_hook=)`, `item_sha_required`, custom
publishers, custom attributes.
- `references/troubleshooting.md` — decision tree for the most common failure
modes with the exact commands to run.

## Scripts

- `scripts/doorstop_snapshot.py` — dumps the tree, documents, items, links,
and validation issues as JSON. Use this when you want a structured view
for agent reasoning rather than parsing CLI stdout.
- `scripts/doorstop_lint.sh` — CI-friendly wrapper: runs `doorstop -e` (errors
on any warning) with sensible defaults, returns non-zero on any issue.

## Example tree

`assets/example_reqs/` is a tiny two-document example (`REQ` + `TST`, one link,
one heading) that validates clean. Copy it as a starting template, or read it to
confirm the canonical on-disk shape when you are unsure.
12 changes: 12 additions & 0 deletions skills/doorstop/assets/.doorstop.skip-all
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# This marker tells `doorstop` not to descend into the `skills/doorstop/assets/`
# subtree when building its document tree. The example requirements tree under
# `example_reqs/` is a teaching fixture — it is a real Doorstop tree, but it is
# not part of the Doorstop project's own requirements. Without this marker, a
# plain `doorstop` run at the Doorstop repo root would try to merge
# `example_reqs/` into the project tree and fail with "multiple root documents".
#
# Users copying `example_reqs/` into their own repo should copy the contents of
# that directory only (e.g. `cp -r example_reqs/. /path/to/new/repo`); this
# marker stays behind, so the copied tree is discovered normally.
#
# See `doorstop/core/builder.py` for the scan-prune logic.
44 changes: 44 additions & 0 deletions skills/doorstop/assets/example_reqs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Example reqs tree

A minimal two-document doorstop tree:

- `reqs/` — root document, prefix `REQ`
- `REQ001` — heading ("System Requirements"), level 1.0
- `REQ002` — normative requirement ("Boot time"), level 1.1
- `tests/` — child document, prefix `TST`, parent `REQ`
- `TST001` — normative test linked to `REQ002`

Use it as:

- A copy-paste starting template for a new project.
- Ground truth for the canonical on-disk shape (see
`references/file-formats.md`).
- A target for skill verification — `doorstop` from the root should exit 0
(with INFO about unreviewed items until you run `doorstop review all`).

## Why the parent directory has `.doorstop.skip-all`

The sibling `skills/doorstop/assets/.doorstop.skip-all` marker tells
doorstop not to descend into this directory when scanning a VCS root. That
matters when the skill is installed inside a repo that is *itself* a
Doorstop project — without the marker, doorstop would try to merge this
example tree into the host project's tree and fail with "multiple root
documents".

The marker lives one level **above** this directory, so it stays behind
when you copy this tree elsewhere.

## Try it

```sh
# Copy into a fresh git repo:
mkdir /tmp/demo && cd /tmp/demo && git init
cp -r /path/to/skills/doorstop/assets/example_reqs/. .
doorstop # validate (INFO: unreviewed)
doorstop review all # stamp everything
doorstop # clean
doorstop publish REQ ./REQ.md # single-doc Markdown publish
```

Note the trailing `/.` in the `cp` above — copies the contents, not the
directory itself.
5 changes: 5 additions & 0 deletions skills/doorstop/assets/example_reqs/reqs/.doorstop.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
settings:
digits: 3
itemformat: yaml
prefix: REQ
sep: ''
10 changes: 10 additions & 0 deletions skills/doorstop/assets/example_reqs/reqs/REQ001.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
active: true
derived: false
header: ''
level: 1.0
links: []
normative: false
ref: ''
reviewed: null
text: |
System Requirements
11 changes: 11 additions & 0 deletions skills/doorstop/assets/example_reqs/reqs/REQ002.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
active: true
derived: false
header: |
Boot time
level: 1.1
links: []
normative: true
ref: ''
reviewed: null
text: |
The system **shall** complete startup within 5 seconds of power-on.
6 changes: 6 additions & 0 deletions skills/doorstop/assets/example_reqs/tests/.doorstop.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
settings:
digits: 3
itemformat: yaml
parent: REQ
prefix: TST
sep: ''
13 changes: 13 additions & 0 deletions skills/doorstop/assets/example_reqs/tests/TST001.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
active: true
derived: false
header: |
Boot-time smoke test
level: 1.0
links:
- REQ002: null
normative: true
ref: ''
reviewed: null
text: |
Power-cycle the unit and measure elapsed time from power-on to the
"ready" signal. The measured value must be ≤ 5 seconds.
Loading