codeforerunner 0.3.2__tar.gz → 0.4.0__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 (56) hide show
  1. codeforerunner-0.4.0/PKG-INFO +258 -0
  2. codeforerunner-0.4.0/README.md +231 -0
  3. {codeforerunner-0.3.2 → codeforerunner-0.4.0}/pyproject.toml +1 -1
  4. {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/cli.py +15 -3
  5. {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/doctor.py +12 -2
  6. {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/installer.py +91 -2
  7. {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/providers/__init__.py +2 -1
  8. {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/providers/anthropic.py +1 -1
  9. {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/providers/ollama.py +10 -0
  10. codeforerunner-0.4.0/src/codeforerunner.egg-info/PKG-INFO +258 -0
  11. {codeforerunner-0.3.2 → codeforerunner-0.4.0}/tests/test_cli.py +130 -0
  12. {codeforerunner-0.3.2 → codeforerunner-0.4.0}/tests/test_doctor.py +39 -0
  13. {codeforerunner-0.3.2 → codeforerunner-0.4.0}/tests/test_providers.py +52 -3
  14. codeforerunner-0.3.2/PKG-INFO +0 -133
  15. codeforerunner-0.3.2/README.md +0 -106
  16. codeforerunner-0.3.2/src/codeforerunner.egg-info/PKG-INFO +0 -133
  17. {codeforerunner-0.3.2 → codeforerunner-0.4.0}/LICENSE.md +0 -0
  18. {codeforerunner-0.3.2 → codeforerunner-0.4.0}/setup.cfg +0 -0
  19. {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/__init__.py +0 -0
  20. {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/bundle.py +0 -0
  21. {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/check.py +0 -0
  22. {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/config.py +0 -0
  23. {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/mcp_server.py +0 -0
  24. {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/prompts/partials/context-format.md +0 -0
  25. {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/prompts/partials/output-rules.md +0 -0
  26. {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/prompts/partials/stack-hints.md +0 -0
  27. {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/prompts/system/base.md +0 -0
  28. {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/prompts/tasks/api-docs.md +0 -0
  29. {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/prompts/tasks/audit.md +0 -0
  30. {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/prompts/tasks/changelog.md +0 -0
  31. {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/prompts/tasks/check.md +0 -0
  32. {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/prompts/tasks/diagrams.md +0 -0
  33. {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/prompts/tasks/flows.md +0 -0
  34. {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/prompts/tasks/init-agent-onboarding.md +0 -0
  35. {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/prompts/tasks/readme.md +0 -0
  36. {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/prompts/tasks/review.md +0 -0
  37. {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/prompts/tasks/scan.md +0 -0
  38. {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/prompts/tasks/stack-docs.md +0 -0
  39. {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/prompts/tasks/version-audit.md +0 -0
  40. {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/providers/base.py +0 -0
  41. {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/providers/google.py +0 -0
  42. {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/providers/openai.py +0 -0
  43. {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner.egg-info/SOURCES.txt +0 -0
  44. {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner.egg-info/dependency_links.txt +0 -0
  45. {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner.egg-info/entry_points.txt +0 -0
  46. {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner.egg-info/requires.txt +0 -0
  47. {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner.egg-info/top_level.txt +0 -0
  48. {codeforerunner-0.3.2 → codeforerunner-0.4.0}/tests/test_check.py +0 -0
  49. {codeforerunner-0.3.2 → codeforerunner-0.4.0}/tests/test_check_config_integration.py +0 -0
  50. {codeforerunner-0.3.2 → codeforerunner-0.4.0}/tests/test_config.py +0 -0
  51. {codeforerunner-0.3.2 → codeforerunner-0.4.0}/tests/test_examples.py +0 -0
  52. {codeforerunner-0.3.2 → codeforerunner-0.4.0}/tests/test_hooks_manifest.py +0 -0
  53. {codeforerunner-0.3.2 → codeforerunner-0.4.0}/tests/test_installer.py +0 -0
  54. {codeforerunner-0.3.2 → codeforerunner-0.4.0}/tests/test_mcp_server.py +0 -0
  55. {codeforerunner-0.3.2 → codeforerunner-0.4.0}/tests/test_validate_codex_marketplace.py +0 -0
  56. {codeforerunner-0.3.2 → codeforerunner-0.4.0}/tests/test_workflows_yaml.py +0 -0
@@ -0,0 +1,258 @@
1
+ Metadata-Version: 2.4
2
+ Name: codeforerunner
3
+ Version: 0.4.0
4
+ Summary: Model-agnostic repository documentation tooling (prompt-first; thin CLI).
5
+ Author: Derek Palmer
6
+ License-Expression: LicenseRef-Codeforerunner-SAL-0.1
7
+ Project-URL: Repository, https://github.com/derek-palmer/codeforerunner
8
+ Project-URL: Issues, https://github.com/derek-palmer/codeforerunner/issues
9
+ Keywords: repository-documentation,developer-tools,agent-tooling,code-generation,prompt-engineering,mcp,llm,documentation
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Environment :: Console
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Topic :: Documentation
19
+ Classifier: Topic :: Software Development :: Documentation
20
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
21
+ Classifier: Topic :: Utilities
22
+ Requires-Python: >=3.11
23
+ Description-Content-Type: text/markdown
24
+ License-File: LICENSE.md
25
+ Requires-Dist: PyYAML>=6.0
26
+ Dynamic: license-file
27
+
28
+ ![codeForerunner — your codebase gets a Forerunner; your docs finally see the light](images/readme_banner.png)
29
+
30
+ # codeForerunner
31
+
32
+ Model-agnostic repository documentation tooling. Ships a prompt pack for codebase analysis and doc generation, a thin Python CLI, an MCP server, drift-detection rules that keep docs honest — and native slash-command skills for Claude Code, Codex, Gemini CLI, and other agent CLIs.
33
+
34
+ ## Two modes
35
+
36
+ ### Mode A — Agent skill (recommended, no API key required)
37
+
38
+ Install forerunner's prompt pack as skills into your agent CLI. Each documentation task becomes a slash command (`/forerunner-readme`, `/forerunner-check`, etc.) available inside Claude Code, Codex, Gemini CLI, and other agents. Authentication is handled by your existing agent subscription — no separate API key needed.
39
+
40
+ ```bash
41
+ # From a cloned repo
42
+ ./install.sh
43
+
44
+ # One-liner (auto-detects Claude Code, Codex, Gemini CLI)
45
+ curl -fsSL https://raw.githubusercontent.com/derek-palmer/codeforerunner/main/install.sh | bash
46
+
47
+ # Windows
48
+ irm https://raw.githubusercontent.com/derek-palmer/codeforerunner/main/install.ps1 | iex
49
+
50
+ # Via forerunner CLI (after pip install)
51
+ forerunner install --all claude
52
+ forerunner install --all codex
53
+ ```
54
+
55
+ Then in your agent:
56
+
57
+ ```
58
+ /forerunner-scan ← scan the repo first
59
+ /forerunner-readme ← generate README
60
+ /forerunner-check ← detect doc drift
61
+ ```
62
+
63
+ ### Mode B — Direct API (needs API key or Ollama)
64
+
65
+ Install the Python CLI and call your provider directly. Works without any agent CLI installed.
66
+
67
+ ```bash
68
+ pipx install codeforerunner # recommended
69
+ pip install codeforerunner # alternative
70
+ ```
71
+
72
+ Configure a provider (or start Ollama for keyless local generation):
73
+
74
+ ```bash
75
+ export ANTHROPIC_API_KEY=sk-...
76
+ forerunner generate readme --stream
77
+ ```
78
+
79
+ If no API key and no `--provider` flag, forerunner auto-detects Ollama at `localhost:11434` and falls back to local mode.
80
+
81
+ ## Slash commands
82
+
83
+ | Command | Task | Purpose |
84
+ |---------|------|---------|
85
+ | `/forerunner-scan` | `scan` | Collect repo evidence (run first) |
86
+ | `/forerunner-readme` | `readme` | Generate or refresh README.md |
87
+ | `/forerunner-api-docs` | `api-docs` | Generate API reference docs |
88
+ | `/forerunner-diagrams` | `diagrams` | Generate Mermaid architecture diagrams |
89
+ | `/forerunner-flows` | `flows` | Document system flows |
90
+ | `/forerunner-stack-docs` | `stack-docs` | Stack-specific developer docs |
91
+ | `/forerunner-version-audit` | `version-audit` | Audit pinned versions vs EOL |
92
+ | `/forerunner-check` | `check` | Check docs for staleness |
93
+ | `/forerunner-review` | `review` | Doc-impact summary for PR review |
94
+ | `/forerunner-audit` | `audit` | Security and dependency audit |
95
+ | `/forerunner-changelog` | `changelog` | Generate changelog from git log |
96
+ | `/forerunner-init` | `init-agent-onboarding` | Bootstrap or refresh AGENTS.md |
97
+
98
+ Slash command availability depends on the agent CLI. Claude Code, Codex, and Gemini CLI support all 12 commands after install.
99
+
100
+ ## Skill install options
101
+
102
+ | Flag | Effect |
103
+ |------|--------|
104
+ | `./install.sh` | Auto-detect all agents, install all skills |
105
+ | `./install.sh --only claude` | Claude Code only |
106
+ | `./install.sh --only codex` | Codex only |
107
+ | `./install.sh --only gemini` | Gemini CLI only |
108
+ | `./install.sh --dry-run` | Preview, write nothing |
109
+ | `./install.sh --list` | Show detected agents + skill list |
110
+ | `./install.sh --uninstall` | Remove all installed skills |
111
+
112
+ ## CLI
113
+
114
+ ```bash
115
+ pip install codeforerunner
116
+ ```
117
+
118
+ | Command | Purpose |
119
+ |---------|---------|
120
+ | `forerunner init` | Resolve agent-onboarding bundle to stdout. |
121
+ | `forerunner scan` | Resolve scan bundle to stdout. |
122
+ | `forerunner doc <task>` | Resolve `base + partials + task` bundle to stdout. |
123
+ | `forerunner check` | Run drift-detection rules; no-op without `forerunner.config.yaml`. |
124
+ | `forerunner generate <task>` | Call configured provider directly. Add `--stream` for token-by-token output. Falls back to Ollama automatically when no API key is configured. |
125
+ | `forerunner doctor` | Health report: skill parity, config, provider key, local-mode status. Add `--fix` to write a starter config. |
126
+ | `forerunner mcp-server` | Serve prompt bundles as MCP tools over stdio (JSON-RPC 2.0). |
127
+ | `forerunner install <agent>` | Install canonical skill into agent-specific directory. Add `--all` for all per-task skills. |
128
+
129
+ ## Prompt pack
130
+
131
+ Prompts are bundled inside the package at `src/codeforerunner/prompts/`.
132
+
133
+ ```text
134
+ prompts/
135
+ ├── system/base.md
136
+ ├── partials/
137
+ │ ├── context-format.md
138
+ │ ├── output-rules.md
139
+ │ └── stack-hints.md
140
+ └── tasks/
141
+ ├── scan.md api-docs.md audit.md
142
+ ├── readme.md diagrams.md changelog.md
143
+ ├── check.md flows.md version-audit.md
144
+ ├── review.md stack-docs.md
145
+ └── init-agent-onboarding.md
146
+ ```
147
+
148
+ ## Quick start (agent skill mode)
149
+
150
+ ```bash
151
+ # Install skills into Claude Code
152
+ curl -fsSL https://raw.githubusercontent.com/derek-palmer/codeforerunner/main/install.sh | bash
153
+
154
+ # In Claude Code:
155
+ # /forerunner-scan → scans your repo
156
+ # /forerunner-readme → generates README.md
157
+ # /forerunner-check → checks for doc drift
158
+ ```
159
+
160
+ ## Quick start (direct API mode)
161
+
162
+ ```bash
163
+ # 1. Install and configure
164
+ pip install codeforerunner
165
+ export ANTHROPIC_API_KEY=sk-...
166
+
167
+ # 2. Run a task
168
+ forerunner generate readme --stream
169
+
170
+ # 3. Enable drift detection
171
+ forerunner doctor --fix # writes forerunner.config.yaml
172
+ forerunner check # run any time or as pre-commit hook
173
+ ```
174
+
175
+ ## GitHub Action
176
+
177
+ ```yaml
178
+ - uses: derek-palmer/codeforerunner@v0.3.2
179
+ ```
180
+
181
+ No-op when `forerunner.config.yaml` is absent.
182
+
183
+ ## Configuration
184
+
185
+ Copy `forerunner.config.yaml.example` to `forerunner.config.yaml` to opt in to drift rules. Generate a starter config with:
186
+
187
+ ```bash
188
+ forerunner doctor --fix
189
+ ```
190
+
191
+ ### Config fields
192
+
193
+ ```yaml
194
+ provider: anthropic # anthropic | openai | google | ollama
195
+ model: claude-opus-4-7
196
+ api_key_env:
197
+ anthropic: ANTHROPIC_API_KEY
198
+
199
+ tasks:
200
+ check:
201
+ enabled_rules:
202
+ - R1-no-cli
203
+ - R2-no-pre-commit
204
+ - R3-no-ci
205
+ - R4-no-installer
206
+ - R5-no-python-package
207
+ - R7-no-mcp
208
+ - R8-no-marketplace
209
+ - RI1-missing-cli
210
+ - RI5-missing-python-package
211
+ - RI7-missing-mcp
212
+ - RV1-version-drift
213
+ ignore_paths:
214
+ - docs/legacy/**/*.md
215
+ ```
216
+
217
+ ### Drift rules
218
+
219
+ | Rule | Fires when |
220
+ |------|-----------|
221
+ | `R1-no-cli` | Doc denies having a CLI, but `cli.py` is present |
222
+ | `R2-no-pre-commit` | Doc denies having pre-commit hooks, but `.pre-commit-hooks.yaml` present |
223
+ | `R3-no-ci` | Doc denies having CI, but `.github/workflows/*.yml` present |
224
+ | `R4-no-installer` | Doc denies having an installer, but `installer.py` present |
225
+ | `R5-no-python-package` | Doc denies having a Python package, but `pyproject.toml` present |
226
+ | `R6-no-docker` | Doc denies having Docker, but `Dockerfile`/`compose.yml` present |
227
+ | `R7-no-mcp` | Doc denies having an MCP server, but `mcp_server.py` present |
228
+ | `R8-no-marketplace` | Doc denies having a marketplace, but `marketplace.json` present |
229
+ | `RI1-missing-cli` | Doc references `forerunner` subcommands but `cli.py` absent |
230
+ | `RI5-missing-python-package` | Doc shows `pip install codeforerunner` but `pyproject.toml` absent |
231
+ | `RI7-missing-mcp` | Doc references `forerunner mcp-server` but `mcp_server.py` absent |
232
+ | `RV1-version-drift` | Doc pins `codeforerunner==X.Y.Z` differing from current version |
233
+
234
+ ## MCP Server
235
+
236
+ `forerunner mcp-server` speaks JSON-RPC 2.0 over stdio and exposes one tool per `prompts/tasks/*.md`. A scan-first gate enforces SPEC V2: any tool except `scan` or `init-agent-onboarding` returns an error until `scan` has been called in the same session.
237
+
238
+ See `examples/mcp/` for Claude Desktop and mcp-cli wiring examples.
239
+
240
+ ## Providers
241
+
242
+ `forerunner generate` supports four providers. When no provider is explicitly configured and no API key is found, forerunner probes `localhost:11434` and falls back to Ollama automatically.
243
+
244
+ | Provider | Env var | Default model |
245
+ |----------|---------|---------------|
246
+ | `anthropic` | `ANTHROPIC_API_KEY` | `claude-opus-4-7` |
247
+ | `openai` | `OPENAI_API_KEY` | `gpt-4o` |
248
+ | `google` | `GOOGLE_API_KEY` | `gemini-2.5-pro` |
249
+ | `ollama` | `OLLAMA_HOST` (optional) | `llama3` |
250
+
251
+ ## Docs and spec
252
+
253
+ - `SPEC.md` — canonical phase/task tracker
254
+ - `docs/getting-started.md` — manual prompt use
255
+ - `docs/prompt-guide.md` — how system, partial, and task prompts compose
256
+ - `docs/editor-agent-setup.md` — adapting prompts to local agents
257
+ - `docs/roadmap.md` — human-readable roadmap
258
+ - `docs/agent-distribution-design.md` — packaging and installer design
@@ -0,0 +1,231 @@
1
+ ![codeForerunner — your codebase gets a Forerunner; your docs finally see the light](images/readme_banner.png)
2
+
3
+ # codeForerunner
4
+
5
+ Model-agnostic repository documentation tooling. Ships a prompt pack for codebase analysis and doc generation, a thin Python CLI, an MCP server, drift-detection rules that keep docs honest — and native slash-command skills for Claude Code, Codex, Gemini CLI, and other agent CLIs.
6
+
7
+ ## Two modes
8
+
9
+ ### Mode A — Agent skill (recommended, no API key required)
10
+
11
+ Install forerunner's prompt pack as skills into your agent CLI. Each documentation task becomes a slash command (`/forerunner-readme`, `/forerunner-check`, etc.) available inside Claude Code, Codex, Gemini CLI, and other agents. Authentication is handled by your existing agent subscription — no separate API key needed.
12
+
13
+ ```bash
14
+ # From a cloned repo
15
+ ./install.sh
16
+
17
+ # One-liner (auto-detects Claude Code, Codex, Gemini CLI)
18
+ curl -fsSL https://raw.githubusercontent.com/derek-palmer/codeforerunner/main/install.sh | bash
19
+
20
+ # Windows
21
+ irm https://raw.githubusercontent.com/derek-palmer/codeforerunner/main/install.ps1 | iex
22
+
23
+ # Via forerunner CLI (after pip install)
24
+ forerunner install --all claude
25
+ forerunner install --all codex
26
+ ```
27
+
28
+ Then in your agent:
29
+
30
+ ```
31
+ /forerunner-scan ← scan the repo first
32
+ /forerunner-readme ← generate README
33
+ /forerunner-check ← detect doc drift
34
+ ```
35
+
36
+ ### Mode B — Direct API (needs API key or Ollama)
37
+
38
+ Install the Python CLI and call your provider directly. Works without any agent CLI installed.
39
+
40
+ ```bash
41
+ pipx install codeforerunner # recommended
42
+ pip install codeforerunner # alternative
43
+ ```
44
+
45
+ Configure a provider (or start Ollama for keyless local generation):
46
+
47
+ ```bash
48
+ export ANTHROPIC_API_KEY=sk-...
49
+ forerunner generate readme --stream
50
+ ```
51
+
52
+ If no API key and no `--provider` flag, forerunner auto-detects Ollama at `localhost:11434` and falls back to local mode.
53
+
54
+ ## Slash commands
55
+
56
+ | Command | Task | Purpose |
57
+ |---------|------|---------|
58
+ | `/forerunner-scan` | `scan` | Collect repo evidence (run first) |
59
+ | `/forerunner-readme` | `readme` | Generate or refresh README.md |
60
+ | `/forerunner-api-docs` | `api-docs` | Generate API reference docs |
61
+ | `/forerunner-diagrams` | `diagrams` | Generate Mermaid architecture diagrams |
62
+ | `/forerunner-flows` | `flows` | Document system flows |
63
+ | `/forerunner-stack-docs` | `stack-docs` | Stack-specific developer docs |
64
+ | `/forerunner-version-audit` | `version-audit` | Audit pinned versions vs EOL |
65
+ | `/forerunner-check` | `check` | Check docs for staleness |
66
+ | `/forerunner-review` | `review` | Doc-impact summary for PR review |
67
+ | `/forerunner-audit` | `audit` | Security and dependency audit |
68
+ | `/forerunner-changelog` | `changelog` | Generate changelog from git log |
69
+ | `/forerunner-init` | `init-agent-onboarding` | Bootstrap or refresh AGENTS.md |
70
+
71
+ Slash command availability depends on the agent CLI. Claude Code, Codex, and Gemini CLI support all 12 commands after install.
72
+
73
+ ## Skill install options
74
+
75
+ | Flag | Effect |
76
+ |------|--------|
77
+ | `./install.sh` | Auto-detect all agents, install all skills |
78
+ | `./install.sh --only claude` | Claude Code only |
79
+ | `./install.sh --only codex` | Codex only |
80
+ | `./install.sh --only gemini` | Gemini CLI only |
81
+ | `./install.sh --dry-run` | Preview, write nothing |
82
+ | `./install.sh --list` | Show detected agents + skill list |
83
+ | `./install.sh --uninstall` | Remove all installed skills |
84
+
85
+ ## CLI
86
+
87
+ ```bash
88
+ pip install codeforerunner
89
+ ```
90
+
91
+ | Command | Purpose |
92
+ |---------|---------|
93
+ | `forerunner init` | Resolve agent-onboarding bundle to stdout. |
94
+ | `forerunner scan` | Resolve scan bundle to stdout. |
95
+ | `forerunner doc <task>` | Resolve `base + partials + task` bundle to stdout. |
96
+ | `forerunner check` | Run drift-detection rules; no-op without `forerunner.config.yaml`. |
97
+ | `forerunner generate <task>` | Call configured provider directly. Add `--stream` for token-by-token output. Falls back to Ollama automatically when no API key is configured. |
98
+ | `forerunner doctor` | Health report: skill parity, config, provider key, local-mode status. Add `--fix` to write a starter config. |
99
+ | `forerunner mcp-server` | Serve prompt bundles as MCP tools over stdio (JSON-RPC 2.0). |
100
+ | `forerunner install <agent>` | Install canonical skill into agent-specific directory. Add `--all` for all per-task skills. |
101
+
102
+ ## Prompt pack
103
+
104
+ Prompts are bundled inside the package at `src/codeforerunner/prompts/`.
105
+
106
+ ```text
107
+ prompts/
108
+ ├── system/base.md
109
+ ├── partials/
110
+ │ ├── context-format.md
111
+ │ ├── output-rules.md
112
+ │ └── stack-hints.md
113
+ └── tasks/
114
+ ├── scan.md api-docs.md audit.md
115
+ ├── readme.md diagrams.md changelog.md
116
+ ├── check.md flows.md version-audit.md
117
+ ├── review.md stack-docs.md
118
+ └── init-agent-onboarding.md
119
+ ```
120
+
121
+ ## Quick start (agent skill mode)
122
+
123
+ ```bash
124
+ # Install skills into Claude Code
125
+ curl -fsSL https://raw.githubusercontent.com/derek-palmer/codeforerunner/main/install.sh | bash
126
+
127
+ # In Claude Code:
128
+ # /forerunner-scan → scans your repo
129
+ # /forerunner-readme → generates README.md
130
+ # /forerunner-check → checks for doc drift
131
+ ```
132
+
133
+ ## Quick start (direct API mode)
134
+
135
+ ```bash
136
+ # 1. Install and configure
137
+ pip install codeforerunner
138
+ export ANTHROPIC_API_KEY=sk-...
139
+
140
+ # 2. Run a task
141
+ forerunner generate readme --stream
142
+
143
+ # 3. Enable drift detection
144
+ forerunner doctor --fix # writes forerunner.config.yaml
145
+ forerunner check # run any time or as pre-commit hook
146
+ ```
147
+
148
+ ## GitHub Action
149
+
150
+ ```yaml
151
+ - uses: derek-palmer/codeforerunner@v0.3.2
152
+ ```
153
+
154
+ No-op when `forerunner.config.yaml` is absent.
155
+
156
+ ## Configuration
157
+
158
+ Copy `forerunner.config.yaml.example` to `forerunner.config.yaml` to opt in to drift rules. Generate a starter config with:
159
+
160
+ ```bash
161
+ forerunner doctor --fix
162
+ ```
163
+
164
+ ### Config fields
165
+
166
+ ```yaml
167
+ provider: anthropic # anthropic | openai | google | ollama
168
+ model: claude-opus-4-7
169
+ api_key_env:
170
+ anthropic: ANTHROPIC_API_KEY
171
+
172
+ tasks:
173
+ check:
174
+ enabled_rules:
175
+ - R1-no-cli
176
+ - R2-no-pre-commit
177
+ - R3-no-ci
178
+ - R4-no-installer
179
+ - R5-no-python-package
180
+ - R7-no-mcp
181
+ - R8-no-marketplace
182
+ - RI1-missing-cli
183
+ - RI5-missing-python-package
184
+ - RI7-missing-mcp
185
+ - RV1-version-drift
186
+ ignore_paths:
187
+ - docs/legacy/**/*.md
188
+ ```
189
+
190
+ ### Drift rules
191
+
192
+ | Rule | Fires when |
193
+ |------|-----------|
194
+ | `R1-no-cli` | Doc denies having a CLI, but `cli.py` is present |
195
+ | `R2-no-pre-commit` | Doc denies having pre-commit hooks, but `.pre-commit-hooks.yaml` present |
196
+ | `R3-no-ci` | Doc denies having CI, but `.github/workflows/*.yml` present |
197
+ | `R4-no-installer` | Doc denies having an installer, but `installer.py` present |
198
+ | `R5-no-python-package` | Doc denies having a Python package, but `pyproject.toml` present |
199
+ | `R6-no-docker` | Doc denies having Docker, but `Dockerfile`/`compose.yml` present |
200
+ | `R7-no-mcp` | Doc denies having an MCP server, but `mcp_server.py` present |
201
+ | `R8-no-marketplace` | Doc denies having a marketplace, but `marketplace.json` present |
202
+ | `RI1-missing-cli` | Doc references `forerunner` subcommands but `cli.py` absent |
203
+ | `RI5-missing-python-package` | Doc shows `pip install codeforerunner` but `pyproject.toml` absent |
204
+ | `RI7-missing-mcp` | Doc references `forerunner mcp-server` but `mcp_server.py` absent |
205
+ | `RV1-version-drift` | Doc pins `codeforerunner==X.Y.Z` differing from current version |
206
+
207
+ ## MCP Server
208
+
209
+ `forerunner mcp-server` speaks JSON-RPC 2.0 over stdio and exposes one tool per `prompts/tasks/*.md`. A scan-first gate enforces SPEC V2: any tool except `scan` or `init-agent-onboarding` returns an error until `scan` has been called in the same session.
210
+
211
+ See `examples/mcp/` for Claude Desktop and mcp-cli wiring examples.
212
+
213
+ ## Providers
214
+
215
+ `forerunner generate` supports four providers. When no provider is explicitly configured and no API key is found, forerunner probes `localhost:11434` and falls back to Ollama automatically.
216
+
217
+ | Provider | Env var | Default model |
218
+ |----------|---------|---------------|
219
+ | `anthropic` | `ANTHROPIC_API_KEY` | `claude-opus-4-7` |
220
+ | `openai` | `OPENAI_API_KEY` | `gpt-4o` |
221
+ | `google` | `GOOGLE_API_KEY` | `gemini-2.5-pro` |
222
+ | `ollama` | `OLLAMA_HOST` (optional) | `llama3` |
223
+
224
+ ## Docs and spec
225
+
226
+ - `SPEC.md` — canonical phase/task tracker
227
+ - `docs/getting-started.md` — manual prompt use
228
+ - `docs/prompt-guide.md` — how system, partial, and task prompts compose
229
+ - `docs/editor-agent-setup.md` — adapting prompts to local agents
230
+ - `docs/roadmap.md` — human-readable roadmap
231
+ - `docs/agent-distribution-design.md` — packaging and installer design
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "codeforerunner"
7
- version = "0.3.2"
7
+ version = "0.4.0"
8
8
  description = "Model-agnostic repository documentation tooling (prompt-first; thin CLI)."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -111,7 +111,8 @@ def cmd_generate(args: argparse.Namespace) -> int:
111
111
  repo_root = Path(args.repo).resolve() if args.repo else Path.cwd()
112
112
  cfg = load_from_repo(repo_root)
113
113
 
114
- provider_name = args.provider or (cfg.provider if cfg else "anthropic")
114
+ explicit_provider = args.provider or (cfg.provider if cfg else None)
115
+ provider_name = explicit_provider or "anthropic"
115
116
  model = args.model or (cfg.model if cfg else None)
116
117
  provider_cls = _providers.get(provider_name)
117
118
  provider = provider_cls()
@@ -132,8 +133,19 @@ def cmd_generate(args: argparse.Namespace) -> int:
132
133
  env_var = (cfg.api_key_env.get(provider_name) if cfg else None) or provider.default_env_var
133
134
  api_key = os.environ.get(env_var)
134
135
  if api_key is None and provider_name != "ollama":
135
- print(f"error: missing API key; set ${env_var}", file=sys.stderr)
136
- return 3
136
+ if explicit_provider is None and _providers.ollama_available():
137
+ provider_name = "ollama"
138
+ provider_cls = _providers.get("ollama")
139
+ provider = provider_cls()
140
+ if not args.model:
141
+ model = provider.default_model
142
+ print("info: no API key; falling back to Ollama (local mode)", file=sys.stderr)
143
+ else:
144
+ msg = f"error: missing API key; set ${env_var}"
145
+ if explicit_provider is None:
146
+ msg += "\nhint: start Ollama for keyless local generation (https://ollama.com)"
147
+ print(msg, file=sys.stderr)
148
+ return 3
137
149
 
138
150
  if getattr(args, "stream", False):
139
151
  try:
@@ -225,13 +225,23 @@ def _check_config_loadable(repo: Path) -> list[Finding]:
225
225
 
226
226
 
227
227
  def _check_provider_api_key(repo: Path) -> list[Finding]:
228
+ from codeforerunner.providers.ollama import is_available as _ollama_available
229
+
228
230
  cfg_path = repo / CONFIG_FILENAME
229
231
  if not cfg_path.is_file():
232
+ if _ollama_available():
233
+ return [
234
+ Finding(
235
+ "ok",
236
+ "provider-api-key",
237
+ "no config; Ollama running — generate will use local mode automatically",
238
+ )
239
+ ]
230
240
  return [
231
241
  Finding(
232
242
  "ok",
233
243
  "provider-api-key",
234
- f"no {CONFIG_FILENAME}; provider key not checked",
244
+ f"no {CONFIG_FILENAME}; set an API key in config or start Ollama for keyless local generation",
235
245
  )
236
246
  ]
237
247
  try:
@@ -259,7 +269,7 @@ def _check_provider_api_key(repo: Path) -> list[Finding]:
259
269
  Finding(
260
270
  "ok",
261
271
  "provider-api-key",
262
- "ollama needs no API key (OLLAMA_HOST optional)",
272
+ "running in local mode (Ollama; no API key needed)",
263
273
  )
264
274
  ]
265
275
  env_var = cfg.api_key_env.get(provider) or _DEFAULT_PROVIDER_ENV.get(provider, "")
@@ -21,6 +21,23 @@ EXIT_USAGE = 2
21
21
  EXIT_BODY_MISMATCH = 3
22
22
  EXIT_UNMANAGED_DEST = 4
23
23
 
24
+ # Per-task skill slugs (source: skills/<slug>/SKILL.md → plugins/codeforerunner/skills/<slug>/SKILL.md)
25
+ TASK_SKILL_SLUGS: tuple[str, ...] = (
26
+ "codeforerunner",
27
+ "forerunner-scan",
28
+ "forerunner-readme",
29
+ "forerunner-api-docs",
30
+ "forerunner-audit",
31
+ "forerunner-changelog",
32
+ "forerunner-check",
33
+ "forerunner-diagrams",
34
+ "forerunner-flows",
35
+ "forerunner-init",
36
+ "forerunner-review",
37
+ "forerunner-stack-docs",
38
+ "forerunner-version-audit",
39
+ )
40
+
24
41
 
25
42
  @dataclass(frozen=True)
26
43
  class Target:
@@ -44,9 +61,65 @@ def resolve_target(agent: str, override: Path | None) -> Target:
44
61
  return Target(agent, home / ".codex/skills/codeforerunner/SKILL.md")
45
62
  if agent == "claude":
46
63
  return Target(agent, home / ".claude/plugins/codeforerunner/skills/codeforerunner/SKILL.md")
64
+ if agent == "gemini":
65
+ raise ValueError(
66
+ "gemini install is handled via `gemini extensions install`; "
67
+ "run `./install.sh --only gemini` instead"
68
+ )
47
69
  raise ValueError(f"unknown agent '{agent}' (expected: codex, claude, generic)")
48
70
 
49
71
 
72
+ def resolve_skill_target(agent: str, slug: str) -> Target:
73
+ """Return install target for a per-task skill slug."""
74
+ home = _home()
75
+ if agent == "codex":
76
+ return Target(agent, home / f".codex/skills/{slug}/SKILL.md")
77
+ if agent == "claude":
78
+ return Target(agent, home / f".claude/plugins/codeforerunner/skills/{slug}/SKILL.md")
79
+ raise ValueError(f"install_all not supported for agent '{agent}' (expected: codex, claude)")
80
+
81
+
82
+ def install_all_skills(
83
+ *,
84
+ agent: str,
85
+ repo_root: Path,
86
+ check_only: bool,
87
+ out=None,
88
+ err=None,
89
+ ) -> int:
90
+ """Install all per-task skills for the given agent. Returns 0 on full success."""
91
+ out = out or sys.stdout
92
+ err = err or sys.stderr
93
+ any_error = False
94
+ for slug in TASK_SKILL_SLUGS:
95
+ src_path = repo_root / "plugins" / "codeforerunner" / "skills" / slug / "SKILL.md"
96
+ if not src_path.is_file():
97
+ print(f"warning: skill source not found: {src_path}", file=err)
98
+ continue
99
+ try:
100
+ target = resolve_skill_target(agent, slug)
101
+ except ValueError as e:
102
+ print(f"error: {e}", file=err)
103
+ return EXIT_USAGE
104
+ # For per-task skills use simple copy (no body-parity check against canonical)
105
+ dest = target.path
106
+ prefix = "would " if check_only else ""
107
+ if dest.exists():
108
+ src_trimmed = src_path.read_bytes().rstrip()
109
+ dest_trimmed = dest.read_bytes().rstrip()
110
+ if src_trimmed == dest_trimmed:
111
+ print(f"skip: {dest} (up-to-date)", file=out)
112
+ continue
113
+ action = "update"
114
+ else:
115
+ action = "create"
116
+ print(f"{prefix}{action}: {dest}", file=out)
117
+ if not check_only:
118
+ dest.parent.mkdir(parents=True, exist_ok=True)
119
+ dest.write_bytes(src_path.read_bytes())
120
+ return EXIT_OK if not any_error else EXIT_BODY_MISMATCH
121
+
122
+
50
123
  def resolve_marketplace_target(agent: str, override: Path | None) -> Target:
51
124
  if agent == "generic":
52
125
  if override is None:
@@ -277,8 +350,11 @@ def install(
277
350
 
278
351
 
279
352
  def add_subparser(sub: argparse._SubParsersAction) -> None:
280
- p = sub.add_parser("install", help="install skill into agent-specific directory (D.installer)")
281
- p.add_argument("agent", choices=["codex", "claude", "generic"])
353
+ p = sub.add_parser("install", help="install skill(s) into agent-specific directories (D.installer)")
354
+ p.add_argument("agent", choices=["codex", "claude", "generic"], nargs="?",
355
+ help="target agent (omit with --all to install to all detected agents)")
356
+ p.add_argument("--all", action="store_true",
357
+ help="install all per-task skills for the specified agent")
282
358
  p.add_argument("--check", action="store_true", help="dry-run: print plan, write nothing")
283
359
  p.add_argument("--path", type=Path, help="dest path override (required for generic)")
284
360
  p.add_argument("--source", type=Path, help="source skill file (default: agent/codeforerunner.skill.md)")
@@ -292,6 +368,19 @@ def add_subparser(sub: argparse._SubParsersAction) -> None:
292
368
 
293
369
  def _cli_entry(args: argparse.Namespace) -> int:
294
370
  root = Path(args.repo).resolve() if args.repo else Path.cwd()
371
+
372
+ if getattr(args, "all", False):
373
+ agent = args.agent or "claude"
374
+ return install_all_skills(
375
+ agent=agent,
376
+ repo_root=root,
377
+ check_only=args.check,
378
+ )
379
+
380
+ if not args.agent:
381
+ print("error: specify an agent or use --all", file=sys.stderr)
382
+ return EXIT_USAGE
383
+
295
384
  return install(
296
385
  agent=args.agent,
297
386
  repo_root=root,