devcoach 0.3.5__tar.gz → 0.3.8__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 (80) hide show
  1. devcoach-0.3.8/.github/scripts/fixtures/devcoach-backup.zip +0 -0
  2. devcoach-0.3.8/.github/scripts/take_screenshots.py +110 -0
  3. {devcoach-0.3.5 → devcoach-0.3.8}/.github/workflows/ci.yml +102 -6
  4. {devcoach-0.3.5 → devcoach-0.3.8}/.github/workflows/ruff-autofix.yml +1 -1
  5. devcoach-0.3.8/.github/workflows/update-screenshots.yml +39 -0
  6. {devcoach-0.3.5 → devcoach-0.3.8}/CLAUDE.md +4 -3
  7. {devcoach-0.3.5 → devcoach-0.3.8}/PKG-INFO +23 -10
  8. {devcoach-0.3.5 → devcoach-0.3.8}/README.md +21 -7
  9. {devcoach-0.3.5 → devcoach-0.3.8}/docs/cli.md +38 -4
  10. devcoach-0.3.8/docs/favicon.svg +1 -0
  11. {devcoach-0.3.5 → devcoach-0.3.8}/docs/getting-started.md +14 -4
  12. devcoach-0.3.8/docs/index.md +55 -0
  13. {devcoach-0.3.5 → devcoach-0.3.8}/docs/mcp-server.md +9 -4
  14. devcoach-0.3.8/docs/screenshots/knowledge-map-dark.png +0 -0
  15. devcoach-0.3.8/docs/screenshots/knowledge-map-light.png +0 -0
  16. devcoach-0.3.8/docs/screenshots/lessons-dark.png +0 -0
  17. devcoach-0.3.8/docs/screenshots/lessons-light.png +0 -0
  18. devcoach-0.3.8/docs/screenshots/settings-dark.png +0 -0
  19. devcoach-0.3.8/docs/screenshots/settings-light.png +0 -0
  20. devcoach-0.3.8/mkdocs.yml +54 -0
  21. {devcoach-0.3.5 → devcoach-0.3.8}/pyproject.toml +15 -4
  22. devcoach-0.3.8/sonar-project.properties +11 -0
  23. {devcoach-0.3.5 → devcoach-0.3.8}/src/devcoach/SKILL.md +65 -68
  24. {devcoach-0.3.5 → devcoach-0.3.8}/src/devcoach/cli/commands.py +174 -26
  25. {devcoach-0.3.5 → devcoach-0.3.8}/src/devcoach/core/coach.py +2 -2
  26. {devcoach-0.3.5 → devcoach-0.3.8}/src/devcoach/core/db.py +21 -6
  27. {devcoach-0.3.5 → devcoach-0.3.8}/src/devcoach/core/git.py +11 -9
  28. {devcoach-0.3.5 → devcoach-0.3.8}/src/devcoach/core/models.py +44 -2
  29. {devcoach-0.3.5 → devcoach-0.3.8}/src/devcoach/mcp/server.py +79 -146
  30. {devcoach-0.3.5 → devcoach-0.3.8}/src/devcoach/web/app.py +37 -6
  31. {devcoach-0.3.5 → devcoach-0.3.8}/src/devcoach/web/templates/base.html +16 -5
  32. {devcoach-0.3.5 → devcoach-0.3.8}/src/devcoach/web/templates/lesson_detail.html +1 -0
  33. {devcoach-0.3.5 → devcoach-0.3.8}/src/devcoach/web/templates/lessons.html +31 -28
  34. {devcoach-0.3.5 → devcoach-0.3.8}/src/devcoach/web/templates/profile.html +8 -8
  35. {devcoach-0.3.5 → devcoach-0.3.8}/src/devcoach/web/templates/settings.html +26 -4
  36. {devcoach-0.3.5 → devcoach-0.3.8}/tests/test_cli.py +30 -9
  37. devcoach-0.3.8/tests/test_cli_commands.py +754 -0
  38. devcoach-0.3.8/tests/test_coach.py +159 -0
  39. devcoach-0.3.8/tests/test_db_extra.py +413 -0
  40. devcoach-0.3.8/tests/test_detect.py +111 -0
  41. devcoach-0.3.8/tests/test_git.py +140 -0
  42. devcoach-0.3.8/tests/test_mcp_server.py +532 -0
  43. devcoach-0.3.8/tests/test_prompts.py +126 -0
  44. {devcoach-0.3.5 → devcoach-0.3.8}/tests/test_web.py +24 -8
  45. devcoach-0.3.8/tests/test_web_extra.py +388 -0
  46. {devcoach-0.3.5 → devcoach-0.3.8}/uv.lock +412 -141
  47. {devcoach-0.3.5 → devcoach-0.3.8}/.github/dependabot.yml +0 -0
  48. {devcoach-0.3.5 → devcoach-0.3.8}/.gitignore +0 -0
  49. {devcoach-0.3.5 → devcoach-0.3.8}/LICENSE +0 -0
  50. {devcoach-0.3.5 → devcoach-0.3.8}/NOTICE +0 -0
  51. {devcoach-0.3.5 → devcoach-0.3.8}/SKILL.md +0 -0
  52. {devcoach-0.3.5 → devcoach-0.3.8}/docs/PLAN.md +0 -0
  53. {devcoach-0.3.5 → devcoach-0.3.8}/docs/configuration.md +0 -0
  54. {devcoach-0.3.5 → devcoach-0.3.8}/docs/web-ui.md +0 -0
  55. {devcoach-0.3.5 → devcoach-0.3.8}/src/devcoach/__init__.py +0 -0
  56. {devcoach-0.3.5 → devcoach-0.3.8}/src/devcoach/cli/__init__.py +0 -0
  57. {devcoach-0.3.5 → devcoach-0.3.8}/src/devcoach/core/__init__.py +0 -0
  58. {devcoach-0.3.5 → devcoach-0.3.8}/src/devcoach/core/detect.py +0 -0
  59. {devcoach-0.3.5 → devcoach-0.3.8}/src/devcoach/core/prompts.py +0 -0
  60. {devcoach-0.3.5 → devcoach-0.3.8}/src/devcoach/mcp/__init__.py +0 -0
  61. {devcoach-0.3.5 → devcoach-0.3.8}/src/devcoach/web/__init__.py +0 -0
  62. {devcoach-0.3.5 → devcoach-0.3.8}/src/devcoach/web/static/favicon.svg +0 -0
  63. {devcoach-0.3.5 → devcoach-0.3.8}/src/devcoach/web/static/relative-time.js +0 -0
  64. {devcoach-0.3.5 → devcoach-0.3.8}/src/devcoach/web/static/style.css +0 -0
  65. {devcoach-0.3.5 → devcoach-0.3.8}/src/devcoach/web/static/vendor/alpinejs.min.js +0 -0
  66. {devcoach-0.3.5 → devcoach-0.3.8}/src/devcoach/web/static/vendor/flatpickr-dark.min.css +0 -0
  67. {devcoach-0.3.5 → devcoach-0.3.8}/src/devcoach/web/static/vendor/flatpickr.min.css +0 -0
  68. {devcoach-0.3.5 → devcoach-0.3.8}/src/devcoach/web/static/vendor/flatpickr.min.js +0 -0
  69. {devcoach-0.3.5 → devcoach-0.3.8}/src/devcoach/web/static/vendor/highlight.min.js +0 -0
  70. {devcoach-0.3.5 → devcoach-0.3.8}/src/devcoach/web/static/vendor/hljs-dark.min.css +0 -0
  71. {devcoach-0.3.5 → devcoach-0.3.8}/src/devcoach/web/static/vendor/hljs-light.min.css +0 -0
  72. {devcoach-0.3.5 → devcoach-0.3.8}/src/devcoach/web/static/vendor/htmx.min.js +0 -0
  73. {devcoach-0.3.5 → devcoach-0.3.8}/src/devcoach/web/static/vendor/icons/bitbucket.svg +0 -0
  74. {devcoach-0.3.5 → devcoach-0.3.8}/src/devcoach/web/static/vendor/icons/github.svg +0 -0
  75. {devcoach-0.3.5 → devcoach-0.3.8}/src/devcoach/web/static/vendor/icons/gitlab.svg +0 -0
  76. {devcoach-0.3.5 → devcoach-0.3.8}/src/devcoach/web/static/vendor/icons/vscode.svg +0 -0
  77. {devcoach-0.3.5 → devcoach-0.3.8}/src/devcoach/web/static/vendor/marked.min.js +0 -0
  78. {devcoach-0.3.5 → devcoach-0.3.8}/src/devcoach/web/static/vendor/tailwind.js +0 -0
  79. {devcoach-0.3.5 → devcoach-0.3.8}/tests/__init__.py +0 -0
  80. {devcoach-0.3.5 → devcoach-0.3.8}/tests/conftest.py +0 -0
