A cross-project status layer. Interlace deterministically indexes what's pending and what got done across all of your repositories, then answers the one question every multi-project developer keeps asking: "where am I across everything?"
The first surface is a CLI called lace. It scans your tracked repos and ranks
what needs attention, so you don't have to mentally re-load the state of a dozen
projects every morning.
$ lace status
interlace ▸ 2 blocking · 5 done this week
imigro-app ▸ 6 blocking · 51 done this week
neuromint ▸ 0 blocking · 12 done this week
...
Context lives in too many places: open issues on GitHub, TODO/FIXME markers
buried in code, unchecked - [ ] boxes in Markdown plans, branches you pushed
and forgot. Interlace collects all of it into one Postgres-backed index and
gives you a single ranked view.
Core principle: the collector is a dumb, fast, deterministic indexer. No LLM ever sits in the collection or ranking loop — results are reproducible and auditable. (LLM-powered summaries are an opt-in, on-demand layer planned for later.)
| Source | What it picks up |
|---|---|
| git | repo state, recent commits, pushed branches |
| code comments | TODO / FIXME / HACK markers (via ripgrep), with p0/p1/p2 priority |
| Markdown | - [ ] / - [x] checkboxes in *.md, with priority:: or [P0]/[P1] conventions |
| GitHub | open/closed issues, opened/merged PRs, and deferred @lace / 📌 PR review comments (token-gated) |
Items are content-addressed, so editing a line or shifting code around
doesn't churn your index — closing a checkbox or deleting a TODO transitions
that item to done in place.
- Node.js ≥ 22 and pnpm 10
- ripgrep (
rg) on your PATH — the code-comment collector shells out to it. Install viabrew install ripgrep(macOS) or your package manager. Without it, only the code-comment collector is skipped; everything else still runs. - A Postgres database reachable via
DATABASE_URL(local Postgres, Docker, or Supabase all work).
git clone https://github.com/maggit/interlace.git
cd interlace
pnpm install
pnpm buildThe CLI binary is built to packages/cli/dist/index.js and exposed as lace.
You can run it via pnpm --filter @interlace/cli exec lace …, or link it onto
your PATH:
pnpm --filter @interlace/cli link --global # makes `lace` available globally-
Point at a database. Copy
.env.exampleto.envand set your connection string, or export it directly:export DATABASE_URL=postgresql://user:pass@host:5432/postgresNeed a throwaway Postgres?
docker run --rm -p 5432:5432 -e POSTGRES_PASSWORD=lace postgres:16-alpine -
Apply the schema. A one-time step (re-run after upgrades that ship new migrations — it's idempotent):
lace db migrate
-
Register a project.
lace project add imigro --path /abs/path/to/imigro --github sahara/imigro
-
Scan — collect the current state of every tracked project (or just one):
lace scan # all projects lace scan imigro # one project
-
Check status.
lace status # super-view: every active project, ranked lace project-status imigro # one project in detail (alias: lace s imigro)
-
Close an item straight from the CLI — flips its checkbox
[ ]→[x]in the source file and re-scans:lace close imigro docs/plan.md:42
-
Run continuously (optional) — watch files and poll on an interval:
lace daemon
| Command | Description |
|---|---|
lace config |
Show resolved mode, DB target (redacted), and enabled collectors |
lace db migrate |
Apply pending migrations to the configured database |
lace project add <slug> --path <abs> [--github <owner/repo>] |
Register a project |
lace project list |
List registered projects |
lace scan [slug] |
Force a collect now — all projects, or one |
lace close <slug> <path:line> |
Mark a checkbox item done and re-scan |
lace status |
Super-view: all active projects, ranked |
lace project-status <slug> (alias s, or lace <slug> status) |
Single project: repo line, done-this-week, pending |
lace daemon |
Watch projects + poll on an interval, scanning continuously |
Run lace config first if a command can't find your database — it prints
exactly what Interlace resolved.
Configuration is layered (later overrides earlier): built-in defaults →
~/.config/interlace/config.toml → .interlace.toml in the repo → environment
variables → command flags. The common knobs:
| Variable | Purpose |
|---|---|
DATABASE_URL |
Postgres connection string (required for local mode) |
GITHUB_TOKEN |
Enables the GitHub collector; absent → GitHub collection is silently disabled |
defer_token |
Marker that turns a PR review comment into a tracked item (default @lace) |
See .env.example for the full set.
Two non-sensitive groups can also be overridden from a TOML config file
(~/.config/interlace/config.toml or a project-local .interlace.toml):
[daemon]
pollIntervalMs = 60000 # full poll cadence (default 300000)
debounceMs = 1000 # quiet period after a file change before re-scan (default 2000)
[ranking]
p2PressureCap = 30 # saturation cap on low-priority (P2) backlog pressure,
# so a big pile of low-priority items can't bury real P0 worklace config prints the resolved daemon intervals so you can confirm an override
took effect.
Interlace is a pnpm + Turborepo monorepo:
packages/
├─ core/ Drizzle schema + migrations, config resolution, ranking,
│ idempotent ingest engine, super-view / project-status queries
├─ collectors/ Pure, deterministic collectors: git, code-comment, markdown, github
├─ cli/ The `lace` command (Commander) — runs collectors inline
├─ workers/ Background-job skeleton (reserved for backend mode)
├─ pollers/ Scheduled-poll skeleton (reserved for backend mode)
└─ api/ HTTP API skeleton (reserved for backend mode)
- core owns the database (Postgres via Drizzle ORM +
postgres.js) and the ingest engine, which is transaction-wrapped and idempotent: re-scanning never duplicates work, and items auto-complete when their source disappears. - collectors are pure functions over a repo's current state — given a path (and optionally a GitHub token) they return items and activity. They never touch the database directly.
- Tests run against pglite (in-process Postgres) — no Docker needed in CI —
plus real
git,rg, andchokidar, and an in-memory fake GitHub client.
pnpm install
pnpm build # turbo build, respects the dependency graph
pnpm test # vitest across all packages
pnpm typecheck # tsc --noEmit across all packages
pnpm lint:deps # dependency-cruiser: enforce package boundaries@interlace/core must be built before packages that import it; turbo and the
lint:deps script handle that ordering for you.
See CONTRIBUTING.md for the contribution workflow, coding conventions, and how to add a new collector; CHANGELOG.md for the release history; and SECURITY.md for how to report a vulnerability.
v1 (local mode) is complete: all collectors, idempotent ingest with
auto-completion, ranking, and the lace CLI including a continuous daemon.
Designed-for but not yet built: backend mode (the api/workers/pollers
packages deployed with a Redis/BullMQ queue), a menu-bar app, an MCP server,
and lace brief (on-demand LLM summaries). Contributions toward any of these
are welcome.
MIT © Raquel Hernandez