Postmortem Writing skill for Codex

Outage write-ups that change something. Codex builds the incident timeline from alert, deploy and chat evidence in UTC, marks impact start, detection, mitigation and resolution, and only then writes the summary. Contributing factors are grouped into trigger, latent conditions, detection and response, each mapped to a specific action with an owner and due date, and a blame-language pass rewrites anything that points at a person.

  • Writing & Docs
  • $postmortem-writing
  • 200 lines
  • 2 files
  • ~2,300 tokens
  • MIT
  • Updated

Install

curl -fsSL codexskills.dev/install.sh \  | sh -s -- postmortem-writing

Installs to ~/.agents/skills/postmortem-writing/ for every project on this machine.

104-line POSIX script. No sudo, no telemetry. Read install.sh

Use it in Codex

Start a prompt with $postmortem-writing, 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 blameless incident postmortems from raw evidence - Slack or chat exports, alert history, deploy logs, dashboards and on-call notes - producing a UTC timeline, impact in user terms, contributing factors, detection and response gaps, and owned action items with due dates. Use when asked to write up an outage, turn an incident channel into a postmortem, draft a post-incident review or RCA document, or review a draft postmortem for blame, vagueness or weak actions.

Use it when

  • An incident is over and needs a written review
  • You have a chat export, alerts and deploy logs but no document yet
  • A draft postmortem blames people or has actions like 'improve monitoring'
  • Leadership wants an outage summary that still holds up to engineering review

Use something else when

How to check the result

Every timeline row cites a source, impact numbers trace to queries, each contributing factor maps to an owned and dated action, and a search for blame phrases returns nothing unaddressed.

The mistake it prevents

Stopping the analysis at 'human error' and writing 'be more careful' as the action, which guarantees the same incident recurs.

~/.agents/skills/postmortem-writing/SKILL.md

--- name: postmortem-writing description: Writes blameless incident postmortems from raw evidence - Slack or chat exports, alert history, deploy logs, dashboards and on-call notes - producing… license: MIT ---

A good postmortem lets someone who was not there understand what users experienced, why the system allowed it, and what will be different next time. Every claim traces to evidence, no sentence assigns fault to a person, and every action item has an owner, a date and a way to tell it is done.

Before writing anything

  1. Collect the raw material and keep it read-only: incident channel export, pager/alert history, deploy and config-change logs, relevant graphs (with timestamps), support ticket counts, status page updates, and any notes the incident commander kept.
  2. Read the team’s existing template. Search the repo or docs folder first (rg -il "postmortem|post-incident|incident review" docs/) and check AGENTS.md for where documents live. Use their headings if they exist; the template below is the fallback.
  3. Confirm with the user: severity level, the audience (internal engineering, whole company, or customers), and whether anything is under legal or security embargo. A customer-facing summary is a separate, shorter document derived from this one.

The live response itself (roles, comms cadence, paging) belongs to $incident-command. Deep causal analysis techniques (five whys, fault trees) belong to $root-cause-analysis; this skill turns their output into the written record.

Workflow

- [ ] 1. Build the timeline from evidence, in UTC, one event per line
- [ ] 2. Mark the four anchor times: start of impact, detection, mitigation, resolution
- [ ] 3. Quantify impact in user terms
- [ ] 4. Write the summary last-but-one (after the timeline is stable)
- [ ] 5. Identify contributing factors, not a single root cause
- [ ] 6. Record what went well and where the response was slowed
- [ ] 7. Derive action items from factors; assign owner, date, ticket
- [ ] 8. Run the blame and vagueness pass
- [ ] 9. List open questions instead of guessing

