issue-flow 0.2.2__tar.gz → 0.2.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. issue_flow-0.2.3/PKG-INFO +216 -0
  2. issue_flow-0.2.3/README.md +192 -0
  3. {issue_flow-0.2.2 → issue_flow-0.2.3}/pyproject.toml +1 -1
  4. {issue_flow-0.2.2 → issue_flow-0.2.3}/src/issue_flow/cli.py +20 -2
  5. {issue_flow-0.2.2 → issue_flow-0.2.3}/src/issue_flow/config.py +14 -3
  6. issue_flow-0.2.3/src/issue_flow/dependencies.py +162 -0
  7. {issue_flow-0.2.2 → issue_flow-0.2.3}/src/issue_flow/init.py +43 -3
  8. issue_flow-0.2.3/src/issue_flow/templates/commands/iflow.md.j2 +77 -0
  9. issue_flow-0.2.3/src/issue_flow/templates/commands/issue-cleanup.md.j2 +60 -0
  10. issue_flow-0.2.3/src/issue_flow/templates/commands/issue-close.md.j2 +64 -0
  11. {issue_flow-0.2.2 → issue_flow-0.2.3}/src/issue_flow/templates/commands/issue-init.md.j2 +6 -0
  12. issue_flow-0.2.3/src/issue_flow/templates/commands/issue-pause.md.j2 +57 -0
  13. issue_flow-0.2.3/src/issue_flow/templates/commands/issue-plan.md.j2 +82 -0
  14. issue_flow-0.2.3/src/issue_flow/templates/commands/issue-start.md.j2 +50 -0
  15. issue_flow-0.2.3/src/issue_flow/templates/commands/issue-yolo.md.j2 +75 -0
  16. issue_flow-0.2.3/src/issue_flow/templates/docs/cursor-issue-workflow.md.j2 +239 -0
  17. issue_flow-0.2.3/src/issue_flow/templates/rules/issueflow-rules.mdc.j2 +125 -0
  18. issue_flow-0.2.3/src/issue_flow/templates/skills/issueflow_history_update/SKILL.md.j2 +84 -0
  19. issue_flow-0.2.3/src/issue_flow/templates/skills/issueflow_iflow/SKILL.md.j2 +55 -0
  20. issue_flow-0.2.3/src/issue_flow/templates/skills/issueflow_issue_cleanup/SKILL.md.j2 +44 -0
  21. issue_flow-0.2.3/src/issue_flow/templates/skills/issueflow_issue_close/SKILL.md.j2 +62 -0
  22. {issue_flow-0.2.2 → issue_flow-0.2.3}/src/issue_flow/templates/skills/issueflow_issue_init/SKILL.md.j2 +5 -2
  23. issue_flow-0.2.3/src/issue_flow/templates/skills/issueflow_issue_pause/SKILL.md.j2 +44 -0
  24. issue_flow-0.2.3/src/issue_flow/templates/skills/issueflow_issue_plan/SKILL.md.j2 +49 -0
  25. issue_flow-0.2.3/src/issue_flow/templates/skills/issueflow_issue_start/SKILL.md.j2 +50 -0
  26. issue_flow-0.2.3/src/issue_flow/templates/skills/issueflow_issue_yolo/SKILL.md.j2 +49 -0
  27. {issue_flow-0.2.2 → issue_flow-0.2.3}/src/issue_flow/templating.py +38 -9
  28. issue_flow-0.2.2/PKG-INFO +0 -157
  29. issue_flow-0.2.2/README.md +0 -133
  30. issue_flow-0.2.2/src/issue_flow/templates/commands/issue-close.md.j2 +0 -50
  31. issue_flow-0.2.2/src/issue_flow/templates/commands/issue-start.md.j2 +0 -16
  32. issue_flow-0.2.2/src/issue_flow/templates/docs/cursor-issue-workflow.md.j2 +0 -120
  33. issue_flow-0.2.2/src/issue_flow/templates/rules/issueflow-rules.mdc.j2 +0 -86
  34. issue_flow-0.2.2/src/issue_flow/templates/skills/issueflow_issue_close/SKILL.md.j2 +0 -49
  35. issue_flow-0.2.2/src/issue_flow/templates/skills/issueflow_issue_start/SKILL.md.j2 +0 -39
  36. {issue_flow-0.2.2 → issue_flow-0.2.3}/LICENSE +0 -0
  37. {issue_flow-0.2.2 → issue_flow-0.2.3}/src/issue_flow/__init__.py +0 -0
  38. {issue_flow-0.2.2 → issue_flow-0.2.3}/src/issue_flow/py.typed +0 -0
  39. {issue_flow-0.2.2 → issue_flow-0.2.3}/src/issue_flow/templates/__init__.py +0 -0
  40. {issue_flow-0.2.2 → issue_flow-0.2.3}/src/issue_flow/templates/commands/__init__.py +0 -0
  41. {issue_flow-0.2.2 → issue_flow-0.2.3}/src/issue_flow/templates/docs/__init__.py +0 -0
  42. {issue_flow-0.2.2 → issue_flow-0.2.3}/src/issue_flow/templates/rules/__init__.py +0 -0
  43. {issue_flow-0.2.2 → issue_flow-0.2.3}/src/issue_flow/templates/skills/issueflow_version_bump/SKILL.md.j2 +0 -0
