devtime-ei 0.1.0__tar.gz → 0.1.2__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 (77) hide show
  1. {devtime_ei-0.1.0 → devtime_ei-0.1.2}/PKG-INFO +113 -30
  2. {devtime_ei-0.1.0 → devtime_ei-0.1.2}/README.md +108 -28
  3. {devtime_ei-0.1.0 → devtime_ei-0.1.2}/pyproject.toml +15 -3
  4. {devtime_ei-0.1.0 → devtime_ei-0.1.2}/src/devtime/__init__.py +1 -1
  5. {devtime_ei-0.1.0 → devtime_ei-0.1.2}/src/devtime/cli.py +55 -7
  6. devtime_ei-0.1.2/src/devtime/demo.py +75 -0
  7. devtime_ei-0.1.2/src/devtime/mcp/server.py +42 -0
  8. devtime_ei-0.1.2/src/devtime/mcp/transport.py +99 -0
  9. devtime_ei-0.1.2/src/devtime/resources/demo-saas/.devtimeignore +23 -0
  10. devtime_ei-0.1.2/src/devtime/resources/demo-saas/README.md +5 -0
  11. devtime_ei-0.1.2/src/devtime/resources/demo-saas/docs/decisions/0001-use-jwt.md +15 -0
  12. devtime_ei-0.1.2/src/devtime/resources/demo-saas/package.json +15 -0
  13. devtime_ei-0.1.2/src/devtime/resources/demo-saas/src/admin/permissions.ts +9 -0
  14. devtime_ei-0.1.2/src/devtime/resources/demo-saas/src/auth/login.ts +21 -0
  15. devtime_ei-0.1.2/src/devtime/resources/demo-saas/src/auth/middleware.ts +16 -0
  16. devtime_ei-0.1.2/src/devtime/resources/demo-saas/src/auth/tokens.ts +11 -0
  17. devtime_ei-0.1.2/src/devtime/resources/demo-saas/src/billing/stripe-webhook.ts +25 -0
  18. devtime_ei-0.1.2/src/devtime/resources/demo-saas/src/billing/subscription-service.ts +11 -0
  19. devtime_ei-0.1.2/src/devtime/resources/demo-saas/src/export/export-csv.ts +14 -0
  20. devtime_ei-0.1.2/src/devtime/resources/demo-saas/src/jobs/email-worker.ts +16 -0
  21. devtime_ei-0.1.2/src/devtime/resources/demo-saas/src/jobs/queues.ts +6 -0
  22. devtime_ei-0.1.2/src/devtime/resources/demo-saas/tests/auth-login.test.ts +10 -0
  23. devtime_ei-0.1.2/src/devtime/resources/demo-saas/tests/stripe-signature.test.ts +8 -0
  24. {devtime_ei-0.1.0 → devtime_ei-0.1.2}/src/devtime_ei.egg-info/PKG-INFO +113 -30
  25. {devtime_ei-0.1.0 → devtime_ei-0.1.2}/src/devtime_ei.egg-info/SOURCES.txt +17 -0
  26. {devtime_ei-0.1.0 → devtime_ei-0.1.2}/src/devtime_ei.egg-info/requires.txt +4 -0
  27. devtime_ei-0.1.0/src/devtime/mcp/server.py +0 -35
  28. {devtime_ei-0.1.0 → devtime_ei-0.1.2}/LICENSE +0 -0
  29. {devtime_ei-0.1.0 → devtime_ei-0.1.2}/setup.cfg +0 -0
  30. {devtime_ei-0.1.0 → devtime_ei-0.1.2}/src/devtime/ai/__init__.py +0 -0
  31. {devtime_ei-0.1.0 → devtime_ei-0.1.2}/src/devtime/ai/local.py +0 -0
  32. {devtime_ei-0.1.0 → devtime_ei-0.1.2}/src/devtime/ai/prompts.py +0 -0
  33. {devtime_ei-0.1.0 → devtime_ei-0.1.2}/src/devtime/ai/providers.py +0 -0
  34. {devtime_ei-0.1.0 → devtime_ei-0.1.2}/src/devtime/assets/devtimeignore.starter +0 -0
  35. {devtime_ei-0.1.0 → devtime_ei-0.1.2}/src/devtime/config.py +0 -0
  36. {devtime_ei-0.1.0 → devtime_ei-0.1.2}/src/devtime/db/__init__.py +0 -0
  37. {devtime_ei-0.1.0 → devtime_ei-0.1.2}/src/devtime/db/connection.py +0 -0
  38. {devtime_ei-0.1.0 → devtime_ei-0.1.2}/src/devtime/db/migrations.py +0 -0
  39. {devtime_ei-0.1.0 → devtime_ei-0.1.2}/src/devtime/db/repository.py +0 -0
  40. {devtime_ei-0.1.0 → devtime_ei-0.1.2}/src/devtime/db/schema.sql +0 -0
  41. {devtime_ei-0.1.0 → devtime_ei-0.1.2}/src/devtime/fixtures/__init__.py +0 -0
  42. {devtime_ei-0.1.0 → devtime_ei-0.1.2}/src/devtime/fixtures/assertions.py +0 -0
  43. {devtime_ei-0.1.0 → devtime_ei-0.1.2}/src/devtime/fixtures/loader.py +0 -0
  44. {devtime_ei-0.1.0 → devtime_ei-0.1.2}/src/devtime/fixtures/runner.py +0 -0
  45. {devtime_ei-0.1.0 → devtime_ei-0.1.2}/src/devtime/intelligence/__init__.py +0 -0
  46. {devtime_ei-0.1.0 → devtime_ei-0.1.2}/src/devtime/intelligence/claims.py +0 -0
  47. {devtime_ei-0.1.0 → devtime_ei-0.1.2}/src/devtime/intelligence/concepts.py +0 -0
  48. {devtime_ei-0.1.0 → devtime_ei-0.1.2}/src/devtime/intelligence/context_pack.py +0 -0
  49. {devtime_ei-0.1.0 → devtime_ei-0.1.2}/src/devtime/intelligence/evidence.py +0 -0
  50. {devtime_ei-0.1.0 → devtime_ei-0.1.2}/src/devtime/intelligence/lineage.py +0 -0
  51. {devtime_ei-0.1.0 → devtime_ei-0.1.2}/src/devtime/intelligence/risk.py +0 -0
  52. {devtime_ei-0.1.0 → devtime_ei-0.1.2}/src/devtime/intelligence/scoring.py +0 -0
  53. {devtime_ei-0.1.0 → devtime_ei-0.1.2}/src/devtime/mcp/__init__.py +0 -0
  54. {devtime_ei-0.1.0 → devtime_ei-0.1.2}/src/devtime/mcp/schemas.py +0 -0
  55. {devtime_ei-0.1.0 → devtime_ei-0.1.2}/src/devtime/mcp/tools.py +0 -0
  56. {devtime_ei-0.1.0 → devtime_ei-0.1.2}/src/devtime/output/__init__.py +0 -0
  57. {devtime_ei-0.1.0 → devtime_ei-0.1.2}/src/devtime/output/json_export.py +0 -0
  58. {devtime_ei-0.1.0 → devtime_ei-0.1.2}/src/devtime/output/markdown.py +0 -0
  59. {devtime_ei-0.1.0 → devtime_ei-0.1.2}/src/devtime/output/terminal.py +0 -0
  60. {devtime_ei-0.1.0 → devtime_ei-0.1.2}/src/devtime/paths.py +0 -0
  61. {devtime_ei-0.1.0 → devtime_ei-0.1.2}/src/devtime/privacy.py +0 -0
  62. {devtime_ei-0.1.0 → devtime_ei-0.1.2}/src/devtime/scanner/__init__.py +0 -0
  63. {devtime_ei-0.1.0 → devtime_ei-0.1.2}/src/devtime/scanner/extractors/__init__.py +0 -0
  64. {devtime_ei-0.1.0 → devtime_ei-0.1.2}/src/devtime/scanner/extractors/base.py +0 -0
  65. {devtime_ei-0.1.0 → devtime_ei-0.1.2}/src/devtime/scanner/extractors/config_files.py +0 -0
  66. {devtime_ei-0.1.0 → devtime_ei-0.1.2}/src/devtime/scanner/extractors/docs.py +0 -0
  67. {devtime_ei-0.1.0 → devtime_ei-0.1.2}/src/devtime/scanner/extractors/nextjs.py +0 -0
  68. {devtime_ei-0.1.0 → devtime_ei-0.1.2}/src/devtime/scanner/extractors/python.py +0 -0
  69. {devtime_ei-0.1.0 → devtime_ei-0.1.2}/src/devtime/scanner/extractors/tests.py +0 -0
  70. {devtime_ei-0.1.0 → devtime_ei-0.1.2}/src/devtime/scanner/extractors/typescript.py +0 -0
  71. {devtime_ei-0.1.0 → devtime_ei-0.1.2}/src/devtime/scanner/file_walker.py +0 -0
  72. {devtime_ei-0.1.0 → devtime_ei-0.1.2}/src/devtime/scanner/ignore.py +0 -0
  73. {devtime_ei-0.1.0 → devtime_ei-0.1.2}/src/devtime/scanner/language.py +0 -0
  74. {devtime_ei-0.1.0 → devtime_ei-0.1.2}/src/devtime/scanner/signals.py +0 -0
  75. {devtime_ei-0.1.0 → devtime_ei-0.1.2}/src/devtime_ei.egg-info/dependency_links.txt +0 -0
  76. {devtime_ei-0.1.0 → devtime_ei-0.1.2}/src/devtime_ei.egg-info/entry_points.txt +0 -0
  77. {devtime_ei-0.1.0 → devtime_ei-0.1.2}/src/devtime_ei.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: devtime-ei