1. Timeline

  • Normalise every timestamp to UTC with the date (2026-03-14 09:42 UTC). Chat exports are often in the exporter’s local time; check the offset against an alert timestamp.
  • One line per event. Source each line: (alert), (deploy log), (#inc-482).
  • Include the quiet gaps. “09:58-10:31 no action; responder investigating DB metrics” is more useful than skipping to the fix, because gaps reveal detection and tooling problems.
  • Describe actions, not people’s states of mind: “on-call rolled back to v4.12.3”, not “on-call panicked and rolled back”.
AnchorDefinitionDerived metric
Impact startFirst moment users were affected (from metrics, not from the first alert)-
DetectedFirst alert or report that a human sawTime to detect = detected - impact start
MitigatedUser impact stopped or reduced to acceptableTime to mitigate = mitigated - detected
ResolvedSystem back to normal state, temporary fixes accounted forDuration = resolved - impact start

If impact start can only be estimated, say so and give the evidence (“error rate first exceeds baseline at 09:31 on the API dashboard”).

2. Impact

State impact the way an affected customer or the business would describe it:

  • Who: which users, regions, plans, tenants. Counts or percentages, not “some users”.
  • What: which actions failed or degraded (checkout returned 502, emails delayed ~40 min).
  • How much: requests failed, orders lost or delayed, SLO budget burned, revenue estimate if finance supplied one. Mark estimates as estimates.
  • Data: was any data lost, corrupted, or exposed? If exposure is possible, stop and tell the user this needs the security or privacy process before the doc circulates.

3. Contributing factors

Complex failures rarely have one root cause. List the conditions that together made the incident possible, grouped so actions map cleanly:

GroupPrompt questionExample factor
TriggerWhat change or event started it?Config push raised pool size above DB max_connections
Latent conditionWhat was already true that let the trigger hurt?No validation of pool size against DB limits
DetectionWhy did we not notice sooner?Alert on 5xx rate only fires after 10 min sustained
ResponseWhat slowed mitigation?Rollback runbook referenced a removed script
Blast radiusWhy was impact as wide as it was?All regions received the config simultaneously

For each factor, ask “why was this possible?” until you reach something a team can change (a check, a default, a process, a tool), then stop. Stopping at “human error” is a sign the analysis is incomplete: ask what made the error easy and its consequence large.

4. Action items

Every action traces to a factor. Every factor has at least one action, or an explicit note that the team accepts the risk.

FieldRule
ActionVerb-first, specific, verifiable: “Add CI check rejecting pool_size > 0.8 x max_connections”
Typeprevent / detect / mitigate / process
OwnerA named person (not a team); team in brackets is fine
DueA date. Large items get a date for the design or first milestone
TicketLink or ID; create the ticket only after the user confirms
PriorityP1 (before next similar change), P2 (this quarter), P3 (backlog, revisit)

Reject vague actions and rewrite them:

VagueSpecific
Improve monitoringAlert when DB connection usage > 85% for 2 min, routed to the DB on-call
Be more careful with configsRequire a second approver for prod config changes touching connection settings
Update the runbookReplace step 4 of the rollback runbook with deployctl rollback --to-previous; test in staging
Add more testsAdd an integration test that boots the service with max pool size against a DB capped at 100 connections

Keep the list short. Five completed actions beat fifteen that rot. Push “nice to have” ideas into a separate “considered, not doing” list with the reason.

5. Blameless language pass

Search the draft for these and rewrite each hit:

rg -n -i "should have|failed to|forgot|careless|mistake|human error|didn't notice|obviously|simply|just" postmortem.md
Instead ofWrite
“Alex failed to check the dashboard”“The dashboard was not part of the deploy checklist”
“Human error caused the outage”“The CLI accepted a production target without confirmation”
“Should have rolled back sooner”“Rollback started 34 min after detection; the runbook pointed to a removed script”

Names may appear in the timeline as roles (“on-call engineer”, “IC”) unless the team’s culture uses names; follow the existing documents. Never name a person in the summary, factors or actions-as-blame.

Template

# Postmortem: <short user-facing description> (<YYYY-MM-DD>)

**Status:** draft | in review | final   **Severity:** SEV-2
**Authors:** <names>   **Incident lead:** <role or name>   **Review meeting:** <date>

## Summary
<3-5 sentences: what users experienced, for how long, the trigger, how it was fixed,
and the single most important follow-up.>

## Impact
- Duration: 09:31-10:47 UTC (76 min); time to detect 11 min; time to mitigate 52 min
- Users affected: ~18% of checkout attempts in EU and US (41,200 failed requests)
- Data: no loss or exposure (verified by <check>)
- SLO: 63% of the monthly checkout availability budget consumed

## Timeline (UTC)
| Time | Event | Source |
|---|---|---|

## Contributing factors
### Trigger
### Latent conditions
### Detection
### Response

## What went well
## Where we got lucky
## Action items
| # | Action | Type | Owner | Due | Ticket | Factor |
|---|---|---|---|---|---|---|

## Considered, not doing
## Open questions
## Appendix: graphs, queries, links

“Where we got lucky” is mandatory: it records near-misses (the incident happened at low traffic, an engineer happened to be online) that would make the next one worse.

Gotchas

  • Writing the summary first anchors the narrative before the timeline is checked. Write it after the timeline and factors are stable.
  • Chat exports mix time zones and edited messages. Prefer system timestamps (alerts, deploy logs) when they conflict with chat, and note the conflict.
  • “Root cause: bad deploy” explains nothing. Name what about the deploy and what allowed it.
  • Do not speculate to fill gaps. Put unknowns in Open questions with the person who can answer them.
  • Customer-facing text must not include internal hostnames, employee names, vendor blame, or unreleased remediation dates. Draft it separately and have the user approve it.
  • Publishing the postmortem, posting it to a channel, or creating tickets is outward-facing: show the user the final text and get a clear yes first.

Verification

  • Every timeline row has a source; every number in Impact traces to a query or graph.
  • The four anchor times are present and the derived durations add up.
  • Each contributing factor maps to at least one action or an explicit accepted-risk note.
  • The blame search above returns no unaddressed hits.
  • A reader outside the team can answer: what broke for users, why, and what changes now. Ask the user to have one such reader skim it if the incident is SEV-1.

What the zip contains

SKILL.md plus the interface file below. Nothing runs on install.

agents/openai.yamlgenerated from this page

Gives the Codex app a display name, a one-line description and a starter prompt for this skill.

interface:
  display_name: "Postmortem Writing"
  short_description: "Outage write-ups that change something"
  default_prompt: "$postmortem-writing Turn this exported incident Slack channel into a blameless postmortem"

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.

esc
New

Introducing Codex Skills Pro

79 professional skills that take Codex through complete engagements, each with its own scripts, references and a report that verifies the result.

All-AccessOne-time payment, no subscription
$49
Get All-AccessOr browse individual skills from $2.99 →

Secure checkout by Creem