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.
- codeforerunner-0.4.0/PKG-INFO +258 -0
- codeforerunner-0.4.0/README.md +231 -0
- {codeforerunner-0.3.2 → codeforerunner-0.4.0}/pyproject.toml +1 -1
- {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/cli.py +15 -3
- {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/doctor.py +12 -2
- {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/installer.py +91 -2
- {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/providers/__init__.py +2 -1
- {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/providers/anthropic.py +1 -1
- {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/providers/ollama.py +10 -0
- codeforerunner-0.4.0/src/codeforerunner.egg-info/PKG-INFO +258 -0
- {codeforerunner-0.3.2 → codeforerunner-0.4.0}/tests/test_cli.py +130 -0
- {codeforerunner-0.3.2 → codeforerunner-0.4.0}/tests/test_doctor.py +39 -0
- {codeforerunner-0.3.2 → codeforerunner-0.4.0}/tests/test_providers.py +52 -3
- codeforerunner-0.3.2/PKG-INFO +0 -133
- codeforerunner-0.3.2/README.md +0 -106
- codeforerunner-0.3.2/src/codeforerunner.egg-info/PKG-INFO +0 -133
- {codeforerunner-0.3.2 → codeforerunner-0.4.0}/LICENSE.md +0 -0
- {codeforerunner-0.3.2 → codeforerunner-0.4.0}/setup.cfg +0 -0
- {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/__init__.py +0 -0
- {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/bundle.py +0 -0
- {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/check.py +0 -0
- {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/config.py +0 -0
- {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/mcp_server.py +0 -0
- {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/prompts/partials/context-format.md +0 -0
- {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/prompts/partials/output-rules.md +0 -0
- {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/prompts/partials/stack-hints.md +0 -0
- {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/prompts/system/base.md +0 -0
- {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/prompts/tasks/api-docs.md +0 -0
- {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/prompts/tasks/audit.md +0 -0
- {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/prompts/tasks/changelog.md +0 -0
- {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/prompts/tasks/check.md +0 -0
- {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/prompts/tasks/diagrams.md +0 -0
- {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/prompts/tasks/flows.md +0 -0
- {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/prompts/tasks/init-agent-onboarding.md +0 -0
- {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/prompts/tasks/readme.md +0 -0
- {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/prompts/tasks/review.md +0 -0
- {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/prompts/tasks/scan.md +0 -0
- {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/prompts/tasks/stack-docs.md +0 -0
- {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/prompts/tasks/version-audit.md +0 -0
- {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/providers/base.py +0 -0
- {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/providers/google.py +0 -0
- {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner/providers/openai.py +0 -0
- {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner.egg-info/SOURCES.txt +0 -0
- {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner.egg-info/dependency_links.txt +0 -0
- {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner.egg-info/entry_points.txt +0 -0
- {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner.egg-info/requires.txt +0 -0
- {codeforerunner-0.3.2 → codeforerunner-0.4.0}/src/codeforerunner.egg-info/top_level.txt +0 -0
- {codeforerunner-0.3.2 → codeforerunner-0.4.0}/tests/test_check.py +0 -0
- {codeforerunner-0.3.2 → codeforerunner-0.4.0}/tests/test_check_config_integration.py +0 -0
- {codeforerunner-0.3.2 → codeforerunner-0.4.0}/tests/test_config.py +0 -0
- {codeforerunner-0.3.2 → codeforerunner-0.4.0}/tests/test_examples.py +0 -0
- {codeforerunner-0.3.2 → codeforerunner-0.4.0}/tests/test_hooks_manifest.py +0 -0
- {codeforerunner-0.3.2 → codeforerunner-0.4.0}/tests/test_installer.py +0 -0
- {codeforerunner-0.3.2 → codeforerunner-0.4.0}/tests/test_mcp_server.py +0 -0
- {codeforerunner-0.3.2 → codeforerunner-0.4.0}/tests/test_validate_codex_marketplace.py +0 -0
- {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
|
+

|
|
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
|
+

|
|
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
|
|
@@ -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
|
-
|
|
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
|
-
|
|
136
|
-
|
|
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};
|
|
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
|
-
"
|
|
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
|
|
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,
|