3
- Version: 0.1.0
3
+ Version: 0.1.2
4
4
  Summary: Local-first Engineering Intelligence for software repositories
5
5
  Author-email: Aviad Shakargi <aviad94@gmail.com>
6
6
  Maintainer-email: Aviad Shakargi <aviad94@gmail.com>
@@ -8,7 +8,7 @@ License: Apache-2.0
8
8
  Project-URL: Homepage, https://github.com/Shakargy/devtime
9
9
  Project-URL: Repository, https://github.com/Shakargy/devtime
10
10
  Project-URL: Issues, https://github.com/Shakargy/devtime/issues
11
- Project-URL: Release Notes, https://github.com/Shakargy/devtime/releases/tag/v0.1.0
11
+ Project-URL: Release Notes, https://github.com/Shakargy/devtime/releases/tag/v0.1.2
12
12
  Project-URL: Demo, https://youtu.be/1Hiu3Y9J_SI
13
13
  Keywords: devtools,cli,static-analysis,repository-analysis,engineering-intelligence,local-first
14
14
  Classifier: Development Status :: 3 - Alpha
@@ -30,8 +30,11 @@ Requires-Dist: pydantic>=2.7
30
30
  Requires-Dist: sqlalchemy>=2.0
31
31
  Requires-Dist: pyyaml>=6.0
