Feature Specs skill for Codex
One page with every state decided. Codex writes one-page feature specs that start from the code: it finds the components, handlers and permission checks a change touches, then defines testable behaviour rules, a states table from empty to permission-denied, edge cases for double actions, deletions and limits, final copy and analytics events. Open questions must be resolved before the spec is marked ready.
curl -fsSL codexskills.dev/install.sh \ | sh -s -- feature-specs Installs to ~/.agents/skills/feature-specs/ for every project on this machine.
curl -fsSL codexskills.dev/cli.mjs -o codex-skills.mjsnode codex-skills.mjs install feature-specs The CLI also searches, updates and removes skills. Run it with no arguments to pick from a list. Needs Node 20.12+.
curl -fsSL codexskills.dev/install.sh \ | sh -s -- --project feature-specs Installs to .agents/skills/feature-specs/ in the current repository. Commit it and everyone who runs Codex there gets it.
curl -fsSLO codexskills.dev/downloads/feature-specs.zipunzip -o feature-specs.zip -d ~/.agents/skills/ The archive holds the skill folder with its generated agents/openai.yaml. Unzip into .agents/skills/ to scope it to a repo.
& ([scriptblock]::Create((irm codexskills.dev/install.ps1))) feature-specs PowerShell 5.1 or 7. Installs to %USERPROFILE%\.agents\skills\. Add -Project for the current repo.
104-line POSIX script. No sudo, no telemetry. Read install.sh
Use it in Codex
Start a prompt with $feature-specs, or pick it from /skills.
You can also just describe the task: Codex reads the description below and loads the playbook when your request matches.
What Codex reads before loading it
Writes short, buildable feature specs for small and medium changes - one-page format with context, behaviour rules, a states table (empty, loading, partial, error, success, disabled, permission-denied), edge cases, copy, analytics, and out-of-scope list - grounded in the existing code paths and components the change touches. Use when asked to spec a small feature, write a one-pager for a ticket, define the states and edge cases of a screen or flow, or turn a design or rough idea into something an engineer can pick up today.
Use it when
- A ticket is too vague to start but too small for a PRD
- Designs show only the happy path
- Engineers keep discovering undecided edge cases mid-build
- You need copy and analytics decided before implementation
Use something else when
- The work spans multiple teams or weeks with new metrics: use prd-writing
- You need help designing the visual and copy treatment of states: use ui-copy-states
- The spec is written and you are implementing it: use spec-to-code
How to check the result
An engineer can list every file to change and state to build without asking, every behaviour rule has an acceptance criterion, and no open question blocks a rule.
The mistake it prevents
Specifying only the success state from the design, leaving errors, limits and permissions to be invented during implementation.
A feature spec is done well when it fits on about one page, an engineer can start without a meeting, every UI state and edge case has a decided behaviour (not “TBD”), and it names the code it touches so estimates are grounded. Small features fail on the states nobody wrote down, not on the happy path.
When to use this vs a PRD
| Change | Document |
|---|---|
| One screen, endpoint or flow; days to two weeks; one team | Feature spec (this skill) |
| Multi-week, multiple teams, new metrics or pricing | PRD ($prd-writing) |
| Architecture, data model or service changes | Design doc ($design-docs-rfcs), linked from the spec |
Before writing
- Read the ticket, any design file or screenshot, and related support issues.
- Read
AGENTS.md, then find the code the change touches:
rg -n "InviteMemberDialog|inviteMember" src/ # components and handlers
rg -n "invitations" db/ migrations/ src/models/ # data model
rg -n "can_invite|permissions" src/auth/ # permission checks
- Note existing components, validation helpers, copy patterns and error handling to reuse. A spec that invents a new pattern where one exists creates inconsistency.
Spec template
# Spec: <feature name>
Ticket: <link> | Owner: <PM/eng> | Designs: <link or "none - follow existing patterns">
Status: draft | ready | in progress
## Context (3-5 sentences)
<Who needs this, the problem, evidence, and why now.>
## Behaviour
1. <rule, testable> e.g. Admins and owners can resend a pending invite; members cannot.
2. <rule> Resend is limited to 3 per invite per 24 h; the 4th attempt shows the limit message.
3. <rule> Resending resets the 7-day expiry from the time of resend.
## States
| State | Trigger | What the user sees | Notes |
|---|---|---|---|
| Empty | No pending invites | "No pending invites" + Invite button | Existing EmptyState component |
| Loading | Fetching invites | Skeleton rows (3) | Do not flash under 300 ms |
| Success | Resend OK | Toast "Invite resent to [email protected]" | Row shows new sent time |
| Error - network | Request fails | Inline row error + Retry | Keep row actions enabled |
| Error - limit | 4th resend in 24 h | "You can resend again after 14:20" | Button disabled until then |
| Permission denied | Member opens page | Resend hidden; list read-only | Server enforces too |
| Expired invite | Past expiry | "Expired" badge; Resend creates fresh invite | |
## Edge cases
- Invitee already joined via another invite: resend hidden, row removed on refresh
- Email bounced previously: show warning and allow edit of address
- Two admins resend at once: one email sent; both see success (idempotent per minute)
## Copy
<all user-facing strings, including errors and confirmations>
## Analytics
- `invite_resent` { workspace_id, inviter_role, attempt_number } (server, on email queued)
## Code touchpoints
- src/components/members/PendingInvites.tsx (UI)
- src/api/invitations.ts resend handler; rate limit via existing RateLimiter
- No schema change: uses invitations.last_sent_at, resend_count
## Out of scope
- Bulk resend; editing role on pending invite
## Acceptance criteria
<Given/When/Then for each behaviour rule, or link>
## Open questions
- <question> - owner, due
States checklist
Walk every item; each one gets a row in the states table or a line saying why it does not apply:
- Empty (first use, and after everything is deleted)
- Loading (initial and incremental; what stays interactive)
- Partial (some data loaded, some failed; pagination end)
- Success (feedback, where focus goes next)
- Validation errors (inline, per field, message text)
- System errors (network, server 5xx, timeout) and retry behaviour
- Disabled (why, and how the user learns why)
- Permission denied (hidden vs disabled vs error; server enforcement)
- Limits reached (counts, sizes, rate limits)
- Offline or slow connection, if the platform supports it
- Long content (names, translations, many items)
For the design and copy of these states, see $ui-copy-states.
Edge case prompts
Ask for each behaviour rule:
- What if the same action happens twice (double click, two tabs, two users)?
- What if the referenced thing was deleted, archived or changed in the meantime?
- What happens at 0, 1, the limit, and the limit + 1?
- What about time zones, daylight saving and expiry boundaries?
- What does an API client (not the UI) experience?
- What happens to existing data when this ships (migration, defaults for old rows)?
Workflow
- [ ] 1. Read ticket, designs, related issues
- [ ] 2. Find and read the code touchpoints; note reusable components
- [ ] 3. Draft context and behaviour rules
- [ ] 4. Fill the states table and edge cases from the checklists
- [ ] 5. Write all copy and analytics events
- [ ] 6. Add acceptance criteria (see $acceptance-criteria) and out-of-scope
- [ ] 7. List open questions; resolve or assign them before "ready"
- [ ] 8. Save beside related docs or attach to the ticket per AGENTS.md conventions
Gotchas
- “Show an error” is not a behaviour; write the message, placement and recovery action.
- Permission rules enforced only in the UI are security bugs; the spec must say the server enforces them.
- Specs that grow past two pages are PRDs or need splitting.
- Designs often show only the success state; the spec owns the rest.
- Do not mark a spec ready while open questions affect behaviour rules.
Verification
Read the spec as the implementing engineer: can you list every file to change and every state to build without asking? Check every behaviour rule has an acceptance criterion, every states checklist item is covered or marked not applicable, all copy is written out, and no open question blocks a behaviour rule.
What the zip contains
SKILL.md plus the interface file below. Nothing runs on install.
agents/openai.yaml
Gives the Codex app a display name, a one-line description and a starter prompt for this skill.
interface:
display_name: "Feature Specs"
short_description: "One page with every state decided"
default_prompt: "$feature-specs Write a one-page spec for resending pending invites, check our members code first" About this skill
Written and maintained by the Codex Skills editors to the same editorial standard as every skill here: a selective description, a real workflow, known pitfalls and a way to verify the work. First published , last updated . MIT licensed. Something wrong or out of date? Tell us.