Spec-driven development with ink — every decision, written permanently.
Project description
███████╗██████╗ ███████╗ ██████╗ ██╗███╗ ██╗██╗ ██╗
██╔════╝██╔══██╗██╔════╝██╔════╝ ██║████╗ ██║██║ ██╔╝
███████╗██████╔╝█████╗ ██║ ██║██╔██╗ ██║█████╔╝
╚════██║██╔═══╝ ██╔══╝ ██║ ██║██║╚██╗██║██╔═██╗
███████║██║ ███████╗╚██████╗ ██║██║ ╚████║██║ ██╗
╚══════╝╚═╝ ╚══════╝ ╚═════╝ ╚═╝╚═╝ ╚═══╝╚═╝ ╚═╝
Spec-driven development with ink — every decision, written permanently.
SpecInk adds the one thing missing from AI-assisted development: the ability to remember why.
The problem
You're using Claude Code (or Cursor, or Copilot). The code is good. The sessions are fast. But six months later you open a module and think:
Why is it done this way? What did we consider? Where is the reasoning?
It's gone. It lived in a chat thread that was cleared weeks ago.
Tools like OpenSpec solve the what — structured specs, proposals, task checklists. But nobody has solved the why.
SpecInk solves the why.
What SpecInk adds
SpecInk is a companion to the OpenSpec/SDD workflow. If you've never heard of Spec-Driven Development, the idea is simple: agree on what to build before any code is written, in a structured Markdown file that lives in your repo alongside the code.
SpecInk keeps the same loop — propose → apply → verify → archive — but adds four features that no existing tool has:
| Feature | What it does |
|---|---|
| Transcript logging | Appends AI session output to transcript.md inside each change folder. The reasoning is preserved. Forever. |
| Decision records | ink decision add captures what was decided, why, and what alternatives were rejected — in an ADR-lite format. |
| Drift detection | After archive, ink drift checks whether your code still matches what the spec said it would do. |
| Conflict preview | Before you start implementing, ink conflicts tells you if two active changes are touching the same spec sections. |
Install
pip install specink
Or with uv:
uv tool install specink
Requires Python 3.11+. No API keys. No SaaS. No database. Just Markdown files that live in your repo.
Quick start
# 1. Initialise in your project
cd my-project
ink init
# 2. Propose a change
ink propose add-dark-mode
# 3. Fill in the spec (your AI assistant can do this)
# .specink/changes/add-dark-mode/specs/spec.md
# 4. Check for conflicts with other active changes
ink conflicts
# 5. Implement the change (with your AI coding assistant)
ink apply add-dark-mode
# 6. Log the AI session transcript
echo "I used CSS variables on :root because..." | ink transcript append add-dark-mode
# 7. Record the key design decision
ink decision add add-dark-mode
# 8. Verify all tasks are done
ink verify add-dark-mode
# 9. Archive (runs drift check automatically)
ink archive add-dark-mode
How it works
Change folder anatomy
Every ink propose creates a structured folder:
.specink/changes/add-dark-mode/
├── proposal.md ← why we're doing this, what's in scope
├── specs/
│ └── spec.md ← BDD scenarios (GIVEN / WHEN / THEN)
├── design.md ← technical approach, constraints
├── tasks.md ← atomic implementation checklist
├── transcript.md ← AI conversation log ✦ new
└── decisions.md ← ADR-lite decision records ✦ new
Archived changes move to .specink/changes/archive/YYYY-MM-DD-add-dark-mode/. Nothing is deleted.
Transcript logging
After your AI session, pipe the key reasoning into the change:
ink transcript append add-dark-mode --speaker assistant
# (type or paste, then Ctrl+D)
# Or from a file
ink transcript append add-dark-mode --file session.txt
# Read it back
ink transcript show add-dark-mode
The transcript is append-only with automatic timestamps:
## 2025-01-23 14:32 — assistant
I chose CSS variables over Tailwind dark: prefix because the app needs
runtime switching without a rebuild. The ThemeProvider approach was
rejected because it adds a React dependency to a framework-agnostic module.
---
Three months later, when someone asks why aren't we using styled-components here, the answer is one command away.
Decision records
Capture any significant design decision in under a minute:
ink decision add add-dark-mode
? Decision title: Use CSS variables for theming
? What was decided: Store all color tokens as CSS custom properties on :root
? Why: Allows runtime switching without a rebuild
? Alternatives rejected: Tailwind dark: prefix, styled-components ThemeProvider
Saved to decisions.md in a format your team can read, diff, and link to in PRs.
Drift detection
Spec-to-code drift is silent and insidious. Six months after archiving a change, ink drift checks whether the code still matches what the spec said it would do:
ink drift add-dark-mode
Drift report for 'add-dark-mode' (archived 2025-01-20)
✓ ThemeProvider found in src/theme.ts
✓ useColorScheme found in src/hooks/useColorScheme.ts
✗ detectSystemPreference not found in any source file
⚠ toggleTheme found only in tests/
2 spec assertions may have drifted from implementation.
Run `ink drift add-dark-mode --verbose` for file references.
No LLM required. Pure text parsing — fast enough to run in CI.
Conflict preview
Before writing a line of code, know if two changes are going to fight each other at archive time:
ink conflicts
Active change conflict scan
add-dark-mode × add-theming
└─ specs/ui/spec.md § "Color system" (both modify)
└─ design.md § "CSS architecture" (both modify)
No conflicts in other active changes.
Tip: archive one change before applying the other.
Works with your AI assistant
SpecInk writes an AGENTS.md to your project root on ink init. Every AI coding assistant that reads this file (Claude Code, Cursor, Windsurf, GitHub Copilot) will know how to navigate your change folders, log transcripts, and record decisions — without you having to re-explain the workflow each session.
The file is yours to edit. It's just Markdown.
Command reference
ink init Initialise SpecInk in a project
ink propose <name> Create a new change proposal
ink apply [name] Mark a change as in progress
ink verify [name] Confirm all tasks are complete
ink archive [name] Archive a completed change
ink list Show all active changes
ink show <name> Show change details and artifact summary
ink status Git-style overview of all changes
ink transcript append <name> Append to AI transcript
ink transcript show <name> Display transcript with timestamps
ink decision add <name> Record an architectural decision
ink decision list <name> List all decisions for a change
ink drift [name] Check for spec-to-code drift
ink conflicts Scan active changes for spec conflicts
All commands accept --verbose / -v for detailed output.
FAQ
Does SpecInk call any LLM? No. Transcripts are written by you or your AI assistant — SpecInk just stores and displays them. Drift detection and conflict scanning are pure text parsing.
Does it replace OpenSpec? No. It's a different philosophy — SpecInk is a standalone Python CLI. If you're already using OpenSpec's slash commands in Cursor or Claude Code, SpecInk's drift and conflict features work alongside them (they both just read Markdown files).
Does it require a specific AI tool? No. It works with Claude Code, Cursor, Windsurf, Copilot, or any tool that can read files and run shell commands.
Can I use it in CI?
Yes. ink drift exits with code 1 if drift is detected, making it suitable as a CI check. All commands support --no-interaction for non-TTY environments.
Comparison
| SpecInk | OpenSpec | GitHub Spec Kit | Kiro | |
|---|---|---|---|---|
| Transcript logging | ✅ | ❌ | ❌ | ❌ |
| Decision records (ADR-lite) | ✅ | ❌ | ❌ | ❌ |
| Drift detection | ✅ | ❌ | ❌ | ❌ |
| Conflict preview | ✅ | ❌ (archive only) | ❌ | ❌ |
| Works with any AI tool | ✅ | ✅ | ✅ | ❌ (IDE lock-in) |
| No API key required | ✅ | ✅ | ✅ | ❌ |
| Python / pip install | ✅ | ❌ (Node.js) | ❌ (Python, heavy) | ❌ (IDE plugin) |
CI/CD & Deployment
The project uses GitHub Actions for continuous integration and deployment:
CI Workflow (runs on every push):
- Linting with
ruff - Type checking with
mypy - Tests with
pytest - Runs on Python 3.11 and 3.12
Release Workflow (runs on push to main):
- All CI checks
- Build package with
uv build - Publish to PyPI with
uv publish
To enable PyPI deployment:
- Generate a PyPI API token at https://pypi.org/manage/account/token/
- Add it as a repository secret named
PYPI_TOKENin GitHub Settings → Secrets and variables → Actions
Contributing
Contributions are welcome. Please read the contributing guide before opening a PR.
For larger features, run ink propose <feature-name> inside the SpecInk repo itself — it's only fair.
License
MIT — see LICENSE for details.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file specink-0.1.2.tar.gz.
File metadata
- Download URL: specink-0.1.2.tar.gz
- Upload date:
- Size: 57.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f5b4d663710e5e91cddda25087e38e0add4373aa92e31db896d9fc7e095ddf19
|
|
| MD5 |
855fca8176067292c967678c99df3010
|
|
| BLAKE2b-256 |
49362c93d8c1c9d6d8efe6c3369a9b998509d7670a30c6c99637e1ff4398cf87
|
File details
Details for the file specink-0.1.2-py3-none-any.whl.
File metadata
- Download URL: specink-0.1.2-py3-none-any.whl
- Upload date:
- Size: 24.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c08fa0846aaf8c4d9c5c70aa16b096cc24ac9966b632820df23212027acf32a0
|
|
| MD5 |
73d6c21ddbf0a36f0f32fb69074a8438
|
|
| BLAKE2b-256 |
b5a0201b0e9d2343fd852d592aaab7bbc258bbaf4860b7ebe7a291345e8d59b7
|