Agents should behave. Let them follow the issue flow.
Project description
issue-flow
Agents should behave. Let them follow the issue flow.
issue-flow scaffolds a lightweight issue-tracking workflow into your project so that Cursor AI agents can pick up GitHub issues, plan work, and land PRs in a consistent way.
What it does
Running issue-flow init in your project root creates:
your-project/
.issueflows/
00-tools/ # Helper scripts for agents
01-current-issues/ # Active issue markdown files
02-partly-solved-issues/ # Parked / in-progress issues
03-solved-issues/ # Completed issues archive
.cursor/
commands/
iflow.md # /iflow — smart dispatcher (quick start)
issue-init.md # /issue-init — fetch a GitHub issue locally
issue-plan.md # /issue-plan — write issue<N>_plan.md and confirm
issue-start.md # /issue-start — implement the plan
issue-pause.md # /issue-pause — park work in 02-partly-solved-issues/
issue-close.md # /issue-close — test, commit, push, PR
issue-cleanup.md # /issue-cleanup — post-merge branch hygiene
issue-yolo.md # /issue-yolo — all-in-one for small, low-risk issues
build.md # /build — rebuild the graphify knowledge graph (optional)
skills/ # Optional Agent Skills (explicit / @ invoke)
issueflow-iflow/SKILL.md
issueflow-issue-init/SKILL.md
issueflow-issue-plan/SKILL.md
issueflow-issue-start/SKILL.md
issueflow-issue-pause/SKILL.md
issueflow-issue-close/SKILL.md
issueflow-issue-cleanup/SKILL.md
issueflow-issue-yolo/SKILL.md
issueflow-version-bump/SKILL.md
issueflow-history-update/SKILL.md
issueflow-build/SKILL.md
rules/
issueflow-rules.mdc # Always-on Cursor rule for the workflow
docs/
cursor-issue-workflow.md # Human-readable overview of the workflow
The Cursor slash commands give agents a repeatable flow. The linear path is:
/issue-init 42— pulls GitHub issue #42 into.issueflows/01-current-issues/and archives older issues./issue-plan— draftsissue<N>_plan.md(Goal / Constraints / Approach / Files to touch / Test strategy / Open questions) and stops for your confirmation./issue-start— reads the confirmed plan and implements it. If no plan file exists, it offers to run/issue-planfirst, proceed without a plan, or abort./issue-close— runs tests, optionally bumps version withuv version --bump, appends aHISTORY.mdentry (or promotes[Unreleased]to a new release section on a bump), updates status files, commits, pushes, and opens a PR./issue-cleanup— after the PR merges, switches to the default branch, fast-forwards, prunes, and deletes the merged local branch.
Plus a few off-path commands:
/iflow— quick start: inspects the current issue's state and dispatches to the right linear step automatically. A branch-derived number (42-fix-login→N=42) is authoritative, so/iflowworks from a fresh branch too./issue-pause— park the current issue in02-partly-solved-issues/with a Remaining work note; optional WIP commit + switch back to the default branch./issue-yolo— all-in-one chain (init → plan → start → close) for small, low-risk issues, with up-front safeguards (refuses on the default branch, refuses with dirty unrelated changes, requires passing tests, single consolidated confirm).
The matching Agent Skills (under .cursor/skills/) carry the same workflows for on-demand use with /issueflow-iflow, /issueflow-issue-init, /issueflow-issue-plan, /issueflow-issue-start, /issueflow-issue-pause, /issueflow-issue-close, /issueflow-issue-cleanup, /issueflow-issue-yolo, @issueflow-version-bump when you need only the bump steps, or @issueflow-history-update when you need only the changelog update (see Cursor Agent Skills).
Prerequisites
issue-flow itself is a small Python CLI, but the scaffolded slash commands
it writes into your project shell out to a few external tools. If they are
missing, the slash commands will fail at runtime — so issue-flow init now
checks for them up front and prints install hints before it does anything.
Required:
- Git — used by every slash command for branch, fetch, status, commit, and push operations. Almost certainly already installed if you're here, but the check covers it for completeness.
- GitHub CLI (
gh) — used by/issue-initto fetch issues, by/issue-closeto open PRs, and by/issue-cleanupto check PR merge status. After installing, rungh auth loginonce to authenticate.
Recommended:
- uv — how issue-flow itself is meant to be installed, and how this repo manages its own Python environment.
Quick install pointers for gh:
| Platform | Command |
|---|---|
| macOS (Homebrew) | brew install gh |
| Windows (winget) | winget install --id GitHub.cli -e |
| Linux (Debian/Ubuntu) | sudo apt install gh (or see cli.github.com for the official repo) |
If a dependency is missing, issue-flow init prints the installation hints
and asks whether to continue anyway. You can bypass the prompt in automation
with issue-flow init --skip-dep-check (the same flag is available on
issue-flow update), and the prompt is also auto-skipped when stdin is not
a TTY (e.g. CI pipelines).
Optional: graphify integration
issue-flow has a lightweight integration with graphify
(PyPI: graphifyy, CLI: graphify) — a tool that turns the project into a
queryable knowledge graph that AI assistants can read instead of grepping
through files. The integration is opt-in by installing graphifyy as its
own tool (the same way you installed issue-flow): there is no flag, no
.env switch, no extras to remember. Detection is purely PATH-based.
What issue-flow does when graphify is on PATH:
issue-flow initandissue-flow updaterungraphify cursor installso the graphify Cursor skill is registered alongside the issue-flow scaffold. If graphify is not installed, both commands just print install hints and continue — they never block.- A new slash command
/build(and matching/issueflow-buildskill) wrapsissue-flow build, which forwards every argument to thegraphifyCLI verbatim (--update,--no-viz,--mode deep,--watch, …). - The scaffolded rules and
/issue-startmentiongraphify-out/GRAPH_REPORT.mdas a recommended pre-read when the file exists./buildis off-path —/iflownever auto-dispatches to it.
To enable, install graphify as its own standalone tool:
uv tool install graphifyy # recommended
# or
pipx install graphifyy
# or
pip install graphifyy
Why not an
issue-flow[graphify]extra (oruv tool install issue-flow --with graphifyy)?uv tool installonly puts the host package's entry-point scripts on PATH. An extra (or--with graphifyy) pulls graphifyy into issue-flow's venv but leaves thegraphifyCLI invisible to the shell, so/buildandgraphify cursor installwould still fail. Installing graphify as its own tool puts a realgraphifyshim on PATH and matches how we treatgit/gh.
Just installed graphifyy and
issue-flow initsays it's still missing? uv prints~/.local/bin is not on your PATHafter the firstuv tool install. Runuv tool update-shell(refreshes shell rc files), then restart your shell and Cursor so the new PATH takes effect. issue-flow's missing-CLI hint also detects this case and tells you the exact directory to add.
After installing, run issue-flow update once so the graphify Cursor skill
gets registered.
Installation
Requires Python 3.13+ and uv.
uv tool install issue-flow
Or add it as a dev dependency to your project:
uv add --dev issue-flow
Quick start
cd your-project
issue-flow init
That's it. Open the project in Cursor and start with /iflow (or step through /issue-init, /issue-plan, /issue-start, /issue-close, /issue-cleanup explicitly).
Usage
issue-flow init [PROJECT_DIR] [--force] [--skip-dep-check]
issue-flow update [PROJECT_DIR] [--skip-dep-check]
issue-flow build [PROJECT_DIR] [-- ...graphify args]
issue-flow init
| Argument / Option | Description |
|---|---|
PROJECT_DIR |
Project root directory. Defaults to . (current directory). |
--force, -f |
Overwrite generated Cursor commands, rules, and workflow doc instead of skipping them. |
--skip-dep-check |
Skip the external-CLI dependency check (git, gh) and the confirmation prompt that follows if anything is missing. Useful in automation. |
Running init again without --force is safe: generated scaffold files that already exist are skipped, and issue markdown under .issueflows/ is never touched by init or update. When the CLI detects an existing scaffold, it reminds you about update and --force.
issue-flow update
| Argument / Option | Description |
|---|---|
PROJECT_DIR |
Project root directory. Defaults to . (current directory). |
--skip-dep-check |
Skip the external-CLI dependency check (git, gh) and the confirmation prompt that follows if anything is missing. |
Use update after upgrading the issue-flow package to refresh the packaged slash commands, Cursor rule, and docs/cursor-issue-workflow.md from the version you have installed. This overwrites those generated files (unlike a plain second init). It still does not modify arbitrary files under .issueflows/ (for example your issue*_original.md / issue*_status.md files), and it creates any new .issueflows/ subdirectories required by the current package.
issue-flow build
| Argument / Option | Description |
|---|---|
PROJECT_DIR |
Project root directory to scan with graphify. Defaults to .. |
...graphify args |
Any extra arguments are forwarded verbatim to the graphify CLI (--update, --no-viz, --mode deep, --watch, …). |
build requires graphifyy to be installed (uv tool install graphifyy). When the graphify CLI is missing, the command prints install hints and exits with code 2. Outputs land in graphify-out/ (graph.html, GRAPH_REPORT.md, graph.json).
When to use which
| Goal | Command |
|---|---|
| First-time setup, or add missing files only | issue-flow init |
Pull newer templates after uv tool upgrade issue-flow (or similar) |
issue-flow update |
| Replace generated scaffolds without upgrading logic | issue-flow init --force |
| Rebuild the graphify knowledge graph | issue-flow build |
Configuration
issue-flow reads a .env file from the project root (via python-dotenv). The following environment variables are supported:
| Variable | Default | Description |
|---|---|---|
ISSUEFLOW_DIR |
.issueflows |
Name of the issue-tracking directory. |
ISSUEFLOW_AGENT_DIR |
.cursor |
Name of the agent/IDE config directory (currently .cursor). |
ISSUEFLOW_DOCS_DIR |
docs |
Where to write the workflow documentation file. |
ISSUEFLOW_HISTORY_FILE |
HISTORY.md |
Changelog file that /issue-close updates (set to e.g. CHANGELOG.md for different conventions). |
Development
git clone https://github.com/jepegit/issue-flow.git
cd issue-flow
uv sync
# Run tests
uv run pytest
# Lint
uv run ruff check src/ tests/
Changelog
See HISTORY.md for release notes.
Future plans
- Multi-tool support — generate config for other AI coding tools (Claude Code, Windsurf, etc.) in addition to Cursor.
issue-flow status— show a dashboard of current, partly-solved, and solved issues.- Custom templates — let users supply their own Jinja2 templates to tailor slash commands and rules to their team's conventions.
- Git hook integration — optionally move issue files on commit based on status markers.
- GitHub Actions workflow — ship a reusable action that syncs issue state between
.issueflows/and GitHub issue labels/milestones.
License
This project is released under the MIT License. See the full text in the repository: LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file issue_flow-0.3.0.tar.gz.
File metadata
- Download URL: issue_flow-0.3.0.tar.gz
- Upload date:
- Size: 54.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
823f738028ba25aa4a22ea0c1d28a930bd2b8cf5551a326c6875aec96d2f33e6
|
|
| MD5 |
95e6f69282ea7bf304ea0d9f0bee526a
|
|
| BLAKE2b-256 |
4c2f1653f4f1bc89440fabb5558200c5dcc2df1814ee52640e7995604fff4e4c
|
Provenance
The following attestation bundles were made for issue_flow-0.3.0.tar.gz:
Publisher:
publish.yml on jepegit/issue-flow
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
issue_flow-0.3.0.tar.gz -
Subject digest:
823f738028ba25aa4a22ea0c1d28a930bd2b8cf5551a326c6875aec96d2f33e6 - Sigstore transparency entry: 1540015839
- Sigstore integration time:
-
Permalink:
jepegit/issue-flow@7a2b8327de5781b76e47373af0d3d8e8935fa777 -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/jepegit
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@7a2b8327de5781b76e47373af0d3d8e8935fa777 -
Trigger Event:
release
-
Statement type:
File details
Details for the file issue_flow-0.3.0-py3-none-any.whl.
File metadata
- Download URL: issue_flow-0.3.0-py3-none-any.whl
- Upload date:
- Size: 80.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
43281ac0ce62bf473e4552da6679cc8d706e761bac03fbde3cd745f6731624aa
|
|
| MD5 |
51fe13feb818f9c062ea4149e2dca7df
|
|
| BLAKE2b-256 |
6339f360ba04e61e24baa82a9a5259e5492f02a4e6793f3da96d2420b7ec1d41
|
Provenance
The following attestation bundles were made for issue_flow-0.3.0-py3-none-any.whl:
Publisher:
publish.yml on jepegit/issue-flow
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
issue_flow-0.3.0-py3-none-any.whl -
Subject digest:
43281ac0ce62bf473e4552da6679cc8d706e761bac03fbde3cd745f6731624aa - Sigstore transparency entry: 1540015906
- Sigstore integration time:
-
Permalink:
jepegit/issue-flow@7a2b8327de5781b76e47373af0d3d8e8935fa777 -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/jepegit
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@7a2b8327de5781b76e47373af0d3d8e8935fa777 -
Trigger Event:
release
-
Statement type: