Git-native project management with AI audit trails. A lightweight alternative to Jira and Confluence where every issue, wiki page, and board lives as plain files in your repo.
If you use AI coding assistants (like Claude Code), you've probably hit these pain points:
- "What did AI do yesterday?" — You asked Claude to fix something last week. It worked. But now you have no idea what it changed or why.
- "It broke again, but I don't remember the fix" — A bug you fixed with AI three weeks ago is back. You can't remember what the solution was, and
git logjust says "fix bug". - "Pick up where AI left off" — You started a feature with Claude, got interrupted, came back days later. Claude has no memory of what it was doing or what decisions were made.
- "I can't verify what AI did" — Your AI assistant made changes across 12 files. You approved them. Now something's wrong and you need to understand the reasoning behind each change.
- "Jira costs $1,000+/month and doesn't talk to my AI" — You're paying for project management tools that your AI assistant can't even read or write to.
Drop a .project/ folder into any git repo. Claude Code automatically:
- Creates a ticket before starting any work
- Documents every step — what it changed, why, which files, what decisions it made
- Updates the wiki with functional docs, technical docs, and decision records
- Links tickets to commits so you can trace any change back to its reasoning
Everything is plain Markdown and JSON. No database. No SaaS. No vendor lock-in. Just files in your repo.
# From inside any git repo:
curl -sL https://raw.githubusercontent.com/rpostulart/Claude-Project-Tracker/main/init.sh | bash
# Or with options:
./init.sh --prefix MYAPP --email me@example.com --slug rp --name "My Project"
# Update an existing installation to the latest version:
curl -sL https://raw.githubusercontent.com/rpostulart/Claude-Project-Tracker/main/init.sh | bash -s -- --updateThe installer prompts for your email and a unique slug (2-4 lowercase letters, e.g. rp). The slug is used in issue IDs to prevent collisions when multiple team members work independently.
This creates:
.project/— issues, wiki, boards, skills, per-user counters (committed to git).claude/skills/— slash commands for Claude CodeCLAUDE.md— instructions that make Claude Code track all work automatically.env— your email, slug, and server config (gitignored)
Once installed, Claude Code tracks everything without you asking:
You: "Fix the login timeout bug"
Claude: 1. Creates MYAPP-rp-1: "Fix login timeout bug"
2. Sets status to in-progress
3. Adds comments as it works:
- "Investigating: timeout happens in auth.ts line 42"
- "Root cause: token refresh waits for expired session"
- "Fixed by adding early return on expired tokens"
- "Modified: src/auth.ts, src/middleware.ts"
4. Updates wiki: Functional + Technical docs
5. Commits with: fix(auth): resolve login timeout [MYAPP-rp-1]
6. Marks ticket as done
Three weeks later...
You: "The login is broken again, check MYAPP-rp-1"
Claude: Reads the full ticket history
Sees exactly what was done, which files, what the root cause was
Picks up where it left off with full context
A visual interface for the same data — no separate tool needed:
# Requires Deno (https://deno.land)
deno run --allow-net --allow-read --allow-write --allow-env .project/server.ts
# Open http://localhost:8000- Kanban board — drag-and-drop issues between columns, time filter on Done
- List view — sortable, filterable table with date range and pagination
- Issue detail — markdown descriptions, comments, subtasks, related issues (clickable, bidirectional), labels, priority
- Wiki — nested pages with tree navigation, search, WYSIWYG editing, copy-to-clipboard for export
- Skills — create and edit Claude Code skills from the browser
Add wiki pages under "Steering Files" to control how Claude works in your project:
- Coding Standards — "Use TypeScript strict mode, Tailwind for CSS"
- Architecture — "All API endpoints return { data, error } envelope"
- Conventions — "Use snake_case for DB columns, camelCase for JS"
Claude reads these before every task and follows them.
| Command | What it does |
|---|---|
/create-issue <title> |
Create a new tracked issue |
/update-status <ID> <status> |
Move an issue (backlog/todo/in-progress/review/done) |
/add-comment <ID> <text> |
Add a comment to an issue |
/track-work <ID or title> |
Start working with full audit trail |
/review-ticket <ID> |
Read a ticket's complete history |
/standup |
Summarize recent activity across issues and commits |
/wiki-update <title> |
Create or update a wiki page |
/document-completion <ID> |
Auto-document completed work in the wiki |
/rebuild-index |
Rebuild issues index from issue files |
/bump-version |
Bump the tracker VERSION (semver) — run after changes that ship to consumer installs |
The tracker installs two Claude Code hooks that enforce the workflow automatically. These run at the harness level, so they can't be forgotten or ignored, even in long conversations.
| Hook | Trigger | What it does |
|---|---|---|
require-issue.sh |
Every Edit/Write | Reminds Claude to decide if an issue is needed. Blocks once, then allows if Claude decides it's trivial. |
require-docs.sh |
Marking issue as done | Blocks setting status to "done" unless wiki docs exist or issue has "skip-docs" label. |
check-version.sh |
Session start (max 1× / 24h) | Compares local .project/VERSION against upstream. Silent when up-to-date (zero token cost); on mismatch, asks the user whether to run init.sh --update. |
How it feels in practice:
You: "add a contact form"
Claude: → tries to edit → hook asks "do you need an issue?"
Claude: → creates issue, sets in-progress → continues working
...implements...
Claude: "I've completed the form. Shall I mark PROJ-rp-3 as done?"
You: "yes"
Claude: → writes wiki docs (functional/technical/decisions) → marks done ✅
You: "fix the typo on line 12"
Claude: → hook asks "do you need an issue?"
Claude: → decides: trivial fix, no issue needed → fixes directly ✅
Hooks are installed in .claude/hooks/ and configured in .claude/settings.json. They skip .project/ files, .claude/ files, and config files automatically.
Every Claude Code turn loads CLAUDE.md and all skill description frontmatter before the user even types. On a naive install that "idle cost" adds up fast. The tracker is tuned so the always-loaded overhead stays small:
- Terse
CLAUDE.md+ on-demand steering page. Golden rules, one-line workflow, and the lookup order live in the always-loadedCLAUDE.md(~40 lines). Full detail — file formats, same-ticket-vs-new rules, description templates, sync commands — lives in.project/wiki/pages/steering-tracker-workflow.mdand is only read when a workflow question comes up. - Short skill descriptions. Each skill's frontmatter
descriptionis ≤15 words. No "Use when asked to..." padding. - Progressive comment loading.
/review-ticketand/track-workreadissue.json+description.md+ the last 3 comments first. Older comments load only when referenced or explicitly requested. Saves 500–3k tokens per invocation on long-lived tickets. - Index-only lookup. Skills use
issues_index.json, never a directory scan.
Baseline went from ~2.6k tokens per turn always-loaded to ~550. See the Context & Token Budget wiki page for the full breakdown.
The tracker ships a VERSION file and a SessionStart hook (.claude/hooks/check-version.sh) that compares the local version against upstream at most once every 24 hours. When they match, the hook is silent (no tokens consumed). When upstream has a newer version, Claude sees a one-line notice and asks you before running the update:
curl -sL https://raw.githubusercontent.com/rpostulart/Claude-Project-Tracker/main/init.sh | bash -s -- --updateTunable via env vars:
CLAUDE_PROJECT_VERSION_URL— point at your own fork'sVERSIONfile.CLAUDE_PROJECT_VERSION_THROTTLE— hours between checks (default24).
Existing installs pick up the hook on their next init.sh --update run; from then on, updates self-announce.
.project/
├── config.json # Project settings (prefix, statuses, team with slugs)
├── VERSION # Installed tracker version (compared to upstream by the update-check hook)
├── issues_index.json # Fast lookup index (auto-rebuilt on startup, gitignored)
├── counters/
│ └── rp.json # Per-user issue counter (one file per team member)
├── server.ts # Deno server (API + web UI)
├── ui/ # Web UI (vanilla JS, no build step)
├── issues/
│ └── PROJ-rp-1/
│ ├── issue.json # Status, priority, assignee, labels, related
│ ├── description.md # What was requested, acceptance criteria, wiki links
│ └── comments/
│ ├── 001.json # "Starting work on this issue"
│ ├── 002.json # "Changed auth.ts: added early return"
│ └── 003.json # "Documented in wiki"
├── wiki/
│ ├── _index.json # Page tree with parent/child nesting
│ └── pages/
│ ├── steering.md # Project conventions for AI
│ ├── functional/ # What features do (user perspective)
│ ├── technical/ # How things work (developer perspective)
│ └── decisions.md # Why choices were made
├── boards/
│ └── default.json # Kanban column definitions
└── skills/
├── create-issue/SKILL.md
├── track-work/SKILL.md
└── ... # 9 skills, synced to .claude/skills/
Each team member gets a unique 2-4 letter slug (e.g. rp) stored in .env (gitignored) and registered in config.json's team array. Issue IDs include the slug: PROJ-rp-1, PROJ-ab-1. Each user has their own counter file in .project/counters/, so different team members never conflict on issue creation — even when working offline.
The issues_index.json is gitignored and rebuilt automatically on server startup, eliminating a second source of merge conflicts.
The issues_index.json file contains a flat array of all issue metadata, sorted by most recently updated first. AI reads this single file instead of scanning every issue directory — much faster for finding recent issues, running standups, or searching for existing tickets. It's maintained automatically by the server and rebuilt on every startup.
Issues can link to each other via the related field in issue.json (e.g. "related": ["PROJ-rp-1"]). Links are bidirectional — if issue A links to B, the UI automatically shows the reverse link on B. Useful for connecting bugs to the features that introduced them.
- One folder per issue — atomic changes, no merge conflicts
- Per-user counters — each team member writes their own counter file, zero coordination needed
- Comments as individual files — append-only, conflict-free in teams
- Wiki nesting via
parentfield — unlimited depth, flat on disk - Everything in git —
git diffshows exactly what changed,git logis your audit trail - No database — works offline, no setup, no migrations
- AI-native — Claude Code reads/writes files directly, no API wrapper needed
| Method | Path | Description |
|---|---|---|
| GET | /api/config |
Project configuration |
| GET/POST | /api/issues |
List or create issues |
| GET/PUT/DELETE | /api/issues/:id |
Issue CRUD |
| PUT | /api/issues/:id/description |
Update description |
| POST | /api/issues/:id/comments |
Add comment |
| POST | /api/issues/rebuild-index |
Rebuild issues index |
| GET | /api/wiki |
Wiki page index |
| GET | /api/wiki/search?q= |
Search wiki content |
| GET/PUT/DELETE | /api/wiki/:slug |
Wiki page CRUD |
| GET/POST | /api/skills |
List skills / sync to .claude |
| GET/PUT/DELETE | /api/skills/:slug |
Skill CRUD |
| GET | /api/boards |
Board configurations |
MIT