@@ -0,0 +1,110 @@
1
+ """Take devcoach UI screenshots for documentation.
2
+
3
+ Flow:
4
+ 1. Restore DB from .github/scripts/fixtures/devcoach-backup.zip via `devcoach restore`
5
+ 2. Start `devcoach ui` on a fixed port
6
+ 3. Capture light + dark screenshots of each page
7
+ 4. Stop the server
8
+ """
9
+
10
+ import signal
11
+ import subprocess
12
+ import sys
13
+ import time
14
+ import urllib.request
15
+ from pathlib import Path
16
+
17
+ SCREENSHOTS_DIR = Path("docs/screenshots")
18
+ FIXTURES_DIR = Path(".github/scripts/fixtures")
19
+ BACKUP_ZIP = FIXTURES_DIR / "devcoach-backup.zip"
20
+ PORT = 7862
21
+ BASE_URL = f"http://localhost:{PORT}"
22
+ VIEWPORT = {"width": 1440, "height": 900}
23
+
24
+ PAGES = [
25
+ ("knowledge-map", "/"),
26
+ ("lessons", "/lessons"),
27
+ ("settings", "/settings"),
28
+ ]
29
+
30
+ def restore_db() -> None:
31
+ result = subprocess.run(
32
+ ["devcoach", "restore", str(BACKUP_ZIP)],
33
+ check=True,
34
+ capture_output=True,
35
+ text=True,
36
+ )
37
+ print(result.stdout.strip())
38
+
39
+
40
+ def wait_for_server(url: str, timeout: int = 30) -> None:
41
+ for _ in range(timeout):
42
+ try:
43
+ urllib.request.urlopen(url, timeout=1)
44
+ return
45
+ except Exception:
46
+ time.sleep(1)
47
+ raise TimeoutError(f"Server at {url} did not start within {timeout}s")
48
+
49
+
50
+ def take_screenshots(server_proc: subprocess.Popen) -> None:
51
+ from playwright.sync_api import sync_playwright
52
+
53
+ SCREENSHOTS_DIR.mkdir(parents=True, exist_ok=True)
54
+
55
+ with sync_playwright() as pw:
56
+ browser = pw.chromium.launch()
57
+
58
+ ctx = browser.new_context(viewport=VIEWPORT, color_scheme="light")
59
+ page = ctx.new_page()
60
+ for name, path in PAGES:
61
+ page.goto(f"{BASE_URL}{path}")
62
+ page.wait_for_load_state("networkidle")
63
+ out = SCREENSHOTS_DIR / f"{name}-light.png"
64
+ page.screenshot(path=str(out))
65
+ print(f" saved {out}")
66
+ ctx.close()
67
+
68
+ ctx = browser.new_context(viewport=VIEWPORT, color_scheme="dark")
69
+ page = ctx.new_page()
70
+ for name, path in PAGES:
71
+ page.goto(f"{BASE_URL}{path}")
72
+ page.wait_for_load_state("networkidle")
73
+ out = SCREENSHOTS_DIR / f"{name}-dark.png"
74
+ page.screenshot(path=str(out))
75
+ print(f" saved {out}")
76
+ ctx.close()
77
+
78
+ browser.close()
79
+
80
+ server_proc.send_signal(signal.SIGTERM)
81
+ server_proc.wait(timeout=10)
82
+
83
+
84
+ def main() -> None:
85
+ if not BACKUP_ZIP.exists():
86
+ sys.exit(f"Backup not found: {BACKUP_ZIP}")
87
+
88
+ print(f"Restoring DB from {BACKUP_ZIP}…")
89
+ restore_db()
90
+
91
+ print(f"Starting devcoach UI on port {PORT}…")
92
+ proc = subprocess.Popen(
93
+ ["devcoach", "ui", "--port", str(PORT)],
94
+ stdout=subprocess.DEVNULL,
95
+ stderr=subprocess.DEVNULL,
96
+ )
97
+
98
+ try:
99
+ wait_for_server(BASE_URL)
100
+ print("Taking screenshots…")
101
+ take_screenshots(proc)
102
+ except Exception:
103
+ proc.terminate()
104
+ raise
105
+
106
+ print("Done.")
107
+
108
+
109
+ if __name__ == "__main__":
110
+ main()
@@ -1,8 +1,17 @@
1
1
  name: CI
