Help us shape the future of Go! Take the 2026 Go Developer Survey

links-issue-tracker

module
v0.23.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 19, 2026 License: MIT

README

An issue tracker that lives inside your git repo and is built for AI agents to drive.

links-issue-tracker — the CLI is lit — keeps your backlog in the repository, next to the code it describes. There's no server to run, no account to create, and no web app to keep in sync. Issues live in an embedded Dolt database, so every change to a ticket is a versioned, committed database mutation that travels with your code through the git remotes you already use.

It's designed so an autonomous coding agent can pull the next piece of work, claim it, finish it, and file follow-ups — coordinating with you and with other agents through one small, predictable CLI.

Why it's interesting

  • The backlog ships with the code. Clone the repo, get the issues. No external service, no drift between "what the tracker says" and "what the branch contains."
  • Every mutation is a commit. State is a Dolt database, so issue history is real, auditable version history — not an activity log bolted onto a SaaS.
  • Built agent-first. Commands like lit next, lit start, and lit done return guidance, not just data — the workflow an agent should follow is baked into the output.
  • One write boundary, one identity per clone. All worktrees of a clone share one issue view (keyed off git rev-parse --git-common-dir). You never edit the database by hand.
  • Minimal and deterministic. Inspired by beads, lit deliberately keeps a small surface area and prefers explicit errors over silent fallbacks.

Get started

Requirements
  • A git repository (or worktree)
  • git 2.36 or newer — lit enumerates a repository's worktrees with git worktree list --porcelain -z, and -z arrived in 2.36

lit ships prebuilt, self-contained binaries — no Go toolchain and no system ICU/zstd needed to run them. The dolt CLI isn't required either; the Dolt storage engine is compiled in.

Install

Install the latest release onto your PATH (downloads the right binary for your OS/arch, checksum-verified):

curl -fsSL https://raw.githubusercontent.com/promptctl/links-issue-tracker/master/scripts/install.sh | bash -s -- --latest-release
lit version

Prefer to grab the archive yourself, pin a version, or build from source? See docs/introduction/installation.md — it covers manual download, --from-release <tag>, and the Go build (the fallback for unsupported platforms or hacking on lit).

A 60-second tour

From inside any git repository:

lit init                                              # set up the workspace for this clone
lit new --title "Launch the site" \
        --topic landing --type epic                   # every ticket lives inside an epic
lit new --title "Build the landing page" \
        --topic landing --type task --parent <epic>   # file your first issue, inside it
lit backlog                                           # see what's workable, in priority order
lit start <id>                                        # claim a ticket
lit done <id>                                         # finish it (closes immediately)

lit init also wires this repo for agents: it adds a short lit section to AGENTS.md and CLAUDE.md telling any coding agent to run lit quickstart before touching work.

Pointing an AI agent at it

If you want an agent (Claude Code, Cursor, etc.) to do the work, give it docs/agent-setup.md — a concrete, copy-pasteable install + workspace-init + core-loop guide written for agents. In a repo that's already initialized, the agent's entry point is simply lit quickstart, which prints the live command reference.

Claude Code plugin

This repo is also a Claude Code plugin marketplace. Install it from any project — no local clone of links-issue-tracker needed:

/plugin marketplace add promptctl/links-issue-tracker
/plugin install lit@lit

That gets you the lit plugin: the /lit:next skill (pick up and start the next ticket). A plan reviewer, which follows lit quickstart review, needs the laws plugin (/plugin marketplace add promptctl/laws, then /plugin install laws@promptctl). For a team, wire lit into every clone instead of asking everyone to install it — add to the repo's .claude/settings.json:

{
  "extraKnownMarketplaces": {
    "lit": {
      "source": { "source": "github", "repo": "promptctl/links-issue-tracker" }
    }
  },
  "enabledPlugins": { "lit@lit": true }
}

How it works

  • Storage — issues are rows in an embedded Dolt SQL database under $(git rev-parse --git-common-dir)/links/. Each lit write validates input, updates rows in a transaction, and commits the working set, so local state is durable after every change.
  • Sync — lit sync mirrors that Dolt data through your existing git remotes; remote config is derived from git remote -v, so there's nothing extra to configure.
  • Automation — lit hooks install adds a shared pre-push hook (once per clone) that attempts a sync on push without ever blocking it.

More depth: docs/introduction/what-is-links.md · docs/concepts.md · docs/architecture.md.

Credit

links is directly inspired by beads by Steve Yegge. The core idea — treat issue tracking as part of the repository workflow so humans and agents coordinate through a fast local CLI and syncable state — is his. links is an independent implementation of that idea with a deliberately minimal, agent-native surface.

Contributing

See CONTRIBUTING.md for dev setup, the build/test/lint commands, and the branch & PR conventions.

