closing-issues/SKILL.md
Close a GitHub issue with a synthesis comment as a flowing graph — validate the synthesis, post the closing comment, close, then run a pluggable callback (e.g. memory store) detached. Use when closing an issue should also capture the LEARNING (not just the diff log) and when the post-close work shouldn't block the close ack.
npx skillsauth add oaustegard/claude-skills closing-issuesInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
A flowing graph that turns "close GitHub issue + capture what I learned"
into a structural DAG. The synthesis text is validated upfront, the close
happens against the GitHub API, and an optional post-close callback runs
detached so the close ack is unblocked.
from closing_issues import close_issue
result = close_issue(
repo="owner/repo",
number=42,
synthesis=(
"Pattern X works because of Y. Constraint: don't apply to Z. "
"Future note: revisit when feature Q lands."
),
)
print(result["issue_url"]) # https://github.com/.../issues/42
print(result["comment_url"]) # ...#issuecomment-...
Closing an issue produces two artifacts:
Good closing comments lead with why, not what. Failure modes, constraints discovered, alternatives rejected. The synthesis is the seed of an institutional memory.
prepare_synthesis ──▶ close_github_issue [terminal]
│
└──▶ post_close_callback [detached, when=callback]
validate=must_have_synthesis_text runs against the raw input
string. Empty or whitespace-only → FAILED with no GitHub API call.
This is structural: callers can't accidentally close-with-no-text.
close_github_issue posts the synthesis as a comment, then
PATCHes the issue to state=closed, state_reason=completed. Returns
the issue URL and comment URL.
post_close_callback (optional) runs detached. Caller plugs in
any extra work — store synthesis in a memory system, ping a tracker,
emit a webhook. Failure here lands in result["detached_failures"]
and does NOT bubble up as a close failure. Skipped via when= if
the callback isn't provided.
def store_in_my_memory(synthesis: str, issue_url: str, repo: str, number: int):
# Whatever your memory layer is — Turso, sqlite, a JSON file, etc.
db.execute("INSERT INTO learnings (issue, synthesis) VALUES (?, ?)",
(issue_url, synthesis))
return {"stored": True}
result = close_issue(
repo="owner/repo",
number=42,
synthesis="...",
post_close_callback=store_in_my_memory,
)
if result["callback_result"] is None and result["detached_failures"]:
# The callback failed but the issue is still closed.
print("Memory store failed:", result["detached_failures"])
The callback receives keyword arguments: synthesis, issue_url,
repo, number. Anything it returns goes into
result["callback_result"].
{
"issue_url": "https://github.com/owner/repo/issues/N",
"comment_url": "https://github.com/.../issues/N#issuecomment-...",
"comment_id": 12345,
"callback_result": <whatever the callback returned, or None>,
"detached_failures": [], # populated if callback raised
}
Raises RuntimeError only if the GitHub close itself fails. Callback
failures are detached.
Requires GH_TOKEN (or GITHUB_TOKEN) in the environment. Classic PAT
or fine-grained PAT with repo scope (specifically issues:write).
gh issue close N directly. This skill
is for the synthesis use case.flowing — the DAG runner this skill is built onopening-prs — the symmetric "open and merge" flowtesting
Disciplined, validation-gated revision of an EXISTING skill so each edit is a measured improvement rather than a guess. Use when editing, revising, or tuning a skill that already exists and there is evidence it underperforms (observed failures, drift, complaints) — invoke by name, or have versioning-skills / creating-skill defer to it before applying edits. Not for authoring a brand-new skill from scratch (use creating-skill) or one-off prose.
development
Skill-aware orchestration with context routing. Decomposes complex tasks into skill-typed subtasks, extracts targeted context subsets, executes subagents in parallel, and synthesizes results. Self-answers trivial lookups inline. No SDK dependency — uses raw HTTP via httpx. Use when tasks require multiple analytical perspectives, when context is large and subtasks only need portions, or when orchestrating-agents spawns too many redundant subagents.
tools
Orchestrates parallel API instances, delegated sub-tasks, and multi-agent workflows with streaming and tool-enabled delegation patterns. Use for parallel analysis, multi-perspective reviews, or complex task decomposition.
development
Invokes Google Gemini models for structured outputs, image generation, multi-modal tasks, and Google-specific features. Use when users request Gemini, image generation, structured JSON output, Google API integration, or cost-effective parallel processing.