2
2
 
3
+ run-name: >-
4
+ ${{ github.event_name == 'workflow_dispatch'
5
+ && format('CI — New release ({0})', inputs.version != '' && inputs.version || inputs.bump)
6
+ || (startsWith(github.ref, 'refs/tags/v')
7
+ && format('CI — New release ({0})', github.ref_name)
8
+ || (github.event_name == 'pull_request'
9
+ && format('CI - PR {0}', github.event.pull_request.title)
10
+ || format('CI — {0}', github.event.head_commit.message))) }}
11
+
3
12
  # Covers three scenarios:
4
13
  #
5
- # 1. Push to main / pull request → lint + test + build
14
+ # 1. Push to main / pull request → lint + test + build + sonar + pages
6
15
  # 2. Tag push (v*) → lint + test + build + publish + GitHub Release
7
16
  # 3. workflow_dispatch (Release) → bump version → tag → lint + test + build + publish + GitHub Release
8
17
  #
@@ -70,12 +79,14 @@ jobs:
70
79
  echo "version=$NEXT" >> "$GITHUB_OUTPUT"
71
80
  echo "tag=v$NEXT" >> "$GITHUB_OUTPUT"
72
81
 
73
- - name: Bump version in pyproject.toml
74
- run: sed -i 's/^version = ".*"/version = "${{ steps.ver.outputs.version }}"/' pyproject.toml
82
+ - name: Bump version in pyproject.toml and sonar-project.properties
83
+ run: |
84
+ sed -i 's/^version = ".*"/version = "${{ steps.ver.outputs.version }}"/' pyproject.toml
85
+ sed -i 's/^sonar.projectVersion=.*/sonar.projectVersion=${{ steps.ver.outputs.version }}/' sonar-project.properties
75
86
 
76
87
  - name: Commit and tag
77
88
  run: |
78
- git add pyproject.toml
89
+ git add pyproject.toml sonar-project.properties
79
90
  git commit -m "chore: bump version to ${{ steps.ver.outputs.version }}"