Code of Conduct

This project follows the Code of Conduct.

Security

To report a vulnerability, see the Security Policy.

License

links is released under the MIT License.

Directories

Path Synopsis
cmd
lit command
internal
app
atomicfile
Package atomicfile replaces a file's contents atomically: the new contents are written to a temporary sibling and renamed over the target, so a reader sees the old file or the new one, never a torn write.
Package atomicfile replaces a file's contents atomically: the new contents are written to a temporary sibling and renamed over the target, so a reader sees the old file or the new one, never a torn write.
claims
Package claims derives, at read time, which checkout is working which lane.
Package claims derives, at read time, which checkout is working which lane.
cli
dbsnapshot
Package dbsnapshot takes filesystem-level snapshots of a Dolt storage directory using copy-on-write where available (APFS clonefile on Darwin, FICLONE on Linux) with a recursive-copy fallback.
Package dbsnapshot takes filesystem-level snapshots of a Dolt storage directory using copy-on-write where available (APFS clonefile on Darwin, FICLONE on Linux) with a recursive-copy fallback.
docclaims
Package docclaims ties the v1 specification's quoted messages to the code that actually ships them.
Package docclaims ties the v1 specification's quoted messages to the code that actually ships them.
docnames
Package docnames checks that every Go name the v1 specification writes in a code span is an identifier somewhere in this repository's source.
Package docnames checks that every Go name the v1 specification writes in a code span is an identifier somewhere in this repository's source.
docsclaims
Package docsclaims ties the repo's user-facing storage prose to the event-store migration state that will falsify it.
Package docsclaims ties the repo's user-facing storage prose to the event-store migration state that will falsify it.
engine
Package engine is the one place lit chooses which storage engine backs a workspace, and the only package outside internal/store that names the Dolt engine's construction surface.
Package engine is the one place lit chooses which storage engine backs a workspace, and the only package outside internal/store that names the Dolt engine's construction surface.
interrupt
Package interrupt owns a process's interrupt-shutdown lifecycle: it turns an operating-system interrupt (SIGINT/SIGTERM) into cancellation of a context, and — this is the load-bearing part — guarantees the process still terminates even when the work in flight ignores that cancellation.
Package interrupt owns a process's interrupt-shutdown lifecycle: it turns an operating-system interrupt (SIGINT/SIGTERM) into cancellation of a context, and — this is the load-bearing part — guarantees the process still terminates even when the work in flight ignores that cancellation.
lawtokens
Package lawtokens is the in-repo authority for the architectural-law marker convention.
Package lawtokens is the in-repo authority for the architectural-law marker convention.
lawtokens/tokenindex
Package tokenindex reads the architectural-law Token index out of its upstream document and renders it as the Go source of internal/lawtokens/canonical_gen.go.
Package tokenindex reads the architectural-law Token index out of its upstream document and renders it as the Go source of internal/lawtokens/canonical_gen.go.
model/lifecycle
Package lifecycle defines the internal lifecycle expression primitives used by model.Issue.
Package lifecycle defines the internal lifecycle expression primitives used by model.Issue.
pathspec
Package pathspec carries a possibly-absent filesystem path as a value.
Package pathspec carries a possibly-absent filesystem path as a value.
precedence
Package precedence resolves ordered fallback chains: the first candidate that carries a value wins.
Package precedence resolves ordered fallback chains: the first candidate that carries a value wins.
rank
Package rank implements lexicographic fractional indexing for work item ordering.
Package rank implements lexicographic fractional indexing for work item ordering.
release
Package release defines the per-release artifact manifest.
Package release defines the per-release artifact manifest.
statusline
Package statusline keeps .lit/statusline.json, one file per checkout saying what that checkout is working on and what `lit next` would pick for it, so a terminal statusline can show both without running lit.
Package statusline keeps .lit/statusline.json, one file per checkout saying what that checkout is working on and what `lit next` would pick for it, so a terminal statusline can show both without running lit.
storage
Package storage is lit's storage contract: what lit needs from a storage engine, stated in the model's vocabulary, with no engine anywhere in the signatures.
Package storage is lit's storage contract: what lit needs from a storage engine, stated in the model's vocabulary, with no engine anywhere in the signatures.
storage/conformance
Package conformance is the executable meaning of lit's storage contract.
Package conformance is the executable meaning of lit's storage contract.
storage/memory
Package memory implements lit's storage contract with nothing but Go values: no SQL, no disk, no schema, no engine artifact of any kind.
Package memory implements lit's storage contract with nothing but Go values: no SQL, no disk, no schema, no engine artifact of any kind.
storage/storagetest
Package storagetest holds fixtures that build workspace shapes through the storage.Store contract, for tests in any package that holds a store.
Package storagetest holds fixtures that build workspace shapes through the storage.Store contract, for tests in any package that holds a store.
store
Package store owns lit's workspace state in an embedded Dolt database: opening and closing it, mutating it under locks, and minting every lit-owned lock path but the config lock (see below).
Package store owns lit's workspace state in an embedded Dolt database: opening and closing it, mutating it under locks, and minting every lit-owned lock path but the config lock (see below).
store/migrations
Package migrations holds the goose changeset registry for the links schema.
Package migrations holds the goose changeset registry for the links schema.
telemetry
Package telemetry builds the one wide event each lit invocation leaves: a single structured record of what ran, how it ended, and the facts the command decided along the way.
Package telemetry builds the one wide event each lit invocation leaves: a single structured record of what ran, how it ended, and the facts the command decided along the way.
testoracle
Package testoracle locates the external CLIs the test suite uses as oracles — independent checkers such as `claude` whose verdict a test trusts over its own reading of the code — for the tests that skip when their oracle is missing.
Package testoracle locates the external CLIs the test suite uses as oracles — independent checkers such as `claude` whose verdict a test trusts over its own reading of the code — for the tests that skip when their oracle is missing.
trace
Package trace is the one place a durable, timestamped JSON trace record is written to disk.
Package trace is the one place a durable, timestamped JSON trace record is written to disk.
version
Package version is the single source of truth for "what binary am I and what can I do." It exposes a typed Info value carrying the binary's identity (link-time-injected version/commit/build-date/origin) plus its capability bounds (the schema-version range it can produce, derived from the embedded migration registry).
Package version is the single source of truth for "what binary am I and what can I do." It exposes a typed Info value carrying the binary's identity (link-time-injected version/commit/build-date/origin) plus its capability bounds (the schema-version range it can produce, derived from the embedded migration registry).
workflows
Package workflows is the definition model for `lit workflows`: user-authored guidance that lit injects into agent-facing output at declared work-lifecycle moments.
Package workflows is the definition model for `lit workflows`: user-authored guidance that lit injects into agent-facing output at declared work-lifecycle moments.
tools
candybar-check command
candybar-check renders lit's cc-candybar plugin on a pinned cc-candybar and fails when any of its segments shows other than a case expects.
candybar-check renders lit's cc-candybar plugin on a pinned cc-candybar and fails when any of its segments shows other than a case expects.
docclaims-sync command
docclaims-sync regenerates internal/docclaims/manifest_gen.go: the record of which quoted message literals in doc-v1-total were last seen to match code that actually ships.
docclaims-sync regenerates internal/docclaims/manifest_gen.go: the record of which quoted message literals in doc-v1-total were last seen to match code that actually ships.
lawtokens-check command
lawtokens-check refuses a commit that cites a law token outside the canonical index.
lawtokens-check refuses a commit that cites a law token outside the canonical index.
lawtokens-sync command
lawtokens-sync regenerates internal/lawtokens/canonical_gen.go from the upstream Token index (tokenindex.UpstreamURL), or with -check reports whether the committed file still matches it.
lawtokens-sync regenerates internal/lawtokens/canonical_gen.go from the upstream Token index (tokenindex.UpstreamURL), or with -check reports whether the committed file still matches it.
licenses command
licenses generates the third-party-dependency compliance artifacts a distributed lit binary ships: THIRD_PARTY_LICENSES (the full license text of every module compiled into the binary), LICENSE-REPORT.md (a human-readable module-to-license table with a summary), and — when -sbom is given — a CycloneDX SBOM (a machine-readable bill of materials for vulnerability scanners).
licenses generates the third-party-dependency compliance artifacts a distributed lit binary ships: THIRD_PARTY_LICENSES (the full license text of every module compiled into the binary), LICENSE-REPORT.md (a human-readable module-to-license table with a summary), and — when -sbom is given — a CycloneDX SBOM (a machine-readable bill of materials for vulnerability scanners).
mkmanifest command
mkmanifest emits the per-release manifest published alongside the binary artifacts.
mkmanifest emits the per-release manifest published alongside the binary artifacts.
perfbench command
perfbench measures what a lit command costs a user: it generates lit stores at controlled row counts, times every user-facing command against each one, and reports the store's bytes on disk alongside.
perfbench measures what a lit command costs a user: it generates lit stores at controlled row counts, times every user-facing command against each one, and reports the store's bytes on disk alongside.
schema-release-check command
schema-release-check refuses a source install of lit whose schema no published release supports.
schema-release-check refuses a source install of lit whose schema no published release supports.
testbudget command
testbudget enforces the per-package wall-clock budgets in budgets.go against a `go test -json` stream on stdin.
testbudget enforces the per-package wall-clock budgets in budgets.go against a `go test -json` stream on stdin.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL