Runcastle

Incident Postmortem Writer

MIT0 downloads

by runcastle

v1.0.0

A single Claude Code agent turns an incident timeline and the last week of commit history into a blameless postmortem — summary, impact, timeline, root causes, contributing factors, what went well, and action items with owners and due dates — written to postmortem/POSTMORTEM.md.

Topology

Disclosures

Disclosures — declared side-effect surface

Everything below runs on your machine or inside the sandbox when you use this workflow. Mismatches between these declarations and the actual code block publishing.

Host hooks

Commands executed on YOUR host machine by Sandcastle lifecycle hooks.

None declared.

Sandbox hooks

Commands executed inside the sandbox container.

None declared.

Network access

None. The agent operates only on the local repository inside the sandbox; the prompt runs `git log` locally to seed recent commit context.

Shell expansion

Prompt files contain !`command` blocks — the agent CLI executes these commands at prompt-load time. They are highlighted amber in the prompt files below.

Files

Diff vs the stock Sandcastle 0.12.0 template Dockerfile — green lines were added by the author, red lines were removed from stock.

+# Sandbox image for the Incident Postmortem Writer workflow.
+# Node 22 + git (the prompt seeds `git log` context) + the Claude Code CLI,
+# running as a non-root `agent` user.
FROM node:22-bookworm
# System dependencies.
RUN apt-get update && apt-get install -y --no-install-recommends \
git \
curl \
jq \
ca-certificates \
&& rm -rf /var/lib/apt/lists/*
# Claude Code CLI (the agent runtime).
RUN npm install -g @anthropic-ai/claude-code
# Non-root agent user. `sandcastle docker build-image` aligns AGENT_UID/GID to
# the host user via --build-arg to avoid permission errors on bind mounts.
ARG AGENT_UID=1000
ARG AGENT_GID=1000
RUN groupadd --gid ${AGENT_GID} agent \
&& useradd --uid ${AGENT_UID} --gid ${AGENT_GID} --create-home --shell /bin/bash agent
USER agent
WORKDIR /workspace
Show full Dockerfile (highlighted)
# Sandbox image for the Incident Postmortem Writer workflow.
# Node 22 + git (the prompt seeds `git log` context) + the Claude Code CLI,
# running as a non-root `agent` user.
FROM node:22-bookworm

# System dependencies.
RUN apt-get update && apt-get install -y --no-install-recommends \
      git \
      curl \
      jq \
      ca-certificates \
 && rm -rf /var/lib/apt/lists/*

# Claude Code CLI (the agent runtime).
RUN npm install -g @anthropic-ai/claude-code

# Non-root agent user. `sandcastle docker build-image` aligns AGENT_UID/GID to
# the host user via --build-arg to avoid permission errors on bind mounts.
ARG AGENT_UID=1000
ARG AGENT_GID=1000
RUN groupadd --gid ${AGENT_GID} agent \
 && useradd --uid ${AGENT_UID} --gid ${AGENT_GID} --create-home --shell /bin/bash agent

USER agent
WORKDIR /workspace

README

Incident Postmortem Writer

Turn a raw incident timeline into a polished, blameless postmortem your team can review and act on. One Claude Code agent, one Docker sandbox, no hooks.

What it does

The agent reads an incident.md timeline from your repository root and seeds itself with the last seven days of commit history, then writes a complete blameless postmortem to postmortem/POSTMORTEM.md. The document follows the standard structure teams expect: summary, quantified impact, a chronological timeline table, root cause(s), contributing factors, what went well, and a table of action items — each with an owner and a due date, biased toward systemic guardrails over "be more careful".

Because it cross-references your recent commits, it can point root-cause analysis at the specific changes that likely contributed, instead of hand-waving. The tone stays factual and neutral, and it never invents timestamps, metrics, or names that the inputs do not support.

How it works

main.ts calls run() once with maxIterations: 1 against an Opus agent — a one-shot document, not a loop. The prompt uses a shell-expansion block (!`git log --since="7 days ago" --oneline`) to inline recent commit context at run time, which is why usesShellExpansion is declared true. All work is local: git log reads your repository and there is no network access. Commits land directly on your current branch through the Docker bind mount.

Requirements

Add an incident.md (timeline, symptoms, detection, remediation) to your repo root, set CLAUDE_CODE_OAUTH_TOKEN in .sandcastle/.env (run claude setup-token on your host), then build the image once with npx @ai-hero/sandcastle docker build-image and run it with npx tsx .sandcastle/main.ts. Read the result at postmortem/POSTMORTEM.md.