80
91
  git tag "${{ steps.ver.outputs.tag }}"
81
92
  git push --atomic origin main "${{ steps.ver.outputs.tag }}"
@@ -106,7 +117,7 @@ jobs:
106
117
  strategy:
107
118
  fail-fast: false
108
119
  matrix:
109
- python-version: ["3.11", "3.12", "3.13"]
120
+ python-version: ["3.12", "3.13"]
110
121
  steps:
111
122
  - uses: actions/checkout@v6
112
123
  with:
@@ -115,7 +126,8 @@ jobs:
115
126
  with:
116
127
  python-version: ${{ matrix.python-version }}
117
128
  - run: uv sync --group dev
118
- - run: uv run pytest tests/ -v --tb=short
129
+ - name: Run tests
130
+ run: uv run pytest tests/ -v --tb=short
119
131
 
120
132
  # ── Build ───────────────────────────────────────────────────────────────
121
133
  build:
@@ -137,6 +149,90 @@ jobs:
137
149
  path: dist/
138
150
  retention-days: 7
139
151
 
152
+ # ── Coverage comment on PR ──────────────────────────────────────────────
153
+ # Posts (and updates) a coverage summary comment on every PR push.
154
+ # Reads the .coverage file generated by pytest-cov — no extra deps needed.
155
+ coverage:
156
+ name: Coverage comment
157
+ needs: [bump]
158
+ if: >
159
+ github.event_name == 'pull_request'
160
+ && (needs.bump.result == 'success' || needs.bump.result == 'skipped')
161
+ runs-on: ubuntu-latest
162
+ permissions:
163
+ pull-requests: write
164
+ steps:
165
+ - uses: actions/checkout@v6
166
+ - uses: astral-sh/setup-uv@v7
167
+ with:
168
+ python-version: "3.12"
169
+ - run: uv sync --group dev
170
+ - name: Run tests with coverage
171
+ run: uv run pytest tests/ --cov=src/devcoach --cov-report=xml
172
+ - uses: py-cov-action/python-coverage-comment-action@v3
173
+ with:
174
+ GITHUB_TOKEN: ${{ github.token }}
175
+ MINIMUM_GREEN: 90
176
+ MINIMUM_ORANGE: 80
177
+
178
+ # ── SonarCloud scan + quality gate ─────────────────────────────────────
179
+ # CI-based analysis: feeds coverage.xml to SonarCloud.
180
+ # Skipped on pull_request events — SONAR_TOKEN is not available to PR
181
+ # workflows (GitHub restricts secret access). Runs on main / tags / dispatch
182
+ # where the token is available.
183
+ # Requires Automatic Analysis to be DISABLED on sonarcloud.io
184
+ # (Administration → Analysis Method).
185
+ sonar:
186
+ name: SonarCloud scan
187
+ needs: [bump, test]
188
+ if: >
189
+ always()
190
+ && github.event_name != 'pull_request'
191
+ && (needs.bump.result == 'success' || needs.bump.result == 'skipped')
192
+ && needs.test.result == 'success'
193
+ runs-on: ubuntu-latest
194
+ steps:
195
+ - uses: actions/checkout@v6
196
+ with:
197
+ ref: ${{ needs.bump.outputs.tag || github.ref }}
198
+ fetch-depth: 0
199
+ - uses: astral-sh/setup-uv@v7
200
+ with:
201
+ python-version: "3.12"
202
+ - run: uv sync --group dev
203
+ - name: Run tests with coverage
204
+ run: uv run pytest tests/ -v --tb=short --cov=src/devcoach --cov-report=xml
205
+ - uses: sonarsource/sonarqube-scan-action@v7
206
+ env:
207
+ SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
208
+
209
+ # ── GitHub Pages ────────────────────────────────────────────────────────
210
+ # Builds MkDocs site and deploys to GitHub Pages on every push to main.
211
+ pages:
212
+ name: Deploy docs to GitHub Pages
213
+ needs: [bump, build]
214
+ if: always() && needs.build.result == 'success' && github.ref == 'refs/heads/main' && github.event_name == 'push'
215
+ runs-on: ubuntu-latest
216
+ permissions:
217
+ pages: write
218
+ id-token: write
219
+ environment:
220
+ name: github-pages
221
+ url: ${{ steps.deploy.outputs.page_url }}
222
+ steps:
223
+ - uses: actions/checkout@v6
224
+ - uses: astral-sh/setup-uv@v7
225
+ with:
226
+ python-version: "3.12"
227
+ - run: uv sync --group docs
228
+ - run: uv run mkdocs build
229
+ - uses: actions/upload-pages-artifact@v5
230
+ with:
231
+ path: site/
232
+ - name: Deploy to GitHub Pages
233
+ id: deploy
234
+ uses: actions/deploy-pages@v5
235
+
140
236
  # ── Publish ─────────────────────────────────────────────────────────────
141
237
  # Runs when a tag is present: either created by the bump job (workflow_dispatch)
142
238
  # or pushed directly (git push origin v1.2.3).
