git-arc
v1.1.0
Published
Git-native decentralized task tracker.
Maintainers
Readme
git-arc
Git-native decentralized task tracker. All state lives inside Git objects under refs/tracker/main, completely separate from your branches, working tree, and CI. Tasks form a directed acyclic graph with typed edges, synced between repositories via standard git push/git fetch.
Requirements
- Node.js >= 22.14.0
- Git >= 2.38 (
git merge-tree --write-treesupport) - Self-hosted Git server for server-side validation (GitHub/GitLab SaaS do not support custom pre-receive hooks)
Install
npm install -g git-arcQuick start
# Initialize the tracker in an existing repo
git arc init
# Create tasks
git arc task create "Design authentication flow"
git arc task create "Implement login endpoint"
# Link tasks with directed edges
git arc edge add blocks <task-a-id> <task-b-id>
# Add comments
git arc comment add <task-id> "Decided to use JWT"
# Sync with remote
git arc push
git arc pullCommands
Core
| Command | Description |
| ----------------------- | ------------------------------------------------- |
| git arc init | Initialize the tracker, configure fetch refspec |
| git arc validate | Check all invariants against the current tree |
| git arc push [remote] | Validate locally, then push to remote |
| git arc pull [remote] | Fetch, fast-forward or 3-way merge reconciliation |
Tasks
| Command | Description |
| ----------------------------- | ----------------------------------------------------------------- |
| git arc task create <title> | Create a task (-p priority, -b body) |
| git arc task list | List tasks (-a includes deleted) |
| git arc task show <id> | Show task details |
| git arc task update <id> | Update fields (-t title, -s status, -p priority, -b body) |
| git arc task delete <id> | Soft-delete (tombstone) |
Edges
| Command | Description |
| ---------------------------------------- | ----------------------------------------------- |
| git arc edge add <type> <from> <to> | Add a directed edge (e.g. blocks) |
| git arc edge remove <type> <from> <to> | Remove an edge |
| git arc edge list | List edges (--from, --to, --type filters) |
Comments
| Command | Description |
| ----------------------------------------------- | ------------------------------------- |
| git arc comment add <task-id> <body> | Add a comment to a task |
| git arc comment list <task-id> | List comments (-a includes deleted) |
| git arc comment delete <task-id> <comment-id> | Soft-delete (tombstone) |
Storage model
All data is stored as Git objects under refs/tracker/main. No working-tree checkout is needed — reads and writes use Git plumbing (ls-tree, hash-object, mktree, commit-tree, update-ref).
tasks/
<uuid>.md # YAML frontmatter + Markdown body
edges/
<type>__<from>__<to> # Zero-byte file, identity encoded in filename
comments/
<task-id>/
<uuid>.md # Markdown body, optional frontmatter for deletion- Tasks and comments are soft-deleted (tombstoned with
deleted: truein frontmatter) - Edges are hard-deleted (file removed)
- IDs are UUID v7 (lexicographic order = chronological order)
Validation
Four invariants are enforced both client-side (git arc validate, git arc push) and server-side (pre-receive hook):
- Parse validity — all files parse as valid YAML frontmatter + Markdown
- Referential integrity — all edges and comments reference existing tasks
- DAG acyclicity — no cycles among non-deleted tasks
- Edge uniqueness — no duplicate
(type, from, to)tuples
Sync
Pushes must be fast-forward. When two agents diverge, git arc pull reconciles via git merge-tree --write-tree (3-way merge), validates the result, and commits. The agent then pushes again.
Server-side validation (pre-receive hook)
Install a pre-receive hook on your bare repository to enforce invariants on every push:
# In your bare repo
cat > hooks/pre-receive << 'EOF'
#!/bin/sh
exec git-arc hook pre-receive
EOF
chmod +x hooks/pre-receiveThe hook validates the proposed tree for any push targeting refs/tracker/main. Invalid state (dangling references, cycles, parse errors) is rejected with descriptive error messages. Deletion of the tracker ref is also rejected.