32
32
  Requires-Dist: pathspec>=0.12
33
+ Provides-Extra: mcp
34
+ Requires-Dist: mcp>=1.2; extra == "mcp"
33
35
  Provides-Extra: dev
34
36
  Requires-Dist: pytest>=8.0; extra == "dev"
37
+ Requires-Dist: mcp>=1.2; extra == "dev"
35
38
  Dynamic: license-file
36
39
 
37
40
  # DevTime
@@ -46,16 +49,32 @@ risky changes.
46
49
 
47
50
  > No cloud. No telemetry. No code execution. No AI required.
48
51
 
49
- [![DevTime demo - Repository memory from evidence](assets/devtime-demo-thumbnail-v0.1.0.png)](https://youtu.be/1Hiu3Y9J_SI)
52
+ ![DevTime terminal demo - install, scan, and explain a repo from evidence](assets/devtime-terminal-demo.svg)
50
53
 
51
- Watch the 2-minute demo: DevTime scans a repo locally, explains concepts from
52
- evidence, surfaces uncertainty, catches a risky diff, and shows how a corroborated
53
- decision improves understanding.
54
+ Prefer video? [Watch the 2-minute demo](https://youtu.be/1Hiu3Y9J_SI): DevTime scans
55
+ a repo locally, explains concepts from evidence, surfaces uncertainty, catches a
56
+ risky diff, and shows how a corroborated decision improves understanding.
54
57
 
55
58
  ---
56
59
 
57
60
  ## Try DevTime in 60 seconds
58
61
 
62
+ ```bash
63
+ pipx install devtime-ei
64
+ dtc demo init
65
+ cd devtime-demo-saas
66
+ dtc init
67
+ dtc scan
68
+ dtc concepts
69
+ dtc explain "Billing Webhooks"
70
+ ```
71
+
72
+ The PyPI distribution is `devtime-ei`. The Python package remains `devtime`, and the
73
+ CLI command remains `dtc`. `dtc demo init` copies a small static example repo into
74
+ `./devtime-demo-saas` so you can try DevTime without cloning this repository.
75
+
76
+ ### From source
77
+
59
78
  ```bash
60
79
  git clone https://github.com/Shakargy/devtime.git
61
80
  cd devtime
@@ -98,27 +117,36 @@ steps) is in **[DEMO_SCRIPT.md](DEMO_SCRIPT.md)**.
98
117
 
99
118
  ## Why this exists
100
119
 
101
- Git remembers code. It does not remember understanding. It does not tell you why a
102
- behavior exists, what evidence supports it, or what nobody has decided yet. As AI
103
- tools generate code faster than teams can review it, that missing understanding
104
- becomes the bottleneck.
120
+ Git records what changed, but it does not preserve the reasoning behind those
121
+ changes. When you return to a repository - or review one you did not write - you often
122
+ have to reconstruct why a behavior exists, what evidence supports it, and what is
123
+ still uncertain.
105
124
 
106
- DevTime builds evidence-backed repository memory: a local layer that says what a
107
- repository can prove, and - just as importantly - what it cannot prove yet.
125
+ DevTime builds evidence-backed repository memory: a local layer that helps a
126
+ codebase explain itself from code, tests, configs, routes, and recorded decisions.
127
+ It shows what the repository can support with evidence - and, just as importantly,
128
+ what it cannot support yet.
108
129
 
109
130
  ## Who it is for
110
131
 
111
- DevTime is for developers reviewing unfamiliar code, teams using AI coding tools, and
112
- maintainers who want repository understanding to be backed by evidence instead of
113
- generated summaries.
132
+ DevTime is for people who need to understand a repository from evidence rather than
133
+ memory.
134
+
135
+ It is especially useful if you:
136
+
137
+ - are onboarding to an unfamiliar codebase and need to understand how a feature is implemented;
138
+ - are reviewing a pull request and want to see what evidence supports a behavior;
139
+ - are returning to a project after weeks or months and cannot remember why something exists;
140
+ - maintain a long-lived project where design decisions are easily lost;
141
+ - want repository understanding to be backed by code and recorded decisions instead of generated summaries.
114
142
 
115
- It is useful when you want to ask:
143
+ Questions DevTime helps answer include:
116
144
 
117
- - where is authentication actually implemented?
118
- - what files prove that billing webhooks exist?
119
- - what is still uncertain?
120
- - did this diff touch a risky concept?
121
- - is there a decision explaining this behavior?
145
+ - Where is authentication actually implemented?
146
+ - What files prove that Billing Webhooks exist?
147
+ - What is still uncertain?
148
+ - Did this diff touch a risky concept?
149
+ - Is there a decision explaining this behavior?
122
150
 
123
151
  ## What DevTime does
124
152
 
@@ -178,14 +206,75 @@ Anything outside these six is out of scope for V0. See [LIMITATIONS.md](LIMITATI
178
206
  | `dtc decision add` | Add a local decision record that can reduce uncertainty. |
179
207
 
180
208
  (Also available: `dtc evidence`, `dtc debt`, `dtc status`, `dtc doctor --privacy`,
181
- `dtc export`, `dtc reset`.)
209
+ `dtc export`, `dtc reset`, `dtc mcp start`.)
182
210
 
183
211
  Requires **Python >= 3.11** and git. See **[QUICKSTART.md](QUICKSTART.md)** for a
184
212
  step-by-step first run and troubleshooting.
185
213
 
214
+ ## Use with coding agents (MCP)
215
+
216
+ Your coding agent starts every session amnesiac about your repository and then
217
+ guesses, confidently. DevTime gives it memory it can trust: a local, read-only MCP
218
+ server that answers only with claims the repository can prove, plus explicit
219
+ uncertainty for what it cannot.
220
+
221
+ Install with MCP support and scan your repo:
222
+
223
+ ```bash
224
+ pipx install "devtime-ei[mcp]"
225
+ cd your-repo
226
+ dtc init
227
+ dtc scan
228
+ ```
229
+
230
+ Add DevTime to Claude Code:
231
+
232
+ ```bash
233
+ claude mcp add devtime -- dtc mcp start
234
+ ```
235
+
236
+ Or in any MCP client that reads `.mcp.json`:
237
+
238
+ ```json
239
+ {
240
+ "mcpServers": {
241
+ "devtime": {
242
+ "command": "dtc",
243
+ "args": ["mcp", "start"]
244
+ }
245
+ }
246
+ }
247
+ ```
248
+
249
+ The agent gets three read-only tools: `list_concepts`, `explain_concept`, and
250
+ `get_context_pack` (governed context with do-not-change-without-review paths, tests
251
+ to run, and agent guidance). Local stdio only - no network listener, no write tools,
252
+ no source code returned, only evidence file paths.
253
+
254
+ DevTime is listed in the official MCP Registry as `io.github.shakargy/devtime`.
255
+
256
+ <!-- mcp-name: io.github.shakargy/devtime -->
257
+
186
258
  ## Installation
187
259
 
188
- Recommended source install for now:
260
+ Recommended: install from PyPI with [pipx](https://pipx.pypa.io/) so the `dtc`
261
+ command is available on your PATH in an isolated environment:
262
+
263
+ ```bash
264
+ pipx install devtime-ei
265
+ ```
266
+
267
+ Or with pip:
268
+
269
+ ```bash
270
+ pip install devtime-ei
271
+ ```
272
+
273
+ The PyPI distribution is `devtime-ei`. The Python package remains `devtime`, and the
274
+ CLI command remains `dtc`. After installing, run `dtc demo init` to create a local
275
+ example repo to try it on.
276
+
277
+ ### From source
189
278
 
190
279
  ```bash
191
280
  git clone https://github.com/Shakargy/devtime.git
@@ -205,12 +294,6 @@ python -m venv .venv
205
294
  pip install -e ".[dev]"
206
295
  ```
207
296
 
208
- Planned PyPI install (after the package is published and verified):
209
-
210
- ```bash
211
- pipx install devtime
212
- ```
213
-
214
297
  ## Example output
215
298
 
216
299
  ```
@@ -274,7 +357,7 @@ intentionally not built yet - in **[LIMITATIONS.md](LIMITATIONS.md)**.
274
357
  ## Roadmap
275
358
 
276
359
  This is an early, local-first V0 focused on being trustworthy before being large.
277
- Not yet built (intentionally): git-history signals, wired MCP transport, an AI
360
+ Not yet built (intentionally): git-history signals, write-enabled MCP tools, an AI
278
361
  provider, a UI, and any cloud/team/enterprise features. See **[ROADMAP.md](ROADMAP.md)**.
279
362
 
280
363
  ## Contributing
@@ -10,16 +10,32 @@ risky changes.
10
10
 
11
11
  > No cloud. No telemetry. No code execution. No AI required.
12
12
 
13
- [![DevTime demo - Repository memory from evidence](assets/devtime-demo-thumbnail-v0.1.0.png)](https://youtu.be/1Hiu3Y9J_SI)
13
+ ![DevTime terminal demo - install, scan, and explain a repo from evidence](assets/devtime-terminal-demo.svg)
14
14
 
15
- Watch the 2-minute demo: DevTime scans a repo locally, explains concepts from
16
- evidence, surfaces uncertainty, catches a risky diff, and shows how a corroborated
17
- decision improves understanding.
15
+ Prefer video? [Watch the 2-minute demo](https://youtu.be/1Hiu3Y9J_SI): DevTime scans
16
+ a repo locally, explains concepts from evidence, surfaces uncertainty, catches a
17
+ risky diff, and shows how a corroborated decision improves understanding.
18
18
 
19
19
  ---
20
20
 
21
21
  ## Try DevTime in 60 seconds
22
22
 
23
+ ```bash
24
+ pipx install devtime-ei
25
+ dtc demo init
26
+ cd devtime-demo-saas
27
+ dtc init
28
+ dtc scan
29
+ dtc concepts
30
+ dtc explain "Billing Webhooks"
31
+ ```
32
+
33
+ The PyPI distribution is `devtime-ei`. The Python package remains `devtime`, and the
34
+ CLI command remains `dtc`. `dtc demo init` copies a small static example repo into
35
+ `./devtime-demo-saas` so you can try DevTime without cloning this repository.
36
+
37
+ ### From source
38
+
23
39
  ```bash
24
40
  git clone https://github.com/Shakargy/devtime.git
25
41
  cd devtime
@@ -62,27 +78,36 @@ steps) is in **[DEMO_SCRIPT.md](DEMO_SCRIPT.md)**.
62
78
 
63
79
  ## Why this exists
64
80
 
65
- Git remembers code. It does not remember understanding. It does not tell you why a
66
- behavior exists, what evidence supports it, or what nobody has decided yet. As AI
67
- tools generate code faster than teams can review it, that missing understanding
68
- becomes the bottleneck.
81
+ Git records what changed, but it does not preserve the reasoning behind those
82
+ changes. When you return to a repository - or review one you did not write - you often
83
+ have to reconstruct why a behavior exists, what evidence supports it, and what is
84
+ still uncertain.
69
85
 
70
- DevTime builds evidence-backed repository memory: a local layer that says what a
71
- repository can prove, and - just as importantly - what it cannot prove yet.
86
+ DevTime builds evidence-backed repository memory: a local layer that helps a
87
+ codebase explain itself from code, tests, configs, routes, and recorded decisions.
88
+ It shows what the repository can support with evidence - and, just as importantly,
89
+ what it cannot support yet.
72
90
 
73
91
  ## Who it is for
74
92
 
75
- DevTime is for developers reviewing unfamiliar code, teams using AI coding tools, and
76
- maintainers who want repository understanding to be backed by evidence instead of
77
- generated summaries.
93
+ DevTime is for people who need to understand a repository from evidence rather than
94
+ memory.
95
+
96
+ It is especially useful if you:
97
+
98
+ - are onboarding to an unfamiliar codebase and need to understand how a feature is implemented;
99
+ - are reviewing a pull request and want to see what evidence supports a behavior;
100
+ - are returning to a project after weeks or months and cannot remember why something exists;
101
+ - maintain a long-lived project where design decisions are easily lost;
102
+ - want repository understanding to be backed by code and recorded decisions instead of generated summaries.
78
103
 
79
- It is useful when you want to ask:
104
+ Questions DevTime helps answer include:
80
105
 
81
- - where is authentication actually implemented?
82
- - what files prove that billing webhooks exist?
83
- - what is still uncertain?
84
- - did this diff touch a risky concept?
85
- - is there a decision explaining this behavior?
106
+ - Where is authentication actually implemented?
107
+ - What files prove that Billing Webhooks exist?
108
+ - What is still uncertain?
109
+ - Did this diff touch a risky concept?
110
+ - Is there a decision explaining this behavior?
86
111
 
87
112
  ## What DevTime does
88
113
 
@@ -142,14 +167,75 @@ Anything outside these six is out of scope for V0. See [LIMITATIONS.md](LIMITATI
142
167
  | `dtc decision add` | Add a local decision record that can reduce uncertainty. |
143
168
 
144
169
  (Also available: `dtc evidence`, `dtc debt`, `dtc status`, `dtc doctor --privacy`,
145
- `dtc export`, `dtc reset`.)
170
+ `dtc export`, `dtc reset`, `dtc mcp start`.)
146
171
 
147
172
  Requires **Python >= 3.11** and git. See **[QUICKSTART.md](QUICKSTART.md)** for a
148
173
  step-by-step first run and troubleshooting.
149
174
 
175
+ ## Use with coding agents (MCP)
176
+
177
+ Your coding agent starts every session amnesiac about your repository and then
178
+ guesses, confidently. DevTime gives it memory it can trust: a local, read-only MCP
179
+ server that answers only with claims the repository can prove, plus explicit
180
+ uncertainty for what it cannot.
181
+
182
+ Install with MCP support and scan your repo:
183
+
184
+ ```bash
185
+ pipx install "devtime-ei[mcp]"
186
+ cd your-repo
187
+ dtc init
188
+ dtc scan
189
+ ```
190
+
191
+ Add DevTime to Claude Code:
192
+
193
+ ```bash
194
+ claude mcp add devtime -- dtc mcp start
195
+ ```
196
+
197
+ Or in any MCP client that reads `.mcp.json`:
198
+
199
+ ```json
200
+ {
201
+ "mcpServers": {
202
+ "devtime": {
203
+ "command": "dtc",
204
+ "args": ["mcp", "start"]
205
+ }
206
+ }
207
+ }
208
+ ```
209
+
210
+ The agent gets three read-only tools: `list_concepts`, `explain_concept`, and
211
+ `get_context_pack` (governed context with do-not-change-without-review paths, tests
212
+ to run, and agent guidance). Local stdio only - no network listener, no write tools,
213
+ no source code returned, only evidence file paths.
214
+
215
+ DevTime is listed in the official MCP Registry as `io.github.shakargy/devtime`.
216
+
217
+ <!-- mcp-name: io.github.shakargy/devtime -->
218
+
150
219
  ## Installation
151
220
 
152
- Recommended source install for now:
221
+ Recommended: install from PyPI with [pipx](https://pipx.pypa.io/) so the `dtc`
222
+ command is available on your PATH in an isolated environment:
223
+
224
+ ```bash
225
+ pipx install devtime-ei
226
+ ```
227
+
228
+ Or with pip:
229
+
230
+ ```bash
231
+ pip install devtime-ei
232
+ ```
233
+
234
+ The PyPI distribution is `devtime-ei`. The Python package remains `devtime`, and the
235
+ CLI command remains `dtc`. After installing, run `dtc demo init` to create a local
236
+ example repo to try it on.
237
+
238
+ ### From source
153
239
 
154
240
  ```bash
155
241
  git clone https://github.com/Shakargy/devtime.git
@@ -169,12 +255,6 @@ python -m venv .venv
169
255
  pip install -e ".[dev]"
170
256
  ```
171
257
 
172
- Planned PyPI install (after the package is published and verified):
173
-
174
- ```bash
175
- pipx install devtime
176
- ```
177
-
178
258
  ## Example output
179
259
 
180
260
  ```
@@ -238,7 +318,7 @@ intentionally not built yet - in **[LIMITATIONS.md](LIMITATIONS.md)**.
238
318
  ## Roadmap
239
319
 
240
320
  This is an early, local-first V0 focused on being trustworthy before being large.
241
- Not yet built (intentionally): git-history signals, wired MCP transport, an AI
321
+ Not yet built (intentionally): git-history signals, write-enabled MCP tools, an AI
242
322
  provider, a UI, and any cloud/team/enterprise features. See **[ROADMAP.md](ROADMAP.md)**.
243
323
 
244
324
  ## Contributing
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "devtime-ei"
3
- version = "0.1.0"
3
+ version = "0.1.2"
4
4
  description = "Local-first Engineering Intelligence for software repositories"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -37,15 +37,20 @@ dependencies = [
37
37
  ]
38
38
 
39
39
  [project.optional-dependencies]
40
+ # Read-only MCP stdio server for coding agents (dtc mcp start).
41
+ mcp = [
42
+ "mcp>=1.2",
43
+ ]
40
44
  dev = [
41
45
  "pytest>=8.0",
46
+ "mcp>=1.2",
42
47
  ]
43
48
 
44
49
  [project.urls]
45
50
  Homepage = "https://github.com/Shakargy/devtime"
46
51
  Repository = "https://github.com/Shakargy/devtime"
47
52
  Issues = "https://github.com/Shakargy/devtime/issues"
48
- "Release Notes" = "https://github.com/Shakargy/devtime/releases/tag/v0.1.0"
53
+ "Release Notes" = "https://github.com/Shakargy/devtime/releases/tag/v0.1.2"
49
54
  Demo = "https://youtu.be/1Hiu3Y9J_SI"
50
55
 
51
56
  [project.scripts]
@@ -59,8 +64,15 @@ build-backend = "setuptools.build_meta"
59
64
  where = ["src"]
60
65
 
61
66
  # Non-Python runtime files that ship inside the package (read at runtime).
67
+ # The demo-saas resource is copied out by `dtc demo init`; the leading-dot
68
+ # .devtimeignore is listed explicitly because glob `*` does not match dotfiles.
62
69
  [tool.setuptools.package-data]
63
- devtime = ["db/*.sql", "assets/*"]
70
+ devtime = [
71
+ "db/*.sql",
72
+ "assets/*",
73
+ "resources/demo-saas/**/*",
74
+ "resources/demo-saas/.devtimeignore",
75
+ ]
64
76
 
65
77
  [tool.pytest.ini_options]
66
78
  testpaths = ["tests"]
@@ -1,6 +1,6 @@
1
1
  """DevTime - local-first Engineering Intelligence for repository memory."""
2
2
 
3
- __version__ = "0.1.0"
3
+ __version__ = "0.1.2"
4
4
 
5
5
  # Version metadata (Builder Edition, Chapter 20).
6
6
  EVIDENCE_MODEL = "2026.06.1"
@@ -24,9 +24,13 @@ console = Console()
24
24
  claim_app = typer.Typer(help="Inspect and govern claims.")
25
25
  decision_app = typer.Typer(help="Record human decisions.")
26
26
  mcp_app = typer.Typer(help="Local read-only MCP server.")
27
+ demo_app = typer.Typer(
28
+ help="Create a local copy of the bundled demo repository.", no_args_is_help=True
29
+ )
27
30
  app.add_typer(claim_app, name="claim")
28
31
  app.add_typer(decision_app, name="decision")
29
32
  app.add_typer(mcp_app, name="mcp")
33
+ app.add_typer(demo_app, name="demo")
30
34
 
31
35
 
32
36
  # --------------------------------------------------------------------------- #
@@ -43,6 +47,37 @@ def init() -> None:
43
47
  console.print("AI disabled. Cloud disabled. Telemetry off. MCP read-only.")
44
48
 
45
49
 
50
+ @demo_app.command("init")
51
+ def demo_init(
52
+ force: bool = typer.Option(
53
+ False, "--force", help="Replace devtime-demo-saas if it already exists."
54
+ ),
55
+ ) -> None:
56
+ """Copy the bundled demo repository into ./devtime-demo-saas (static files only)."""
57
+ from devtime.demo import DEMO_DIR_NAME, DemoExistsError, create_demo
58
+
59
+ try:
60
+ create_demo(Path.cwd(), force=force)
61
+ except DemoExistsError as exc:
62
+ console.print(
63
+ f"[yellow]{DEMO_DIR_NAME}/ already exists[/yellow] at {exc.path}."
64
+ )
65
+ console.print(
66
+ "Use [bold]dtc demo init --force[/bold] to replace it, "
67
+ "or remove the directory first."
68
+ )
69
+ raise typer.Exit(code=1)
70
+
71
+ console.print(f"[green]Demo repository created[/green] at ./{DEMO_DIR_NAME}")
72
+ console.print("")
73
+ console.print("Next:")
74
+ console.print(f" cd {DEMO_DIR_NAME}")
75
+ console.print(" dtc init")
76
+ console.print(" dtc scan")
77
+ console.print(" dtc concepts")
78
+ console.print(' dtc explain "Billing Webhooks"')
79
+
80
+
46
81
  @app.command()
47
82
  def status() -> None:
48
83
  """Show local storage, AI, cloud, telemetry, MCP, and scan status."""
@@ -306,20 +341,33 @@ def decision_add(
306
341
 
307
342
  @mcp_app.command("start")
308
343
  def mcp_start() -> None:
309
- """Preview planned read-only MCP tools. Does NOT start a server in V0."""
310
- from devtime.mcp.server import describe_server
344
+ """Start the local read-only MCP server over stdio (for coding agents)."""
345
+ # stdout belongs to the JSON-RPC stream: all diagnostics go to stderr.
346
+ err = Console(stderr=True)
347
+
348
+ if not paths.is_initialized():
349
+ err.print("[red]DevTime is not initialized here.[/red]")
350
+ err.print("Run [bold]dtc init[/bold] and [bold]dtc scan[/bold] in the repository first.")
351
+ raise typer.Exit(code=2)
352
+
353
+ from devtime.mcp.transport import McpDependencyMissing, run_stdio
311
354
 
312
- console.print(describe_server())
313
- # Honest exit: nothing was started, so a command named "start" returns nonzero.
314
- raise typer.Exit(code=1)
355
+ err.print("DevTime MCP server: stdio, read-only, local only. Ctrl+C to stop.")
356
+ try:
357
+ run_stdio()
358
+ except McpDependencyMissing as exc:
359
+ # markup=False: the hint contains [mcp], which rich would eat as a tag.
360
+ err.print(str(exc), markup=False, style="red")
361
+ raise typer.Exit(code=1)
315
362
 
316
363
 
317
364
  @mcp_app.command("preview")
318
365
  def mcp_preview() -> None:
319
- """Preview planned read-only MCP tools (transport not implemented in V0)."""
366
+ """Show implemented and planned read-only MCP tools."""
320
367
  from devtime.mcp.server import describe_server
321
368
 
322
- console.print(describe_server())
369
+ # markup=False: the text contains [mcp], which rich would eat as a tag.
370
+ console.print(describe_server(), markup=False)
323
371
 
324
372
 
325
373
  @mcp_app.command("status")
@@ -0,0 +1,75 @@
1
+ """Bundled demo repository support for `dtc demo init`.
2
+
3
+ This lets people who installed DevTime from PyPI (`pipx install devtime-ei`) try it
4
+ without cloning the source repository. It copies a small, static example repo that
5
+ ships inside the installed package into the current working directory.
6
+
7
+ It only copies static files. It never executes code, never installs anything, never
8
+ runs tests or migrations, and never touches the network. Nothing leaves the machine.
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ import shutil
14
+ from importlib import resources
15
+ from pathlib import Path
16
+
17
+ # Directory name created in the current working directory.
18
+ DEMO_DIR_NAME = "devtime-demo-saas"
19
+
20
+ # The packaged demo lives at src/devtime/resources/demo-saas/ and ships in the wheel
21
+ # via [tool.setuptools.package-data].
22
+ _RESOURCE_SUBPATH = ("resources", "demo-saas")
23
+
24
+ # Artifacts that must never end up in a copied demo, stripped defensively after copy.
25
+ _FORBIDDEN_DIRS = {".devtime", ".git", "node_modules", "__pycache__", ".cache"}
26
+ _FORBIDDEN_FILE_SUFFIXES = (".sqlite", ".sqlite3", ".db")
27
+
28
+
29
+ class DemoExistsError(Exception):
30
+ """Raised when the demo directory already exists and force was not requested."""
31
+
32
+ def __init__(self, path: Path) -> None:
33
+ self.path = path
34
+ super().__init__(str(path))
35
+
36
+
37
+ def packaged_demo_source() -> Path:
38
+ """Return a filesystem path to the demo directory bundled in the package."""
39
+ root = resources.files("devtime")
40
+ source = root.joinpath(*_RESOURCE_SUBPATH)
41
+ # In a normal wheel/editable install this is already a real path on disk.
42
+ return Path(str(source))
43
+
44
+
45
+ def _strip_forbidden(dest: Path) -> None:
46
+ """Remove any artifacts that must never be part of a shared demo."""
47
+ for path in sorted(dest.rglob("*"), reverse=True):
48
+ if path.is_dir() and path.name in _FORBIDDEN_DIRS:
49
+ shutil.rmtree(path, ignore_errors=True)
50
+ elif path.is_file() and path.suffix.lower() in _FORBIDDEN_FILE_SUFFIXES:
51
+ path.unlink(missing_ok=True)
52
+
53
+
54
+ def create_demo(dest_parent: Path, *, force: bool = False) -> Path:
55
+ """Copy the bundled demo into ``dest_parent/devtime-demo-saas``.
56
+
57
+ Writes only inside ``dest_parent``. Returns the created directory path.
58
+ Raises :class:`DemoExistsError` if the destination exists and ``force`` is False.
59
+ """
60
+ dest = dest_parent / DEMO_DIR_NAME
61
+ if dest.exists():
62
+ if not force:
63
+ raise DemoExistsError(dest)
64
+ shutil.rmtree(dest)
65
+
66
+ source = packaged_demo_source()
67
+ if not source.is_dir():
68
+ raise FileNotFoundError(f"Bundled demo not found at {source}")
69
+
70
+ # as_file guarantees a real filesystem path even if the package were zipped.
71
+ with resources.as_file(resources.files("devtime").joinpath(*_RESOURCE_SUBPATH)) as src_path:
72
+ shutil.copytree(src_path, dest)
73
+
74
+ _strip_forbidden(dest)
75
+ return dest
@@ -0,0 +1,42 @@
1
+ """MCP server description (Builder Edition, Chapter 16).
2
+
3
+ v0.1.2: the stdio transport is implemented for the read-only tool subset in
4
+ devtime.mcp.transport. The remaining planned tools stay listed as planned so
5
+ the preview output never overclaims.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import json
11
+
12
+ from devtime.mcp import schemas
13
+ from devtime.mcp.transport import IMPLEMENTED_TOOLS
14
+
15
+
16
+ def describe_server() -> str:
17
+ """Honest preview: implemented tools are separated from planned ones."""
18
+ planned_read = [t for t in schemas.TOOLS["read"] if t not in IMPLEMENTED_TOOLS]
19
+ planned_context = [t for t in schemas.TOOLS["context"] if t not in IMPLEMENTED_TOOLS]
20
+ lines = [
21
+ "MCP transport: stdio, read-only, local only.",
22
+ 'Requires the optional dependency: pip install "devtime-ei[mcp]"',
23
+ "Start with: dtc mcp start (stdout is the protocol stream).",
24
+ "",
25
+ "Implemented tools:",
26
+ ]
27
+ lines += [f" - {t}" for t in IMPLEMENTED_TOOLS]
28
+ lines += ["Planned read tools (not implemented yet):"]
29
+ lines += [f" - {t}" for t in planned_read]
30
+ lines += ["Planned context tools (not implemented yet):"]
31
+ lines += [f" - {t}" for t in planned_context]
32
+ lines += ["Planned review tools (not implemented yet):"]
33
+ lines += [f" - {t}" for t in schemas.TOOLS["review"]]
34
+ lines += [
35
+ "",
36
+ "Write tools are not exposed. No network listener. No source code is returned.",
37
+ ]
38
+ return "\n".join(lines)
39
+
40
+
41
+ def describe_permissions() -> str:
42
+ return json.dumps(schemas.DEFAULT_PERMISSIONS, indent=2)