@@ -30,7 +30,7 @@ jobs:
30
30
  run: uv run ruff format src/ tests/
31
31
 
32
32
  - name: Open PR if there are changes
33
- uses: peter-evans/create-pull-request@v7
33
+ uses: peter-evans/create-pull-request@v8
34
34
  with:
35
35
  commit-message: "style: apply ruff auto-fixes"
36
36
  title: "style: ruff auto-fix"
@@ -0,0 +1,39 @@
1
+ name: Update documentation screenshots (GitHub Pages)
2
+
3
+ on:
4
+ workflow_dispatch:
5
+
6
+ jobs:
7
+ screenshots:
8
+ name: Take and commit screenshots
9
+ runs-on: ubuntu-latest
10
+ permissions:
11
+ contents: write
12
+
13
+ steps:
14
+ - uses: actions/checkout@v6
15
+
16
+ - uses: astral-sh/setup-uv@v7
17
+ with:
18
+ python-version: "3.12"
19
+
20
+ - name: Install devcoach
21
+ run: uv sync
22
+
23
+ - name: Install Playwright + Chromium
24
+ run: |
25
+ uv pip install playwright
26
+ uv run playwright install chromium --with-deps
27
+
28
+ - name: Restore DB and take screenshots
29
+ run: uv run python .github/scripts/take_screenshots.py
30
+
31
+ - name: Commit screenshots
32
+ run: |
33
+ git config user.name "github-actions[bot]"
34
+ git config user.email "github-actions[bot]@users.noreply.github.com"
35
+ git add docs/screenshots/
36
+ git diff --staged --quiet && echo "No changes." || (
37
+ git commit -m "docs: update screenshots [skip ci]" &&
38
+ git push
39
+ )
@@ -9,7 +9,7 @@ based on the user's knowledge map, the rate limit, and what has already been tau
9
9
 
10
10
  Repo: https://github.com/UltimaPhoenix/dev-coach
11
11
  PyPI package name: `devcoach`
12
- End-user command: `uvx devcoach`
12
+ End-user command: `uvx devcoach` (CLI) / `uvx devcoach mcp` (MCP server)
13
13
 
14
14
  ---
15
15
 
@@ -240,7 +240,7 @@ npx @modelcontextprotocol/inspector devcoach
240
240
  "mcpServers": {
241
241
  "devcoach": {
242
242
  "command": "uvx",
243
- "args": ["devcoach"]
243
+ "args": ["devcoach", "mcp"]
244
244
  }
245
245
  }
246
246
  }
@@ -252,7 +252,8 @@ npx @modelcontextprotocol/inspector devcoach
252
252
 
253
253
  - Follow **Uncle Bob's Clean Code** principles
254
254
  - Follow **PEP** standards
255
- - Linting and formatting enforced by **ruff** — run `uv run ruff check src/ tests/` and `uv run ruff format src/ tests/` before committing
255
+ - Linting and formatting enforced by **ruff** — run `uv run ruff check src/ tests/` and `uv run ruff format src/ tests/` before committing. **All ruff checks must pass before committing.**
256
+ - Test coverage must stay **at or above 80%** — run `uv run pytest --cov=src/devcoach --cov-fail-under=80` to verify. Do not merge code that drops total coverage below this threshold.
256
257
  - No external dependencies beyond `fastmcp` and `pydantic`
257
258
  - `db.py` exposes only pure functions — no business logic
258
259
  - `coach.py` never imports from `server.py` (one-way dependency)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: devcoach
3
- Version: 0.3.5
3
+ Version: 0.3.8
4
4
  Summary: A local MCP server that acts as a progressive technical coach for Claude Code and Claude Desktop
5
5
  Project-URL: Homepage, https://github.com/UltimaPhoenix/dev-coach
6
6
  Project-URL: Repository, https://github.com/UltimaPhoenix/dev-coach
@@ -216,12 +216,11 @@ Classifier: Intended Audience :: Developers
216
216
  Classifier: License :: OSI Approved :: Apache Software License
217
217
  Classifier: Operating System :: OS Independent
218
218
  Classifier: Programming Language :: Python :: 3
219
- Classifier: Programming Language :: Python :: 3.11
220
219
  Classifier: Programming Language :: Python :: 3.12
221
220
  Classifier: Programming Language :: Python :: 3.13
222
221
  Classifier: Topic :: Education
223
222
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
224
- Requires-Python: >=3.11
223
+ Requires-Python: >=3.12
225
224
  Requires-Dist: fastapi>=0.110
226
225
  Requires-Dist: fastmcp>=2.0
227
226
  Requires-Dist: jinja2>=3.1
@@ -233,8 +232,11 @@ Description-Content-Type: text/markdown
233
232
  # devcoach
234
233
 
