# File Issue

> Turns something said in a session into a tracked issue that a cold agent can act on, and copies the session log beside it wherever one can be had — always attempted, never a reason to withhold the issue. Decides first whether the thing needs tracking at all, searches for an existing issue before creating a second one, quotes the request in the words it was made in rather than paraphrasing it, and states an acceptance test someone else can check. Creates the portal every later step resolves back to.

- Skill: `dogkeeper886/file-issue` (Agent Skill, multi-file: 6 files)
- Install (CLI): `npx skillmds@latest add dogkeeper886/file-issue`
- Raw SKILL.md: https://api.skillmd.com/api/skills/dogkeeper886/file-issue/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: dogkeeper886 (https://skillmd.com/u/dogkeeper886)
- Updated: 2026-09-10
- Page: https://skillmd.com/skills/dogkeeper886/file-issue

---


# File an issue

Target: $ARGUMENTS — what to file, or the thing just discussed.

**The issue is a portal, not a record.** Everything after it resolves backwards through
it: a branch takes its name, a commit cites it, a PR closes it, and an agent picking up
cold reads it first. What it cannot do is carry the reasoning that produced it — an issue
body is a summary by nature, and summarising is where the intent shifts.

So the split is: **the issue states the decision and the test; the session log holds the
reasoning.** The issue links to the log rather than absorbing it.

**The point is to make the platform pay off.** Every act below is a `gh` or `glab` call a
person could make themselves. The value is not having to remember which, not having to
notice the two CLIs disagree, and not having to write a body that a stranger can act on
from a standing start. Where this skill would add a step the platform does not need, it is
wrong — process invented on top of a tracker is a cost the tracker was supposed to remove.

## 0. Which platform

**Derive it, never assume it.** `git remote get-url origin` names the host. No address
belongs in this file: one a person has to keep correct goes stale silently.

| | GitHub — `gh` | GitLab — `glab` |
|---|---|---|
| create | `gh issue create --body-file <f>` | `glab issue create -d "$(cat <f>)"` — there is no `--body-file` |
| search | `gh issue list --search "…" --state all` | `glab issue list --search "…" --in title,description --all` |
| comment | `gh issue comment` | `glab issue note` |
| label | `gh issue edit --add-label` | `glab issue update --label` |
| change request | `pr` | `mr` |
| templates live in | `.github/ISSUE_TEMPLATE/` | `.gitlab/issue_templates/`, reachable as `--template <name>` |

Both read the repository from the git remote, so neither takes a `--repo` argument from
inside the clone.

**Linking differs, and it is the one place to stop and say so.** GitHub carries dependencies
natively. GitLab's blocking relationships are a paid tier; on a free instance the reachable
verb is `--linked-issues` with `--link-type relates_to`, which records a relation but does
not gate anything. Say which you got — a relation reported as a dependency is a promise the
platform will not keep.

## 1. Should this be an issue at all

The judgment the whole workflow rests on. File too eagerly and the tracker fills with
things nobody closes; too reluctantly and the work happens with no record.

**Do not file:**

- A question the reply answers.
- A fix smaller than the issue describing it. A typo takes ten seconds; the issue takes
  two minutes and a close.
- Thinking aloud, exploring an idea, weighing an approach. A decision is not yet made.
- Something already being done in this session and about to be committed.

**Do file:**

- A second problem surfaced while working on a first. **This is the case that goes
  unrecorded most often** — the session ends and the observation dies with it.
- Anything that will be picked up by someone, or something, other than this session.
- A decision made here that later work must not silently reverse.

**Uncertain? Ask.** A user who says "we should probably…" has not decided. One question is
cheaper than an issue nobody wanted.

## 2. Search before creating

    gh   issue list --search "<key terms>" --state all --limit 20
    glab issue list --search "<key terms>" --in title,description --all --per-page 20

`glab` lists open issues by default, so `--all` is what reaches closed ones too. There is
no `--state` flag on it. The pair above asks both platforms the same question: open and
closed, capped at twenty.

A second issue for the same thing splits its history, and nothing says which one is live.
On a hit, comment on the existing issue instead and say that is what you did.

## 3. Save the session, where it can be had

**Always attempt it. Never block on it.** The log is worth real effort — it is the only
place the reasoning behind a compressed body survives — and it is never a reason to hold
back an issue. The issue has to stand on its own: a reader should never *need* the log to
act, and should almost always *have* it. Where it cannot be had, file the issue anyway and
leave Context out. An issue withheld for a missing record is worse than an issue without one.

**Where it lives.** The host writes a log per session. For Claude Code that is:

    ~/.claude/projects/<project-slug>/<session-uuid>.jsonl

with subagent logs and tool-result files in a directory of the same name beside it.
The project slug is the working directory with separators replaced. Another host will put
it somewhere else — find it rather than assuming this path, and say so if you cannot.

**Copy the log verbatim** into `.sessions/`, keeping its own filename, and commit it:

    cp ~/.claude/projects/<slug>/<uuid>.jsonl .sessions/

**Copy, do not render.** Any markdown version is a filter, however careful — it drops the
records it judged uninteresting, and that judgment is the exact thing this design removes.
A readable view can be generated from the source whenever one is wanted, precisely because
the source kept everything.

