spec-agent 0.1.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.
- spec_agent-0.1.0/LICENSE +21 -0
- spec_agent-0.1.0/PKG-INFO +390 -0
- spec_agent-0.1.0/README.md +356 -0
- spec_agent-0.1.0/pyproject.toml +65 -0
- spec_agent-0.1.0/setup.cfg +4 -0
- spec_agent-0.1.0/spec_agent/__init__.py +1 -0
- spec_agent-0.1.0/spec_agent/agent.py +174 -0
- spec_agent-0.1.0/spec_agent/cli.py +157 -0
- spec_agent-0.1.0/spec_agent/config.py +59 -0
- spec_agent-0.1.0/spec_agent/tools/__init__.py +1 -0
- spec_agent-0.1.0/spec_agent/tools/wiki_index.py +31 -0
- spec_agent-0.1.0/spec_agent/tools/wiki_read.py +37 -0
- spec_agent-0.1.0/spec_agent/tools/wiki_search.py +71 -0
- spec_agent-0.1.0/spec_agent/tools/wiki_write.py +38 -0
- spec_agent-0.1.0/spec_agent.egg-info/PKG-INFO +390 -0
- spec_agent-0.1.0/spec_agent.egg-info/SOURCES.txt +24 -0
- spec_agent-0.1.0/spec_agent.egg-info/dependency_links.txt +1 -0
- spec_agent-0.1.0/spec_agent.egg-info/entry_points.txt +2 -0
- spec_agent-0.1.0/spec_agent.egg-info/requires.txt +9 -0
- spec_agent-0.1.0/spec_agent.egg-info/top_level.txt +1 -0
- spec_agent-0.1.0/tests/test_agent.py +104 -0
- spec_agent-0.1.0/tests/test_config.py +66 -0
- spec_agent-0.1.0/tests/test_wiki_index.py +47 -0
- spec_agent-0.1.0/tests/test_wiki_read.py +33 -0
- spec_agent-0.1.0/tests/test_wiki_search.py +44 -0
- spec_agent-0.1.0/tests/test_wiki_write.py +43 -0
spec_agent-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Vishesh Chaitanya
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: spec-agent
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Auto-generate an Obsidian knowledge wiki from every git push, powered by Claude
|
|
5
|
+
Author-email: Vishesh Chaitanya <visheshchaitanya@gmail.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/visheshchaitanya/spec-agent
|
|
8
|
+
Project-URL: Repository, https://github.com/visheshchaitanya/spec-agent
|
|
9
|
+
Project-URL: Issues, https://github.com/visheshchaitanya/spec-agent/issues
|
|
10
|
+
Keywords: obsidian,wiki,git,documentation,anthropic,claude,ai,developer-tools
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Topic :: Software Development :: Documentation
|
|
20
|
+
Classifier: Topic :: Software Development :: Version Control :: Git
|
|
21
|
+
Classifier: Topic :: Utilities
|
|
22
|
+
Requires-Python: >=3.11
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
License-File: LICENSE
|
|
25
|
+
Requires-Dist: anthropic>=0.40.0
|
|
26
|
+
Requires-Dist: click>=8.1
|
|
27
|
+
Requires-Dist: pyyaml>=6.0
|
|
28
|
+
Requires-Dist: python-frontmatter>=1.1
|
|
29
|
+
Requires-Dist: rich>=13.0
|
|
30
|
+
Provides-Extra: dev
|
|
31
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
32
|
+
Requires-Dist: pytest-cov>=5.0; extra == "dev"
|
|
33
|
+
Dynamic: license-file
|
|
34
|
+
|
|
35
|
+
# spec-agent
|
|
36
|
+
|
|
37
|
+
> Auto-generate an Obsidian knowledge wiki from every `git push` — powered by Claude.
|
|
38
|
+
|
|
39
|
+
Every time you push code, **spec-agent** reads the diff, classifies the change, and writes a structured spec document into your [Obsidian](https://obsidian.md) vault. Over time, your vault becomes a living, visually-navigable graph of everything you've ever built.
|
|
40
|
+
|
|
41
|
+
Inspired by [Andrej Karpathy's LLM Wiki pattern](https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f): the LLM acts as a compiler (raw commits → structured wiki), not a retrieval engine. No RAG, no embeddings — just well-organized markdown with `[[wikilinks]]` that Obsidian renders as a knowledge graph.
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## How It Works
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
git push
|
|
49
|
+
└── ~/.git-hooks/post-push ← global hook, fires on every repo
|
|
50
|
+
└── spec-agent run ← Python CLI
|
|
51
|
+
└── Claude (tool-use) ← agentic loop
|
|
52
|
+
├── classify_commit
|
|
53
|
+
├── search_wiki ← finds related existing pages
|
|
54
|
+
├── read_wiki_file ← reads context before updating
|
|
55
|
+
├── write_wiki_file ← creates or updates spec
|
|
56
|
+
└── update_index ← appends row to index.md
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
The agent:
|
|
60
|
+
1. Classifies the commit type (`feature`, `bug`, `refactor`, `arch`, `chore`)
|
|
61
|
+
2. Searches your vault for related pages to link to
|
|
62
|
+
3. Writes an adaptive spec using the appropriate template
|
|
63
|
+
4. Updates `index.md` — the master log that Claude reads at session start
|
|
64
|
+
|
|
65
|
+
**Chore commits are skipped.** Bot branches (`dependabot/*`, `renovate/*`) are skipped. Tiny commits (below a configurable character threshold) are skipped.
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Features
|
|
70
|
+
|
|
71
|
+
- **Zero friction** — fires automatically on every `git push`, no developer action needed
|
|
72
|
+
- **Adaptive templates** — selects the right format based on commit type
|
|
73
|
+
- `feature` → full spec (summary, problem, implementation, files, open questions)
|
|
74
|
+
- `bug` → short report (root cause, fix applied)
|
|
75
|
+
- `refactor` → brief note (what changed, why, before/after)
|
|
76
|
+
- `arch` → ADR format (context, decision, consequences, alternatives)
|
|
77
|
+
- **Accurate `[[wikilinks]]`** — searches vault for existing pages before writing, so links are real
|
|
78
|
+
- **Living index** — `index.md` is a table of every spec ever written; share it with Claude at session start to give it full project memory
|
|
79
|
+
- **Obsidian graph** — concepts referenced by many specs become visual hubs after 10+ specs
|
|
80
|
+
- **Works on every repo** — one global hook installation covers all your projects
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## Prerequisites
|
|
85
|
+
|
|
86
|
+
- **Python 3.11+**
|
|
87
|
+
- **An Anthropic API key** — [get one here](https://console.anthropic.com)
|
|
88
|
+
- **Obsidian** — [download here](https://obsidian.md) (free)
|
|
89
|
+
- **Git 2.9+** (for `core.hooksPath` support)
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## Installation
|
|
94
|
+
|
|
95
|
+
### From PyPI (recommended)
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
pip install spec-agent
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### From source
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
git clone https://github.com/visheshchaitanya/spec-agent.git ~/.spec-agent
|
|
105
|
+
pip install -e ~/.spec-agent
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## Setup
|
|
111
|
+
|
|
112
|
+
### 1. Set your API key
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
export ANTHROPIC_API_KEY="sk-ant-..."
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Add this to your shell profile (`~/.zshrc`, `~/.bashrc`, or `~/.zshenv`) to make it permanent:
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
echo 'export ANTHROPIC_API_KEY="sk-ant-..."' >> ~/.zshrc
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### 2. Initialize your vault
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
spec-agent init --vault ~/Documents/dev-wiki
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
This creates the vault directory structure and writes a default `~/.spec-agent/config.yaml`.
|
|
131
|
+
|
|
132
|
+
Then open `~/Documents/dev-wiki` as a vault in Obsidian (**File → Open vault as folder**).
|
|
133
|
+
|
|
134
|
+
### 3. Install the global git hook
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
spec-agent install-hook
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
This creates `~/.git-hooks/post-push` and sets `git config --global core.hooksPath ~/.git-hooks`. The hook fires on every push in every repository on your machine.
|
|
141
|
+
|
|
142
|
+
### 4. Push anything to test
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
cd ~/any-repo
|
|
146
|
+
git push
|
|
147
|
+
# → spec-agent fires in the background
|
|
148
|
+
# → spec appears in ~/Documents/dev-wiki
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## Configuration
|
|
154
|
+
|
|
155
|
+
Config lives at `~/.spec-agent/config.yaml`:
|
|
156
|
+
|
|
157
|
+
```yaml
|
|
158
|
+
vault_path: ~/Documents/dev-wiki
|
|
159
|
+
model: claude-sonnet-4-6
|
|
160
|
+
ignored_repos: [] # list of repo names to skip entirely
|
|
161
|
+
ignored_branches:
|
|
162
|
+
- dependabot/*
|
|
163
|
+
- renovate/*
|
|
164
|
+
min_commit_chars: 50 # skip pushes where total commit message length is below this
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
| Key | Default | Description |
|
|
168
|
+
|-----|---------|-------------|
|
|
169
|
+
| `vault_path` | `~/Documents/dev-wiki` | Absolute path to your Obsidian vault |
|
|
170
|
+
| `model` | `claude-sonnet-4-6` | Anthropic model to use |
|
|
171
|
+
| `ignored_repos` | `[]` | Exact repo names to never process |
|
|
172
|
+
| `ignored_branches` | `[dependabot/*, renovate/*]` | Glob patterns — matching branches are skipped |
|
|
173
|
+
| `min_commit_chars` | `50` | Skip pushes where total commit message length is below this (filters "wip", "fix typo") |
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
## Vault Structure
|
|
178
|
+
|
|
179
|
+
```
|
|
180
|
+
~/Documents/dev-wiki/
|
|
181
|
+
├── index.md ← master log — give this to Claude at session start
|
|
182
|
+
├── features/
|
|
183
|
+
│ ├── alert-ingestion.md
|
|
184
|
+
│ └── auth-system.md
|
|
185
|
+
├── bugs/
|
|
186
|
+
│ ├── fix-status-migration.md
|
|
187
|
+
│ └── fix-null-pointer.md
|
|
188
|
+
├── refactors/
|
|
189
|
+
│ └── extract-auth-middleware.md
|
|
190
|
+
├── concepts/ ← auto-created graph hubs when first referenced
|
|
191
|
+
│ ├── clickhouse.md
|
|
192
|
+
│ └── jwt.md
|
|
193
|
+
└── projects/
|
|
194
|
+
└── my-app.md
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### index.md — your project memory
|
|
198
|
+
|
|
199
|
+
`index.md` is a markdown table of every spec ever written:
|
|
200
|
+
|
|
201
|
+
```markdown
|
|
202
|
+
# Dev Wiki — Index
|
|
203
|
+
|
|
204
|
+
| Date | Type | Title | Project | Link |
|
|
205
|
+
|------|------|-------|---------|------|
|
|
206
|
+
| 2026-04-07 | bug | Fix status migration | my-app | [[bugs/fix-status-migration]] |
|
|
207
|
+
| 2026-04-05 | feature | Alert ingestion pipeline | my-app | [[features/alert-ingestion]] |
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
Paste the contents of `index.md` at the start of any Claude session — Claude immediately knows everything you've built across all projects.
|
|
211
|
+
|
|
212
|
+
### Spec frontmatter
|
|
213
|
+
|
|
214
|
+
Every generated spec has YAML frontmatter:
|
|
215
|
+
|
|
216
|
+
```yaml
|
|
217
|
+
---
|
|
218
|
+
type: feature
|
|
219
|
+
project: my-app
|
|
220
|
+
date: 2026-04-07
|
|
221
|
+
commit: a3f9c12
|
|
222
|
+
status: shipped
|
|
223
|
+
---
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
---
|
|
227
|
+
|
|
228
|
+
## Giving Claude context at session start
|
|
229
|
+
|
|
230
|
+
Paste this into your Claude session to give it full project memory:
|
|
231
|
+
|
|
232
|
+
```
|
|
233
|
+
Here is my dev wiki index — everything I've built:
|
|
234
|
+
|
|
235
|
+
<paste contents of ~/Documents/dev-wiki/index.md>
|
|
236
|
+
|
|
237
|
+
I'm working on <task>. Based on the index, what related specs should I look at?
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
Claude can then ask you to paste specific spec files for deeper context.
|
|
241
|
+
|
|
242
|
+
---
|
|
243
|
+
|
|
244
|
+
## CLI Reference
|
|
245
|
+
|
|
246
|
+
```
|
|
247
|
+
spec-agent [COMMAND] [OPTIONS]
|
|
248
|
+
|
|
249
|
+
Commands:
|
|
250
|
+
run Run the agent (called automatically by git hook)
|
|
251
|
+
init Initialize vault directory and write config
|
|
252
|
+
install-hook Install global git post-push hook
|
|
253
|
+
config-get Read a config value (used internally by hook)
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### `spec-agent run`
|
|
257
|
+
|
|
258
|
+
```
|
|
259
|
+
Options:
|
|
260
|
+
--repo TEXT Repository name (required)
|
|
261
|
+
--branch TEXT Branch that was pushed (required)
|
|
262
|
+
--messages TEXT Newline-separated commit messages (required)
|
|
263
|
+
--diff-file TEXT Path to temp file containing the git diff (required)
|
|
264
|
+
--config TEXT Path to config.yaml [default: ~/.spec-agent/config.yaml]
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
### `spec-agent init`
|
|
268
|
+
|
|
269
|
+
```
|
|
270
|
+
Options:
|
|
271
|
+
--vault TEXT Path to Obsidian vault directory (required)
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
### `spec-agent install-hook`
|
|
275
|
+
|
|
276
|
+
No options. Installs `~/.git-hooks/post-push` and sets the global git hooks path.
|
|
277
|
+
|
|
278
|
+
---
|
|
279
|
+
|
|
280
|
+
## Manual run (without pushing)
|
|
281
|
+
|
|
282
|
+
You can run the agent manually against any repo:
|
|
283
|
+
|
|
284
|
+
```bash
|
|
285
|
+
DIFF_FILE=$(mktemp /tmp/spec-agent-diff.XXXXXX)
|
|
286
|
+
git diff HEAD~1..HEAD | head -c 50000 > "$DIFF_FILE"
|
|
287
|
+
|
|
288
|
+
spec-agent run \
|
|
289
|
+
--repo "$(basename $(pwd))" \
|
|
290
|
+
--branch "$(git rev-parse --abbrev-ref HEAD)" \
|
|
291
|
+
--messages "$(git log HEAD~1..HEAD --format='%s')" \
|
|
292
|
+
--diff-file "$DIFF_FILE"
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
---
|
|
296
|
+
|
|
297
|
+
## Per-repo opt-out
|
|
298
|
+
|
|
299
|
+
To exclude a specific repo from spec generation, add its name to `ignored_repos` in `~/.spec-agent/config.yaml`:
|
|
300
|
+
|
|
301
|
+
```yaml
|
|
302
|
+
ignored_repos:
|
|
303
|
+
- my-private-repo
|
|
304
|
+
- dotfiles
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
---
|
|
308
|
+
|
|
309
|
+
## Development
|
|
310
|
+
|
|
311
|
+
### Requirements
|
|
312
|
+
|
|
313
|
+
```bash
|
|
314
|
+
git clone https://github.com/visheshchaitanya/spec-agent.git
|
|
315
|
+
cd spec-agent
|
|
316
|
+
pip install -e ".[dev]"
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
### Run tests
|
|
320
|
+
|
|
321
|
+
```bash
|
|
322
|
+
pytest
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
### Run tests with coverage
|
|
326
|
+
|
|
327
|
+
```bash
|
|
328
|
+
pytest --cov=spec_agent --cov-report=term-missing
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
All tests use temporary directories — no vault or API key required.
|
|
332
|
+
|
|
333
|
+
---
|
|
334
|
+
|
|
335
|
+
## Architecture
|
|
336
|
+
|
|
337
|
+
### Tool-using agent loop
|
|
338
|
+
|
|
339
|
+
The agent runs an Anthropic `messages.create` loop until `stop_reason == "end_turn"`:
|
|
340
|
+
|
|
341
|
+
```
|
|
342
|
+
client.messages.create(tools=TOOL_DEFINITIONS, ...)
|
|
343
|
+
→ stop_reason == "tool_use"
|
|
344
|
+
→ dispatch tool, collect results
|
|
345
|
+
→ append assistant + user messages
|
|
346
|
+
→ loop
|
|
347
|
+
→ stop_reason == "end_turn"
|
|
348
|
+
→ done
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
### Tools
|
|
352
|
+
|
|
353
|
+
| Tool | Purpose |
|
|
354
|
+
|------|---------|
|
|
355
|
+
| `classify_commit` | Agent classifies diff type and extracts concepts (no-op server-side — agent reasons internally) |
|
|
356
|
+
| `search_wiki` | Full-text search across vault using `grep -r` — finds related pages for wikilinks |
|
|
357
|
+
| `read_wiki_file` | Reads existing spec file — enables update mode instead of duplicate creation |
|
|
358
|
+
| `write_wiki_file` | Writes markdown to vault; `mode=update` appends a dated changelog section |
|
|
359
|
+
| `update_index` | Appends row to `index.md` master log |
|
|
360
|
+
|
|
361
|
+
### Diff safety
|
|
362
|
+
|
|
363
|
+
Git diffs larger than 50,000 characters are truncated before being passed to the agent. The diff is passed via a temp file (not shell arguments) to avoid escaping issues with special characters.
|
|
364
|
+
|
|
365
|
+
---
|
|
366
|
+
|
|
367
|
+
## Roadmap
|
|
368
|
+
|
|
369
|
+
- [ ] GitHub webhook / cloud daemon (replace local hook with HTTP POST)
|
|
370
|
+
- [ ] Multi-agent parallel processing (Classifier + Writer + Linker)
|
|
371
|
+
- [ ] Obsidian Dataview dashboards
|
|
372
|
+
- [ ] Per-project vault paths
|
|
373
|
+
- [ ] Slack/email notifications on spec creation
|
|
374
|
+
|
|
375
|
+
---
|
|
376
|
+
|
|
377
|
+
## Contributing
|
|
378
|
+
|
|
379
|
+
Pull requests welcome. Please:
|
|
380
|
+
|
|
381
|
+
1. Fork the repo and create a branch from `main`
|
|
382
|
+
2. Add tests for any new behavior
|
|
383
|
+
3. Ensure `pytest` passes
|
|
384
|
+
4. Open a pull request
|
|
385
|
+
|
|
386
|
+
---
|
|
387
|
+
|
|
388
|
+
## License
|
|
389
|
+
|
|
390
|
+
[MIT](LICENSE) — © 2026 Vishesh Chaitanya
|