Meeting Notes to Issues
MIT↓ 0 downloadsA single Claude Code agent reads raw meeting notes and turns every actionable item into a clean, ready-to-file issue draft — one markdown file per action with title, context, acceptance criteria, and a suggested owner and label — plus an INDEX.md summary table.
Topology
Disclosures
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.
Shell expansion
No shell-expansion blocks in prompt files.
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 Meeting Notes to Issues workflow.+# Node 22, git, and 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.+# node:22-bookworm already ships a "node" user at UID/GID 1000, so we RENAME it+# (the stock Sandcastle template pattern) — groupadd/useradd would collide with+# the existing IDs on a default build.ARG AGENT_UID=1000ARG AGENT_GID=1000-RUN groupadd --gid ${AGENT_GID} agent \- && useradd --uid ${AGENT_UID} --gid ${AGENT_GID} --create-home --shell /bin/bash agent+RUN groupmod -o -g ${AGENT_GID} node \+ && usermod -o -u ${AGENT_UID} -g ${AGENT_GID} -d /home/agent -m -l agent node-USER agent-WORKDIR /workspace+USER ${AGENT_UID}:${AGENT_GID}+WORKDIR /home/agent++# Sandcastle bind-mounts the worktree and sets the working directory at+# container start; the container just needs to stay alive until then.+ENTRYPOINT ["sleep", "infinity"]
Show full Dockerfile (highlighted)
# Sandbox image for the Meeting Notes to Issues workflow.
# Node 22, git, and 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.
# node:22-bookworm already ships a "node" user at UID/GID 1000, so we RENAME it
# (the stock Sandcastle template pattern) — groupadd/useradd would collide with
# the existing IDs on a default build.
ARG AGENT_UID=1000
ARG AGENT_GID=1000
RUN groupmod -o -g ${AGENT_GID} node \
&& usermod -o -u ${AGENT_UID} -g ${AGENT_GID} -d /home/agent -m -l agent node
USER ${AGENT_UID}:${AGENT_GID}
WORKDIR /home/agent
# Sandcastle bind-mounts the worktree and sets the working directory at
# container start; the container just needs to stay alive until then.
ENTRYPOINT ["sleep", "infinity"]
# Auth for the Claude Code organizer agent.
# Run `claude setup-token` on your host to generate a token, then paste it here
# in your local .sandcastle/.env (never commit the real .env).
CLAUDE_CODE_OAUTH_TOKEN=
import { run, claudeCode } from "@ai-hero/sandcastle";
import { docker } from "@ai-hero/sandcastle/sandboxes/docker";
// A single-pass note organizer. One Sonnet agent reads notes/meeting.md and
// emits one issue-draft markdown file per actionable item plus an index table.
// maxIterations is 1 because this is a one-shot extraction, not a loop. Default
// `head` branch strategy on docker means commits land on the current branch.
const result = await run({
name: "meeting-notes-to-issues",
agent: claudeCode("claude-sonnet-4-6"),
sandbox: docker(),
promptFile: ".sandcastle/prompt.md",
maxIterations: 1,
});
console.log(`Issue drafts written in ${result.commits.length} commit(s) on ${result.branch}.`);
Meeting notes to issue drafts
You are an operations organizer. Turn a messy set of meeting notes into clean, file-ready issue drafts that an engineer or PM could grab and act on without asking follow-up questions.
Input
Read notes/meeting.md in the repository root — raw, unstructured meeting notes
(decisions, tangents, action items, open questions). If the file is missing,
say so and stop.
Your task
Extract every genuinely actionable item — a task, a bug, a decision that needs follow-up, or a concrete open question with an owner. Ignore pure chatter and already-closed decisions.
For each action, create one markdown file at issues/<nn>-<kebab-title>.md
(zero-padded number, e.g. issues/01-fix-login-timeout.md) with:
- Title — a crisp, imperative one-liner (as an
#heading). - Context — 2–4 sentences of background pulled from the notes so the issue stands alone. Quote the notes where the exact wording matters.
- Acceptance criteria — a checklist of what "done" means, specific and testable.
- Suggested owner — a name if the notes name one, otherwise a role.
- Suggested labels — 1–3 short labels (e.g.
bug,backend,discovery). - Priority — your best read (P0/P1/P2) with a one-line reason.
Then write issues/INDEX.md containing a summary markdown table with columns:
number, title, owner, priority, labels — one row per issue, linking each row to
its file.
Do not invent owners, dates, or facts that are not supported by the notes; where
something is unknown, write TBD. Commit everything with a message like
ops: draft issues from meeting notes.
README
Meeting Notes to Issues
The fastest path from a wall of meeting notes to a tidy stack of file-ready issues. One Claude Code agent, one Docker sandbox, no network, no hooks.
What it does
The agent reads notes/meeting.md — your raw, unstructured notes — and pulls
out every genuinely actionable item: tasks, bugs, follow-up decisions, and
concrete open questions. For each one it writes a self-contained draft to
issues/<nn>-<title>.md with an imperative title, enough context to stand
alone, testable acceptance criteria, a suggested owner and labels, and a
priority call with a one-line reason. It then rolls everything up into an
issues/INDEX.md summary table so you can triage the whole batch at a glance.
Chatter and already-closed decisions are skipped. Unknowns are marked TBD
rather than invented, so nothing in the drafts is fabricated.
How it works
main.ts calls run() once with maxIterations: 1 against a Sonnet agent — a
single extraction pass, not a loop. Commits land directly on your current branch
through the Docker bind mount, so there is no worktree or merge step, and no
network access or shell expansion is used.
Requirements
Drop your notes at notes/meeting.md, 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. Review the drafts in issues/, tweak as needed,
and paste them straight into your tracker.