@@ -0,0 +1,216 @@
1
+ Metadata-Version: 2.4
2
+ Name: issue-flow
3
+ Version: 0.2.3
4
+ Summary: Agents should behave. Let them follow the issue flow.
5
+ Keywords: cursor,ai,agents,issue-tracking,workflow
6
+ Author: jepegit
7
+ Author-email: jepegit <jepe@ife.no>
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Topic :: Software Development :: Build Tools
14
+ Classifier: Programming Language :: Python :: 3.13
15
+ Requires-Dist: jinja2>=3.1.6
16
+ Requires-Dist: python-dotenv>=1.2.2
17
+ Requires-Dist: rich>=14.3.3
18
+ Requires-Dist: typer>=0.24.1
19
+ Requires-Python: >=3.13
20
+ Project-URL: Homepage, https://github.com/jepegit/issue-flow
21
+ Project-URL: Repository, https://github.com/jepegit/issue-flow
22
+ Project-URL: Issues, https://github.com/jepegit/issue-flow/issues
23
+ Description-Content-Type: text/markdown
24
+
25
+ # issue-flow
26
+
27
+ Agents should behave. Let them follow the issue flow.
28
+
29
+ **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.
30
+
31
+ ## What it does
32
+
33
+ Running `issue-flow init` in your project root creates:
34
+
35
+ ```text
36
+ your-project/
37
+ .issueflows/
38
+ 00-tools/ # Helper scripts for agents
39
+ 01-current-issues/ # Active issue markdown files
40
+ 02-partly-solved-issues/ # Parked / in-progress issues
41
+ 03-solved-issues/ # Completed issues archive
42
+ .cursor/
43
+ commands/
44
+ iflow.md # /iflow — smart dispatcher (quick start)
45
+ issue-init.md # /issue-init — fetch a GitHub issue locally
46
+ issue-plan.md # /issue-plan — write issue<N>_plan.md and confirm
47
+ issue-start.md # /issue-start — implement the plan
48
+ issue-pause.md # /issue-pause — park work in 02-partly-solved-issues/
49
+ issue-close.md # /issue-close — test, commit, push, PR
50
+ issue-cleanup.md # /issue-cleanup — post-merge branch hygiene
51
+ issue-yolo.md # /issue-yolo — all-in-one for small, low-risk issues
52
+ skills/ # Optional Agent Skills (explicit / @ invoke)
53
+ issueflow-iflow/SKILL.md
54
+ issueflow-issue-init/SKILL.md
55
+ issueflow-issue-plan/SKILL.md
56
+ issueflow-issue-start/SKILL.md
57
+ issueflow-issue-pause/SKILL.md
58
+ issueflow-issue-close/SKILL.md
59
+ issueflow-issue-cleanup/SKILL.md
60
+ issueflow-issue-yolo/SKILL.md
61
+ issueflow-version-bump/SKILL.md
62
+ issueflow-history-update/SKILL.md
63
+ rules/
64
+ issueflow-rules.mdc # Always-on Cursor rule for the workflow
65
+ docs/
66
+ cursor-issue-workflow.md # Human-readable overview of the workflow
67
+ ```
68
+
69
+ The Cursor slash commands give agents a repeatable flow. The linear path is:
70
+
71
+ 1. `/issue-init 42` — pulls GitHub issue #42 into `.issueflows/01-current-issues/` and archives older issues.
72
+ 2. `/issue-plan` — drafts `issue<N>_plan.md` (Goal / Constraints / Approach / Files to touch / Test strategy / Open questions) and stops for your confirmation.
73
+ 3. `/issue-start` — reads the confirmed plan and implements it. If no plan file exists, it offers to run `/issue-plan` first, proceed without a plan, or abort.
74
+ 4. `/issue-close` — runs tests, optionally bumps version with `uv version --bump`, appends a `HISTORY.md` entry (or promotes `[Unreleased]` to a new release section on a bump), updates status files, commits, pushes, and opens a PR.
75
+ 5. `/issue-cleanup` — after the PR merges, switches to the default branch, fast-forwards, prunes, and deletes the merged local branch.
76
+
77
+ Plus a few off-path commands:
78
+
79
+ - `/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 `/iflow` works from a fresh branch too.
80
+ - `/issue-pause` — park the current issue in `02-partly-solved-issues/` with a **Remaining work** note; optional WIP commit + switch back to the default branch.
81
+ - `/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).
82
+
83
+ 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](https://cursor.com/docs/context/skills)).
84
+
85
+ ## Prerequisites
86
+
87
+ issue-flow itself is a small Python CLI, but the **scaffolded slash commands
88
+ it writes into your project shell out to a few external tools**. If they are
89
+ missing, the slash commands will fail at runtime — so `issue-flow init` now
90
+ checks for them up front and prints install hints before it does anything.
91
+
92
+ Required:
93
+
94
+ - **[Git](https://git-scm.com/downloads)** — used by every slash command for
95
+ branch, fetch, status, commit, and push operations. Almost certainly already
96
+ installed if you're here, but the check covers it for completeness.
97
+ - **[GitHub CLI (`gh`)](https://cli.github.com/)** — used by `/issue-init` to
98
+ fetch issues, by `/issue-close` to open PRs, and by `/issue-cleanup` to check
99
+ PR merge status. After installing, run `gh auth login` once to authenticate.
100
+
101
+ Recommended:
102
+
103
+ - **[uv](https://docs.astral.sh/uv/)** — how issue-flow itself is meant to be
104
+ installed, and how this repo manages its own Python environment.
105
+
106
+ Quick install pointers for `gh`:
107
+
108
+ | Platform | Command |
109
+ |---|---|
110
+ | macOS (Homebrew) | `brew install gh` |
111
+ | Windows (winget) | `winget install --id GitHub.cli -e` |
112
+ | Linux (Debian/Ubuntu) | `sudo apt install gh` (or see [cli.github.com](https://cli.github.com/) for the official repo) |
113
+
114
+ If a dependency is missing, `issue-flow init` prints the installation hints
115
+ and asks whether to continue anyway. You can bypass the prompt in automation
116
+ with `issue-flow init --skip-dep-check` (the same flag is available on
117
+ `issue-flow update`), and the prompt is also auto-skipped when stdin is not
118
+ a TTY (e.g. CI pipelines).
119
+
120
+ ## Installation
121
+
122
+ Requires Python 3.13+ and [uv](https://docs.astral.sh/uv/).
123
+
124
+ ```bash
125
+ uv tool install issue-flow
126
+ ```
127
+
128
+ Or add it as a dev dependency to your project:
129
+
130
+ ```bash
131
+ uv add --dev issue-flow
132
+ ```
133
+
134
+ ## Quick start
135
+
136
+ ```bash
137
+ cd your-project
138
+ issue-flow init
139
+ ```
140
+
141
+ 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).
142
+
143
+ ## Usage
144
+
145
+ ```
146
+ issue-flow init [PROJECT_DIR] [--force] [--skip-dep-check]
147
+ issue-flow update [PROJECT_DIR] [--skip-dep-check]
148
+ ```
149
+
150
+ ### `issue-flow init`
151
+
152
+ | Argument / Option | Description |
153
+ |---|---|
154
+ | `PROJECT_DIR` | Project root directory. Defaults to `.` (current directory). |
155
+ | `--force`, `-f` | Overwrite generated Cursor commands, rules, and workflow doc instead of skipping them. |
156
+ | `--skip-dep-check` | Skip the external-CLI dependency check (`git`, `gh`) and the confirmation prompt that follows if anything is missing. Useful in automation. |
157
+
158
+ 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`.
159
+
160
+ ### `issue-flow update`
161
+
162
+ | Argument / Option | Description |
163
+ |---|---|
164
+ | `PROJECT_DIR` | Project root directory. Defaults to `.` (current directory). |
165
+ | `--skip-dep-check` | Skip the external-CLI dependency check (`git`, `gh`) and the confirmation prompt that follows if anything is missing. |
166
+
167
+ 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.
168
+
169
+ ### When to use which
170
+
171
+ | Goal | Command |
172
+ |---|---|
173
+ | First-time setup, or add missing files only | `issue-flow init` |
174
+ | Pull newer templates after `uv tool upgrade issue-flow` (or similar) | `issue-flow update` |
175
+ | Replace generated scaffolds without upgrading logic | `issue-flow init --force` |
176
+
177
+ ## Configuration
178
+
179
+ issue-flow reads a `.env` file from the project root (via python-dotenv). The following environment variables are supported:
180
+
181
+ | Variable | Default | Description |
182
+ |---|---|---|
183
+ | `ISSUEFLOW_DIR` | `.issueflows` | Name of the issue-tracking directory. |
184
+ | `ISSUEFLOW_AGENT_DIR` | `.cursor` | Name of the agent/IDE config directory (currently `.cursor`). |
185
+ | `ISSUEFLOW_DOCS_DIR` | `docs` | Where to write the workflow documentation file. |
186
+ | `ISSUEFLOW_HISTORY_FILE` | `HISTORY.md` | Changelog file that `/issue-close` updates (set to e.g. `CHANGELOG.md` for different conventions). |
187
+
188
+ ## Development
189
+
190
+ ```bash
191
+ git clone https://github.com/jepegit/issue-flow.git
192
+ cd issue-flow
193
+ uv sync
194
+
195
+ # Run tests
196
+ uv run pytest
197
+
198
+ # Lint
199
+ uv run ruff check src/ tests/
200
+ ```
201
+
202
+ ## Changelog
203
+
204
+ See [HISTORY.md](HISTORY.md) for release notes.
205
+
206
+ ## Future plans
207
+
208
+ - **Multi-tool support** — generate config for other AI coding tools (Claude Code, Windsurf, etc.) in addition to Cursor.
209
+ - **`issue-flow status`** — show a dashboard of current, partly-solved, and solved issues.
210
+ - **Custom templates** — let users supply their own Jinja2 templates to tailor slash commands and rules to their team's conventions.
211
+ - **Git hook integration** — optionally move issue files on commit based on status markers.
212
+ - **GitHub Actions workflow** — ship a reusable action that syncs issue state between `.issueflows/` and GitHub issue labels/milestones.
213
+
214
+ ## License
215
+
216
+ This project is released under the MIT License. See the full text in the repository: [LICENSE](https://github.com/jepegit/issue-flow/blob/main/LICENSE).
@@ -0,0 +1,192 @@
1
+ # issue-flow
2
+
3
+ Agents should behave. Let them follow the issue flow.
4
+
5
+ **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.
6
+
7
+ ## What it does
8
+
9
+ Running `issue-flow init` in your project root creates:
10
+
11
+ ```text
12
+ your-project/
13
+ .issueflows/
14
+ 00-tools/ # Helper scripts for agents
15
+ 01-current-issues/ # Active issue markdown files
16
+ 02-partly-solved-issues/ # Parked / in-progress issues
17
+ 03-solved-issues/ # Completed issues archive
18
+ .cursor/
19
+ commands/
20
+ iflow.md # /iflow — smart dispatcher (quick start)
21
+ issue-init.md # /issue-init — fetch a GitHub issue locally
22
+ issue-plan.md # /issue-plan — write issue<N>_plan.md and confirm
23
+ issue-start.md # /issue-start — implement the plan
24
+ issue-pause.md # /issue-pause — park work in 02-partly-solved-issues/
25
+ issue-close.md # /issue-close — test, commit, push, PR
26
+ issue-cleanup.md # /issue-cleanup — post-merge branch hygiene
27
+ issue-yolo.md # /issue-yolo — all-in-one for small, low-risk issues
28
+ skills/ # Optional Agent Skills (explicit / @ invoke)
29
+ issueflow-iflow/SKILL.md
30
+ issueflow-issue-init/SKILL.md
31
+ issueflow-issue-plan/SKILL.md
32
+ issueflow-issue-start/SKILL.md
33
+ issueflow-issue-pause/SKILL.md
34
+ issueflow-issue-close/SKILL.md
35
+ issueflow-issue-cleanup/SKILL.md
36
+ issueflow-issue-yolo/SKILL.md
37
+ issueflow-version-bump/SKILL.md
38
+ issueflow-history-update/SKILL.md
39
+ rules/
40
+ issueflow-rules.mdc # Always-on Cursor rule for the workflow
41
+ docs/
42
+ cursor-issue-workflow.md # Human-readable overview of the workflow
43
+ ```
44
+
45
+ The Cursor slash commands give agents a repeatable flow. The linear path is:
46
+
47
+ 1. `/issue-init 42` — pulls GitHub issue #42 into `.issueflows/01-current-issues/` and archives older issues.
48
+ 2. `/issue-plan` — drafts `issue<N>_plan.md` (Goal / Constraints / Approach / Files to touch / Test strategy / Open questions) and stops for your confirmation.
49
+ 3. `/issue-start` — reads the confirmed plan and implements it. If no plan file exists, it offers to run `/issue-plan` first, proceed without a plan, or abort.
50
+ 4. `/issue-close` — runs tests, optionally bumps version with `uv version --bump`, appends a `HISTORY.md` entry (or promotes `[Unreleased]` to a new release section on a bump), updates status files, commits, pushes, and opens a PR.
51
+ 5. `/issue-cleanup` — after the PR merges, switches to the default branch, fast-forwards, prunes, and deletes the merged local branch.
52
+
53
+ Plus a few off-path commands:
54
+
55
+ - `/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 `/iflow` works from a fresh branch too.
56
+ - `/issue-pause` — park the current issue in `02-partly-solved-issues/` with a **Remaining work** note; optional WIP commit + switch back to the default branch.
57
+ - `/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).
58
+
59
+ 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](https://cursor.com/docs/context/skills)).
60
+
61
+ ## Prerequisites
62
+
63
+ issue-flow itself is a small Python CLI, but the **scaffolded slash commands
64
+ it writes into your project shell out to a few external tools**. If they are
65
+ missing, the slash commands will fail at runtime — so `issue-flow init` now
66
+ checks for them up front and prints install hints before it does anything.
67
+
68
+ Required:
69
+
70
+ - **[Git](https://git-scm.com/downloads)** — used by every slash command for
71
+ branch, fetch, status, commit, and push operations. Almost certainly already
72
+ installed if you're here, but the check covers it for completeness.
73
+ - **[GitHub CLI (`gh`)](https://cli.github.com/)** — used by `/issue-init` to
74
+ fetch issues, by `/issue-close` to open PRs, and by `/issue-cleanup` to check
75
+ PR merge status. After installing, run `gh auth login` once to authenticate.
76
+
77
+ Recommended:
78
+
79
+ - **[uv](https://docs.astral.sh/uv/)** — how issue-flow itself is meant to be
80
+ installed, and how this repo manages its own Python environment.
81
+
82
+ Quick install pointers for `gh`:
83
+
84
+ | Platform | Command |
85
+ |---|---|
86
+ | macOS (Homebrew) | `brew install gh` |
87
+ | Windows (winget) | `winget install --id GitHub.cli -e` |
88
+ | Linux (Debian/Ubuntu) | `sudo apt install gh` (or see [cli.github.com](https://cli.github.com/) for the official repo) |
89
+
90
+ If a dependency is missing, `issue-flow init` prints the installation hints
91
+ and asks whether to continue anyway. You can bypass the prompt in automation
92
+ with `issue-flow init --skip-dep-check` (the same flag is available on
93
+ `issue-flow update`), and the prompt is also auto-skipped when stdin is not
94
+ a TTY (e.g. CI pipelines).
95
+
96
+ ## Installation
97
+
98
+ Requires Python 3.13+ and [uv](https://docs.astral.sh/uv/).
99
+
100
+ ```bash
101
+ uv tool install issue-flow
102
+ ```
103
+
104
+ Or add it as a dev dependency to your project:
105
+
106
+ ```bash
107
+ uv add --dev issue-flow
108
+ ```
109
+
110
+ ## Quick start
111
+
112
+ ```bash
113
+ cd your-project
114
+ issue-flow init
115
+ ```
116
+
117
+ 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).
118
+
119
+ ## Usage
120
+
121
+ ```
122
+ issue-flow init [PROJECT_DIR] [--force] [--skip-dep-check]
123
+ issue-flow update [PROJECT_DIR] [--skip-dep-check]
124
+ ```
125
+
126
+ ### `issue-flow init`
127
+
128
+ | Argument / Option | Description |
129
+ |---|---|
130
+ | `PROJECT_DIR` | Project root directory. Defaults to `.` (current directory). |
131
+ | `--force`, `-f` | Overwrite generated Cursor commands, rules, and workflow doc instead of skipping them. |
132
+ | `--skip-dep-check` | Skip the external-CLI dependency check (`git`, `gh`) and the confirmation prompt that follows if anything is missing. Useful in automation. |
133
+
134
+ 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`.
135
+
136
+ ### `issue-flow update`
137
+
138
+ | Argument / Option | Description |
139
+ |---|---|
140
+ | `PROJECT_DIR` | Project root directory. Defaults to `.` (current directory). |
141
+ | `--skip-dep-check` | Skip the external-CLI dependency check (`git`, `gh`) and the confirmation prompt that follows if anything is missing. |
142
+
143
+ 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.
144
+
145
+ ### When to use which
146
+
147
+ | Goal | Command |
148
+ |---|---|
149
+ | First-time setup, or add missing files only | `issue-flow init` |
150
+ | Pull newer templates after `uv tool upgrade issue-flow` (or similar) | `issue-flow update` |
151
+ | Replace generated scaffolds without upgrading logic | `issue-flow init --force` |
152
+
153
+ ## Configuration
154
+
155
+ issue-flow reads a `.env` file from the project root (via python-dotenv). The following environment variables are supported:
156
+
157
+ | Variable | Default | Description |
158
+ |---|---|---|
159
+ | `ISSUEFLOW_DIR` | `.issueflows` | Name of the issue-tracking directory. |
160
+ | `ISSUEFLOW_AGENT_DIR` | `.cursor` | Name of the agent/IDE config directory (currently `.cursor`). |
161
+ | `ISSUEFLOW_DOCS_DIR` | `docs` | Where to write the workflow documentation file. |
162
+ | `ISSUEFLOW_HISTORY_FILE` | `HISTORY.md` | Changelog file that `/issue-close` updates (set to e.g. `CHANGELOG.md` for different conventions). |
163
+
164
+ ## Development
165
+
166
+ ```bash
167
+ git clone https://github.com/jepegit/issue-flow.git
168
+ cd issue-flow
169
+ uv sync
170
+
171
+ # Run tests
172
+ uv run pytest
173
+
174
+ # Lint
175
+ uv run ruff check src/ tests/
176
+ ```
177
+
178
+ ## Changelog
179
+
180
+ See [HISTORY.md](HISTORY.md) for release notes.
181
+
182
+ ## Future plans
183
+
184
+ - **Multi-tool support** — generate config for other AI coding tools (Claude Code, Windsurf, etc.) in addition to Cursor.
185
+ - **`issue-flow status`** — show a dashboard of current, partly-solved, and solved issues.
186
+ - **Custom templates** — let users supply their own Jinja2 templates to tailor slash commands and rules to their team's conventions.
187
+ - **Git hook integration** — optionally move issue files on commit based on status markers.
188
+ - **GitHub Actions workflow** — ship a reusable action that syncs issue state between `.issueflows/` and GitHub issue labels/milestones.
189
+
190
+ ## License
191
+
192
+ This project is released under the MIT License. See the full text in the repository: [LICENSE](https://github.com/jepegit/issue-flow/blob/main/LICENSE).
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "issue-flow"
3
- version = "0.2.2"
3
+ version = "0.2.3"
4
4
  description = "Agents should behave. Let them follow the issue flow."
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -32,11 +32,21 @@ def init(
32
32
  "-f",
33
33
  help="Overwrite existing files without asking.",
34
34
  ),
35
+ skip_dep_check: bool = typer.Option(
36
+ False,
37
+ "--skip-dep-check",
38
+ help=(
39
+ "Skip the external-CLI dependency check (git, gh) and the "
40
+ "confirmation prompt that follows if anything is missing."
41
+ ),
42
+ ),
35
43
  ) -> None:
36
44
  """Scaffold issue-flow directories and Cursor config files in a project."""
37
45
  from issue_flow.init import run_init
38
46
 
39
- run_init(project_root=project_dir, force=force)
47
+ run_init(
48
+ project_root=project_dir, force=force, skip_dep_check=skip_dep_check
49
+ )
40
50
 
41
51
 
42
52
  @app.command()
@@ -48,11 +58,19 @@ def update(
48
58
  file_okay=False,
49
59
  resolve_path=True,
50
60
  ),
61
+ skip_dep_check: bool = typer.Option(
62
+ False,
63
+ "--skip-dep-check",
64
+ help=(
65
+ "Skip the external-CLI dependency check (git, gh) and the "
66
+ "confirmation prompt that follows if anything is missing."
67
+ ),
68
+ ),
51
69
  ) -> None:
52
70
  """Refresh packaged Cursor commands, rules, and workflow doc from this package."""
53
71
  from issue_flow.init import run_update
54
72
 
55
- run_update(project_root=project_dir)
73
+ run_update(project_root=project_dir, skip_dep_check=skip_dep_check)
56
74
 
57
75
 
58
76
  def main() -> None:
@@ -25,18 +25,26 @@ class Settings:
25
25
  issueflows_dir: str = field(
26
26
  default_factory=lambda: os.getenv("ISSUEFLOW_DIR", ".issueflows")
27
27
  )
28
- cursor_dir: str = field(
29
- default_factory=lambda: os.getenv("ISSUEFLOW_CURSOR_DIR", ".cursor")
28
+ agent_dir: str = field(
29
+ default_factory=lambda: os.getenv("ISSUEFLOW_AGENT_DIR", ".cursor")
30
30
  )
31
31
  docs_dir: str = field(
32
32
  default_factory=lambda: os.getenv("ISSUEFLOW_DOCS_DIR", "docs")
33
33
  )
34
+ history_file: str = field(
35
+ default_factory=lambda: os.getenv("ISSUEFLOW_HISTORY_FILE", "HISTORY.md")
36
+ )
37
+
38
+ # Give a deprecation warning if the user is using the old ISSUEFLOW_CURSOR_DIR environment variable
39
+ if os.getenv("ISSUEFLOW_CURSOR_DIR"):
40
+ print("WARNING: The ISSUEFLOW_CURSOR_DIR environment variable is deprecated (replaced by ISSUEFLOW_AGENT_DIR).")
34
41
 
35
42
  # Subdirectory names inside .issueflows/
36
43
  tools_folder: str = "00-tools"
37
44
  current_issues_folder: str = "01-current-issues"
38
45
  partly_solved_folder: str = "02-partly-solved-issues"
39
46
  solved_folder: str = "03-solved-issues"
47
+ designs_folder: str = "04-designs-and-guides"
40
48
 
41
49
  @property
42
50
  def issueflows_subdirs(self) -> list[str]:
@@ -45,6 +53,7 @@ class Settings:
45
53
  self.current_issues_folder,
46
54
  self.partly_solved_folder,
47
55
  self.solved_folder,
56
+ self.designs_folder,
48
57
  ]
49
58
 
50
59
  def template_context(self, project_root: Path) -> dict[str, str]:
@@ -52,12 +61,14 @@ class Settings:
52
61
  project_name = _detect_project_name(project_root)
53
62
  return {
54
63
  "issueflows_dir": self.issueflows_dir,
55
- "cursor_dir": self.cursor_dir,
64
+ "agent_dir": self.agent_dir,
56
65
  "docs_dir": self.docs_dir,
66
+ "history_file": self.history_file,
57
67
  "tools_folder": self.tools_folder,
58
68
  "current_issues_folder": self.current_issues_folder,
59
69
  "partly_solved_folder": self.partly_solved_folder,
60
70
  "solved_folder": self.solved_folder,
71
+ "designs_folder": self.designs_folder,
61
72
  "project_name": project_name,
62
73
  }
63
74
 
@@ -0,0 +1,162 @@
1
+ """External CLI dependency detection for issue-flow.
2
+
3
+ The scaffolded workflow shells out to ``git`` and ``gh`` (GitHub CLI) via
4
+ slash commands. We detect missing tools at ``issue-flow init`` /
5
+ ``issue-flow update`` time so users get a clear install hint rather than a
6
+ confusing failure later from inside a Cursor command.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import shutil
12
+ import sys
13
+ from dataclasses import dataclass
14
+
15
+ from rich.console import Console
16
+
17
+
18
+ @dataclass(frozen=True)
19
+ class Dependency:
20
+ """A single external CLI tool issue-flow's workflow depends on."""
21
+
22
+ name: str
23
+ command: str
24
+ purpose: str
25
+ docs_url: str
26
+ # Platform hint → short install snippet. Keys are free-form labels
27
+ # shown verbatim (e.g. "macOS (Homebrew)", "Windows (winget)", "Linux
28
+ # (Debian/Ubuntu)"). Values are one-line commands.
29
+ install_hints: tuple[tuple[str, str], ...]
30
+
31
+
32
+ # The scaffolded slash commands (see
33
+ # ``src/issue_flow/templates/commands/*.md.j2``) invoke these tools. ``uv``
34
+ # is intentionally *not* listed here: it is an install-time prerequisite
35
+ # for issue-flow itself, not something the scaffold calls at runtime, so
36
+ # it belongs in the README only.
37
+ REQUIRED_DEPENDENCIES: tuple[Dependency, ...] = (
38
+ Dependency(
39
+ name="Git",
40
+ command="git",
41
+ purpose=(
42
+ "Used by every slash command for branch, fetch, status, "
43
+ "commit, and push operations."
44
+ ),
45
+ docs_url="https://git-scm.com/downloads",
46
+ install_hints=(
47
+ ("macOS (Homebrew)", "brew install git"),
48
+ ("Windows (winget)", "winget install --id Git.Git -e"),
49
+ ("Linux (Debian/Ubuntu)", "sudo apt install git"),
50
+ ),
51
+ ),
52
+ Dependency(
53
+ name="GitHub CLI",
54
+ command="gh",
55
+ purpose=(
56
+ "Used by /issue-init to fetch issues, /issue-close to open "
57
+ "PRs, and /issue-cleanup to check PR merge status. Remember "
58
+ "to run `gh auth login` once after installing."
59
+ ),
60
+ docs_url="https://cli.github.com/",
61
+ install_hints=(
62
+ ("macOS (Homebrew)", "brew install gh"),
63
+ ("Windows (winget)", "winget install --id GitHub.cli -e"),
64
+ (
65
+ "Linux (Debian/Ubuntu)",
66
+ "sudo apt install gh # or see https://cli.github.com/ for the official repo",
67
+ ),
68
+ ),
69
+ ),
70
+ )
71
+
72
+
73
+ def check_dependencies(
74
+ dependencies: tuple[Dependency, ...] = REQUIRED_DEPENDENCIES,
75
+ ) -> list[Dependency]:
76
+ """Return the subset of ``dependencies`` whose ``command`` is not on ``PATH``.
77
+
78
+ Uses :func:`shutil.which` only — no subprocess invocations — so it is
79
+ safe to call on any platform without risk of hanging or prompting.
80
+ """
81
+ return [dep for dep in dependencies if shutil.which(dep.command) is None]
82
+
83
+
84
+ def format_missing_report(
85
+ missing: list[Dependency],
86
+ console: Console,
87
+ ) -> None:
88
+ """Print a human-readable report listing missing dependencies.
89
+
90
+ The output is intentionally compact and uses only ``rich`` markup so
91
+ it blends with the rest of the ``init`` output.
92
+ """
93
+ if not missing:
94
+ return
95
+
96
+ count = len(missing)
97
+ noun = "dependency" if count == 1 else "dependencies"
98
+ console.print(
99
+ f"[bold yellow]Missing {count} external {noun}:[/bold yellow]"
100
+ )
101
+ for dep in missing:
102
+ console.print(
103
+ f"\n [bold]{dep.name}[/bold] "
104
+ f"([cyan]{dep.command}[/cyan] not found on PATH)"
105
+ )
106
+ console.print(f" [dim]{dep.purpose}[/dim]")
107
+ console.print(f" Docs: [blue]{dep.docs_url}[/blue]")
108
+ console.print(" Install:")
109
+ for label, snippet in dep.install_hints:
110
+ console.print(f" - {label}: [green]{snippet}[/green]")
111
+ console.print()
112
+
113
+
114
+ def prompt_or_skip(
115
+ missing: list[Dependency],
116
+ console: Console,
117
+ *,
118
+ skip: bool,
119
+ stdin_is_tty: bool | None = None,
120
+ ) -> bool:
121
+ """Decide whether to proceed despite missing deps.
122
+
123
+ Returns ``True`` to continue, ``False`` if the user declined.
124
+
125
+ - If ``missing`` is empty, returns ``True``.
126
+ - If ``skip`` is ``True``, prints a one-line note and returns ``True``
127
+ without prompting.
128
+ - If stdin is not a TTY (e.g. CI, piped input), prints a one-line
129
+ note and returns ``True`` without prompting so automation doesn't
130
+ hang.
131
+ - Otherwise asks the user with :func:`typer.confirm`.
132
+ """
133
+ if not missing:
134
+ return True
135
+
136
+ format_missing_report(missing, console)
137
+
138
+ if skip:
139
+ console.print(
140
+ "[dim]Dependency check bypassed via --skip-dep-check; "
141
+ "continuing anyway.[/dim]\n"
142
+ )
143
+ return True
144
+
145
+ if stdin_is_tty is None:
146
+ stdin_is_tty = sys.stdin.isatty()
147
+
148
+ if not stdin_is_tty:
149
+ console.print(
150
+ "[dim]Non-interactive session (stdin is not a TTY); "
151
+ "continuing without prompting. "
152
+ "Install the tools above before running the slash commands.[/dim]\n"
153
+ )
154
+ return True
155
+
156
+ # Imported lazily to keep this module importable in environments
157
+ # that only need check_dependencies (e.g. tests or custom scripts).
158
+ import typer
159
+
160
+ return typer.confirm(
161
+ "Continue with issue-flow setup anyway?", default=False
162
+ )