**Raw. Whole. Unedited.** No summary, no "key decisions" section, no extraction. The moment
anyone decides what mattered, the thing that mattered and was not obvious is gone. That is
the drift this whole design exists to remove, and it is undone by one helpful edit.

Two properties worth knowing rather than discovering. A live session's file **grows as you
work**, so any copy is a snapshot rather than a final record — say which. And these files
are large; a project's accumulated sessions run to megabytes, which is accepted rather than
solved. Pruning is summarising with a longer interval.

**What the log buys.** A body states the decision; the log holds the alternatives, the dead
ends, and the phrasing that produced it. It is read as background, never as specification —
the code binds on reality, the issue binds on scope, and the log only informs.

## 4. Pick the template and fill it

The body skeleton is not in this file. It ships as a template, so that a person filing
through the web interface gets the same sections an agent does:

| The thing is | Template | Ends in | The sections it exists for |
|---|---|---|---|
| something broken | [bug.md](templates/bug.md) | a diff | **Root cause**, **Proposed fix** — a bug without either is a report, not an issue |
| something to build or change | [task.md](templates/task.md) | a diff | **Plan**, **Expected outcome**, **What's next** |
| something to write or correct | [docs.md](templates/docs.md) | a diff | **Who reads it**, and two reviews — technical for true, editorial for readable |
| a change to infrastructure | [environment.md](templates/environment.md) | either | **Blast radius**, **Rollback**, **Window** |
| an act to perform | [operation.md](templates/operation.md) | evidence | **Access**, **Pre-checks**, **Verification**, **Evidence to capture** |

All five carry What · Done when · Context · Out of scope. **The list is a floor.** A kind
needing a section none of them has gets it, and the template gains it afterwards.

**"Ends in" decides how the issue closes**, not how it is written. A diff closes by merging
a change request; evidence closes by hand with the commands, their output and the
before-and-after state on the issue. `environment` goes both ways — infrastructure as code
produces a diff, a manual provision produces evidence — and the sections are identical
either way, so the fork is stated in the template and resolved later rather than splitting
it in two.

**Rollback and verification are why the last two exist.** A commit reverts; a migrated
database does not, and a rotated certificate leaves no diff to inspect. Those templates ask
for a known-good state, a rollback that has actually been run somewhere rather than assumed,
and verification taken from outside the change — because checking with the tool that made
it proves the tool ran, not that the world changed.

**The project's copy wins.** Look in `.github/ISSUE_TEMPLATE/` or
`.gitlab/issue_templates/` first and fill what is there. The templates beside this skill
are the starting point, not the authority — a project that has edited its own has made a
decision, and overwriting it with the shipped version reverses that decision silently.

Where the project has none, place these there rather than filling them from here, so the
CLI and the web form agree from then on. On GitLab the flag reads that directory directly:
`glab issue create --template bug`.

Where the project's copy is missing a section this skill requires — root cause, proposed
fix, the session link — add the section to the body and say you did. Do not edit their
template as a side effect of filing one issue.

### The four rules the template cannot enforce

**Quote, do not paraphrase.** "The report reads as a wall when it lands in Slack" is what
was said. "Improve report formatting" is what an agent does with it, and the two are not
the same instruction. Paraphrase is the first place intent shifts, and it happens before
anyone can notice.

**"Done when" is the whole issue.** An acceptance line a third party can check is what
makes this pickable cold. *"No open Sev-1 defects and 95% of planned cases executed"* is
checkable; *"quality is acceptable"* is not. If you cannot write one, the thing is not
ready to be an issue, and the honest move is to say so rather than file it anyway.

**"Out of scope" is load-bearing.** It records a decision, so a later gap reads as a known
tradeoff rather than an oversight, and it is what stops the next agent widening the work.

**Link, never inline.** Pasting the session into the body is the summarising failure by
another route: it makes the issue unreadable and the log redundant at once.

## 5. Create it, and say where it went

    gh   issue create --title "<states the problem, not the fix>" --body-file <f>
    glab issue create --title "<states the problem, not the fix>" -d "$(cat <f>)"

Then set whatever label marks *ready to be picked up* in this project. Where the project
declares none, say so rather than inventing one.

Blocked by something? Record it as a real edge where the platform has them, and report
what you actually got — see step 0.

## Steps

Copy this checklist and tick each item as you finish it:

    Task Progress:
    - [ ] Platform derived from the git remote, not assumed
    - [ ] Decided it needs tracking — and said why, if it was close
    - [ ] Searched for an existing issue
    - [ ] Session saved and linked, or its absence accepted and Context omitted
    - [ ] Template picked — bug · task · docs · environment · operation
    - [ ] Issue created, labelled; linking reported as what the platform gave
    - [ ] Verdict reported

## Report

Two lines and a question:

    FILED — #42, blocked by #38, log at .sessions/<uuid>.jsonl
    Next: nothing. It is pickable when #38 closes.
    Want the body?

When it was decided *not* to file, that is still a verdict and still needs saying:

    NOT FILED — a typo fix, already done in this session.
    Next: nothing.

And when it should be filed but was not — the body is written and creation was deferred,
usually because someone asked for it that way:

    DRAFTED — body written to <path>, not on the platform.
    Next: create it, or say what to change first.

**Say which of the three it was.** A draft reported as filed is the worst of them: the work
looks tracked and nothing is.

The body, the search results and the session path are prepared and held until asked.