235
234
  [![PyPI](https://img.shields.io/github/v/release/UltimaPhoenix/dev-coach?label=PyPI)](https://pypi.org/project/devcoach/)
236
- [![Python](https://img.shields.io/badge/python-3.11%2B-blue)](https://pypi.org/project/devcoach/)
235
+ [![Python](https://img.shields.io/badge/python-3.12%2B-blue)](https://pypi.org/project/devcoach/)
237
236
  [![CI](https://github.com/UltimaPhoenix/dev-coach/actions/workflows/ci.yml/badge.svg)](https://github.com/UltimaPhoenix/dev-coach/actions/workflows/ci.yml)
237
+ [![Quality Gate](https://sonarcloud.io/api/project_badges/measure?project=UltimaPhoenix_dev-coach&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=UltimaPhoenix_dev-coach)
238
+ [![Coverage](https://sonarcloud.io/api/project_badges/measure?project=UltimaPhoenix_dev-coach&metric=coverage)](https://sonarcloud.io/summary/new_code?id=UltimaPhoenix_dev-coach)
239
+ [![Docs](https://img.shields.io/badge/docs-GitHub%20Pages-purple)](https://ultimaphoenix.github.io/dev-coach/)
238
240
  [![License](https://img.shields.io/badge/license-Apache%202.0-blue)](LICENSE)
239
241
 
240
242
  **Progressive technical coaching, directly in Claude.** After every task you complete with Claude Code or Claude Desktop, devcoach delivers a short, targeted lesson based on what you already know — no generic tutorials, no repeated topics.
@@ -254,12 +256,20 @@ Everything runs **locally**. No data leaves your machine. One SQLite file at `~/
254
256
 
255
257
  ---
256
258
 
259
+ ## Screenshots
260
+
261
+ | Knowledge map | Lesson history | Settings |
262
+ |:---------------------------------------------------------:|:---:|:---:|
263
+ | ![Knowledge map](docs/screenshots/knowledge-map-dark.png) | ![Lessons](docs/screenshots/lessons-dark.png) | ![Settings](docs/screenshots/settings-dark.png) |
264
+
265
+ ---
266
+
257
267
  ## Installation
258
268
 
259
269
  ### Recommended — no permanent install needed
260
270
 
261
271
  ```bash
262
- uvx devcoach
272
+ uvx devcoach mcp # starts the MCP server directly
263
273
  ```
264
274
 
265
275
  ### Permanent install
@@ -276,7 +286,7 @@ devcoach install
276
286
 
277
287
  Restart Claude Code or Claude Desktop after installing.
278
288
 
279
- > **Requirements:** [uv](https://docs.astral.sh/uv/) · Python 3.11+ · Claude Code or Claude Desktop
289
+ > **Requirements:** [uv](https://docs.astral.sh/uv/) · Python 3.12+ · Claude Code or Claude Desktop
280
290
 
281
291
  ---
282
292
 
@@ -311,7 +321,7 @@ Claude: [does the work]
311
321
 
312
322
  **Structured concurrency with asyncio.TaskGroup**
313
323
 
314
- TaskGroup (Python 3.11+) is the modern replacement for bare gather() calls.
324
+ TaskGroup (Python 3.12+) is the modern replacement for bare gather() calls.
315
325
  Unlike gather(), it cancels sibling tasks automatically when one raises...
316
326
  ```
317
327
 
@@ -330,13 +340,16 @@ devcoach feedback lesson-python-taskgroup-001 dont_know # need to revisit —
330
340
 
331
341
  | Command | Description |
332
342
  |---------|-------------|
343
+ | `devcoach` | Show all available commands |
344
+ | `devcoach mcp` | Start the MCP server (stdio) for Claude Code / Claude Desktop |
333
345
  | `devcoach setup` | Run the onboarding wizard in the terminal |
334
346
  | `devcoach install` | Register with Claude Code / Claude Desktop |
335
347
  | `devcoach profile` | Show your knowledge map with confidence bars |
336
348
  | `devcoach stats` | Overview: lesson counts, weakest/strongest topics |
337
349
  | `devcoach lessons` | Browse lesson history with filters |
338
350
  | `devcoach lesson <id>` | Show a single lesson in full |
339
- | `devcoach star <id>` | Toggle starred flag |
351
+ | `devcoach star <id>` | Mark a lesson as starred (favourite) |
352
+ | `devcoach unstar <id>` | Remove the starred mark from a lesson |
340
353
  | `devcoach feedback <id> <know\|dont_know\|clear>` | Record comprehension |
341
354
  | `devcoach set max_per_day <n>` | Max lessons in a 24-hour window (default 2) |
342
355
  | `devcoach set min_gap_minutes <n>` | Minimum minutes between lessons (default 240) |
@@ -376,7 +389,7 @@ devcoach implements the [MCP 2025-11-25 spec](https://modelcontextprotocol.io/sp
376
389
  "devcoach": {
377
390
  "type": "stdio",
378
391
  "command": "uvx",
379
- "args": ["devcoach"]
392
+ "args": ["devcoach", "mcp"]
380
393
  }
381
394
  }
382
395
  }
@@ -418,7 +431,7 @@ git tag v1.2.3
418
431
  git push origin v1.2.3
419
432
  ```
420
433
 
421
- The pipeline will lint, test across Python 3.11–3.13, build, publish to PyPI via OIDC Trusted Publishing, and create a GitHub Release automatically.
434
+ The pipeline will lint, test across Python 3.12–3.13, build, publish to PyPI via OIDC Trusted Publishing, and create a GitHub Release automatically.
422
435
 
423
436
  > **First-time PyPI setup:** configure a Trusted Publisher on PyPI for `UltimaPhoenix/dev-coach` (environment: `pypi`, workflow: `ci.yml`). No API token required after that.
424
437
 
@@ -1,8 +1,11 @@
1
1
  # devcoach
2
2
 
3
3
  [![PyPI](https://img.shields.io/github/v/release/UltimaPhoenix/dev-coach?label=PyPI)](https://pypi.org/project/devcoach/)
4
- [![Python](https://img.shields.io/badge/python-3.11%2B-blue)](https://pypi.org/project/devcoach/)
4
+ [![Python](https://img.shields.io/badge/python-3.12%2B-blue)](https://pypi.org/project/devcoach/)
5
5
  [![CI](https://github.com/UltimaPhoenix/dev-coach/actions/workflows/ci.yml/badge.svg)](https://github.com/UltimaPhoenix/dev-coach/actions/workflows/ci.yml)
6
+ [![Quality Gate](https://sonarcloud.io/api/project_badges/measure?project=UltimaPhoenix_dev-coach&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=UltimaPhoenix_dev-coach)
7
+ [![Coverage](https://sonarcloud.io/api/project_badges/measure?project=UltimaPhoenix_dev-coach&metric=coverage)](https://sonarcloud.io/summary/new_code?id=UltimaPhoenix_dev-coach)
8
+ [![Docs](https://img.shields.io/badge/docs-GitHub%20Pages-purple)](https://ultimaphoenix.github.io/dev-coach/)
6
9
  [![License](https://img.shields.io/badge/license-Apache%202.0-blue)](LICENSE)
7
10
 
8
11
  **Progressive technical coaching, directly in Claude.** After every task you complete with Claude Code or Claude Desktop, devcoach delivers a short, targeted lesson based on what you already know — no generic tutorials, no repeated topics.
@@ -22,12 +25,20 @@ Everything runs **locally**. No data leaves your machine. One SQLite file at `~/
22
25
 
23
26
  ---
24
27
 
28
+ ## Screenshots
29
+
30
+ | Knowledge map | Lesson history | Settings |
31
+ |:---------------------------------------------------------:|:---:|:---:|
32
+ | ![Knowledge map](docs/screenshots/knowledge-map-dark.png) | ![Lessons](docs/screenshots/lessons-dark.png) | ![Settings](docs/screenshots/settings-dark.png) |
33
+
34
+ ---
35
+
25
36
  ## Installation
26
37
 
27
38
  ### Recommended — no permanent install needed
28
39
 
29
40
  ```bash
30
- uvx devcoach
41
+ uvx devcoach mcp # starts the MCP server directly
31
42
  ```
32
43
 
33
44
  ### Permanent install
@@ -44,7 +55,7 @@ devcoach install
44
55
 
45
56
  Restart Claude Code or Claude Desktop after installing.
46
57
 
47
- > **Requirements:** [uv](https://docs.astral.sh/uv/) · Python 3.11+ · Claude Code or Claude Desktop
58
+ > **Requirements:** [uv](https://docs.astral.sh/uv/) · Python 3.12+ · Claude Code or Claude Desktop
48
59
 
49
60
  ---
50
61
 
@@ -79,7 +90,7 @@ Claude: [does the work]
79
90
 
80
91
  **Structured concurrency with asyncio.TaskGroup**
81
92
 
82
- TaskGroup (Python 3.11+) is the modern replacement for bare gather() calls.
93
+ TaskGroup (Python 3.12+) is the modern replacement for bare gather() calls.
83
94
  Unlike gather(), it cancels sibling tasks automatically when one raises...
84
95
  ```
85
96
 
@@ -98,13 +109,16 @@ devcoach feedback lesson-python-taskgroup-001 dont_know # need to revisit —
98
109
 
99
110
  | Command | Description |
100
111
  |---------|-------------|
112
+ | `devcoach` | Show all available commands |
113
+ | `devcoach mcp` | Start the MCP server (stdio) for Claude Code / Claude Desktop |
101
114
  | `devcoach setup` | Run the onboarding wizard in the terminal |
102
115
  | `devcoach install` | Register with Claude Code / Claude Desktop |
103
116
  | `devcoach profile` | Show your knowledge map with confidence bars |
104
117
  | `devcoach stats` | Overview: lesson counts, weakest/strongest topics |
105
118
  | `devcoach lessons` | Browse lesson history with filters |
106
119
  | `devcoach lesson <id>` | Show a single lesson in full |
107
- | `devcoach star <id>` | Toggle starred flag |
120
+ | `devcoach star <id>` | Mark a lesson as starred (favourite) |
121
+ | `devcoach unstar <id>` | Remove the starred mark from a lesson |
108
122
  | `devcoach feedback <id> <know\|dont_know\|clear>` | Record comprehension |
109
123
  | `devcoach set max_per_day <n>` | Max lessons in a 24-hour window (default 2) |
110
124
  | `devcoach set min_gap_minutes <n>` | Minimum minutes between lessons (default 240) |
@@ -144,7 +158,7 @@ devcoach implements the [MCP 2025-11-25 spec](https://modelcontextprotocol.io/sp
144
158
  "devcoach": {
145
159
  "type": "stdio",
146
160
  "command": "uvx",
147
- "args": ["devcoach"]
161
+ "args": ["devcoach", "mcp"]
148
162
  }
149
163
  }
150
164
  }
@@ -186,7 +200,7 @@ git tag v1.2.3
186
200
  git push origin v1.2.3
187
201
  ```
188
202
 
189
- The pipeline will lint, test across Python 3.11–3.13, build, publish to PyPI via OIDC Trusted Publishing, and create a GitHub Release automatically.
203
+ The pipeline will lint, test across Python 3.12–3.13, build, publish to PyPI via OIDC Trusted Publishing, and create a GitHub Release automatically.
190
204
 
191
205
  > **First-time PyPI setup:** configure a Trusted Publisher on PyPI for `UltimaPhoenix/dev-coach` (environment: `pypi`, workflow: `ci.yml`). No API token required after that.
192
206
 
@@ -1,15 +1,38 @@
1
1
  # CLI reference
2
2
 
3
- ## Global
3
+ ## Overview
4
+
5
+ Running `devcoach` with no arguments prints a help panel listing every available command:
4
6
 
5
7
  ```
6
- devcoach <command> [options]
8
+ devcoach
7
9
  ```
8
10
 
9
11
  All commands operate on `~/.devcoach/coaching.db`. No network access required.
10
12
 
11
13
  ---
12
14
 
15
+ ## MCP server
16
+
17
+ ### `devcoach mcp`
18
+
19
+ Start the stdio MCP server for Claude Code or Claude Desktop. This is what you put in your MCP config:
20
+
21
+ ```json
22
+ {
23
+ "mcpServers": {
24
+ "devcoach": {
25
+ "command": "uvx",
26
+ "args": ["devcoach", "mcp"]
27
+ }
28
+ }
29
+ }
30
+ ```
31
+
32
+ ---
33
+
34
+ ---
35
+
13
36
  ## Knowledge map
14
37
 
15
38
  ### `devcoach profile`
@@ -117,13 +140,24 @@ devcoach lesson lesson-python-generators-001
117
140
 
118
141
  ### `devcoach star <id>`
119
142
 
120
- Toggle the starred (favourite) flag on a lesson.
143
+ Mark a lesson as starred (favourite).
121
144
 
122
145
  ```bash
123
146
  devcoach star lesson-python-generators-001
124
147
  # → Lesson lesson-python-generators-001 → ★ starred
125
148
  ```
126
149
 
150
+ ### `devcoach unstar <id>`
151
+
152
+ Remove the starred mark from a lesson.
153
+
154
+ ```bash
155
+ devcoach unstar lesson-python-generators-001
156
+ # → Lesson lesson-python-generators-001 → ☆ unstarred
157
+ ```
158
+
159
+ Both commands are idempotent — calling them when the lesson is already in the target state is safe.
160
+
127
161
  ### `devcoach feedback <id> <value>`
128
162
 
129
163
  Record whether you understood a lesson. Adjusts knowledge confidence.
@@ -191,7 +225,7 @@ Followed by optional group assignment and rate-limit settings.
191
225
 
192
226
  ### `devcoach install`
193
227
 
194
- Register the devcoach MCP server in Claude's config files.
228
+ Register the devcoach MCP server (`devcoach mcp`) in Claude's config files.
195
229
 
196
230
  ```bash
197
231
  devcoach install # both Claude Code + Claude Desktop
@@ -0,0 +1 @@
1
+ ../src/devcoach/web/static/favicon.svg
@@ -3,25 +3,35 @@
3
3
  ## Prerequisites
4
4
 
5
5
  - [uv](https://docs.astral.sh/uv/) (recommended) or pip
6
- - Python 3.11+
6
+ - Python 3.12+
7
7
  - Claude Code or Claude Desktop
8
8
 
9
9
  ---
10
10
 
11
11
  ## 1. Install
12
12
 
13
- ### One-time run (no permanent install)
13
+ devcoach is published on [PyPI](https://pypi.org/project/devcoach/) and can be installed with any Python package manager.
14
+
15
+ ### One-time run — no install needed
14
16
 
15
17
  ```bash
16
- uvx devcoach
18
+ uvx devcoach mcp
17
19
  ```
18
20
 
19
- ### Permanent install
21
+ `uvx` fetches the latest release from PyPI and runs it in an isolated environment. Nothing is left behind.
22
+
23
+ ### Permanent install with uv (recommended)
20
24
 
21
25
  ```bash
22
26
  uv tool install devcoach
23
27
  ```
24
28
 
29
+ ### Permanent install with pip
30
+
31
+ ```bash
32
+ pip install devcoach
33
+ ```
34
+
25
35
  ---
26
36
 
27
37
  ## 2. Register with Claude