Documentation

how it works.

Installation

Binary

Installs to ~/.local/bin. Change that with EPIQ_INSTALL_DIR (or XDG_BIN_HOME), and pin a version with EPIQ_VERSION=v1.0.0.

npm

Verify

Getting started

  1. Open a Git repository, or create one. To collaborate, it needs a remote.
  2. Run Epiq. The first run opens a setup wizard.

Then, if you like, open the browser app:

What gets created. The setup wizard writes user config to ~/.epiq-global/config.json. Initialization adds a project definition at ./.epiq/project.json, authoritative Git state at ~/.epiq-global/worktrees/<id>, and updates your .gitignore to ignore local-only .epiq/log/.

Core concepts

Event-sourced state

Every change is stored as an append-only event in a user-scoped log, rather than mutating a shared file. The current state is materialized in memory by replaying a merge of all user logs in a deterministic order (time-sortable ULIDs plus a reference to the last known event). This makes concurrent edits converge to the same state and keeps Git merges trivial.

Local-first

All operations apply instantly on your machine. Synchronization happens explicitly with :sync or automatically. When histories diverge, merging the event logs and replaying them leads to a consistent state.

In the terminal (TUI)

Command reference

Type : to enter command-line mode, then a command. Commands accept a modifier (in violet) and a free-text argument. Autocompletion suggests valid modifiers as you type, and the set of available commands depends on what is selected.

Create & edit

Command Description
:new issue|swimlane|board <name> Create a new board, swimlane, or issue
:edit title <text> Rename the selected node inline
:edit description Open the selected issue's description in your editor (also e)
:edit comment <text> Edit the currently selected comment inline (only your own comments)
:comment <text> Add a comment to the selected issue
:delete Delete the currently selected node
:move Move a node — usually triggered with m, then navigate and confirm

Issue workflow

Command Description
:tag <name> Add or create a tag on the selected issue
:untag <name> Remove a tag from the selected issue
:assign <name> Assign a user to the selected issue
:unassign <name> Remove an assignee from the selected issue
:yank ref|title|description|tags|assignees Copy the selected item's ref, title, description, tags, or assignees (also y)
:close Move the selected issue to the Closed swimlane
:reopen Move a closed issue back to its previous swimlane

View & history

Command Description
:filter tag|assignee|description|title|clear <value> Filter the board; combine filters by running several in succession
:peek <offset>|<date>|now|prev|next View the board's state at another point in time. Offset is <n>h, d, w, mo, or y (e.g. 3d); or an absolute YYYY-MM-DD date
:replay <offset>|<date> [duration] Replay board history forward from a point in time as an animation, with an optional playback duration (e.g. 30s)
:export Export the current board layout to markdown

System & sync

Command Description
:sync Pull, commit, and push Epiq state via Git
:config editor|username|view|autoSync|syncDebounceMs|logLevel <value> Change a setting; see Configuration
:init Initialize Epiq in the current Git repository
:help Open the help screen
:exit Exit the application
:coffee 1|3|5|20|custom Sponsor the development of Epiq ☕

Time travel

Because state is a full event log, you can inspect the board as it was at any point in the past. Use :peek with a time offset, or step through history:

# jump to an offset: h, d, w, mo, y (e.g. 3 days ago)
:peek 3d

# or jump to an absolute date
:peek 2026-01-15

# step backward / forward through history
:peek prev
:peek next

# return to the present
:peek now

Where :peek shows a frozen snapshot, :replay plays history forward from that point as an animation — watch the board evolve event by event. The optional second argument sets the playback duration:

# replay the last month of activity
:replay 1mo

# same, spread over a 30 second animation
:replay 1mo 30s

While peeking or replaying, the board is read-only; viewing, yanking to the clipboard, exporting, and configuration remain available.

Export

Run :export to write the current board to a markdown file.

:export

Configuration

Adjust settings with :config <setting> <value>.

Setting Description
editor Preferred external editor for descriptions
username Your display name on events and assignments
view wide|dense Board layout density
autoSync on|off Enable or disable automatic synchronization
syncDebounceMs <ms> Debounce window for auto-sync in milliseconds (e.g. 5000, 15000, 30000)
logLevel debug|info|error Logging verbosity
In the browser (GUI)

The board

epiq gui serves the same board in the browser. Add tickets and lanes in place, and narrow a busy board with the filter box — it matches on ref or title.

Settings follow the port. epiq gui uses port 3710, with a fallback to a free one. Settings are persisted in localStorage, so on a new port the timeline selections etc. start fresh. Reclaim 3710 to get them back.

Tickets & commits

Clicking a ticket opens its panel, docked to the right or along the bottom. Descriptions and comments take markdown, and images can be pasted or dropped straight in.

The Code tab lists every commit linked to the ticket, with its message, diffstat and per-file diff. Comment on any line, or mark a file as reviewed.

Timeline

Drag the scrubber across the history to check out the board as it was at that moment, as volume per period or as individual events. The header reads Read-only while you are in the past, and Now brings you back.

Collaboration

Sync & Git

Epiq uses Git in the background — no manual Git commands required. Running :sync synchronizes changes between your local state (at ~/.epiq-global/worktrees/<id>/) and the remote. By using Git worktrees, synchronization stays isolated from your regular development workflow.

Changes are append-only events in user-scoped files, so Git merges become trivial combinations of independent files. Later events take precedence when conflicts occur, and idempotent events keep concurrent updates predictable.

Tip. Sync often to keep divergence small, or turn on :config autoSync on.

MCP & agents

The epiq-mcp binary is an MCP server, so agents can work your board.

Claude Code

Register it for every project:

Or for the current project only:

Restart Claude Code, then check with claude mcp list: it should report epiq … ✔ Connected.

The Epiq skill

The server tells an agent what it can do; the skill tells it how to work the board. Ask the agent to run epiq_skill_install, or fetch it yourself:

Linking commits. A commit links to a ticket when its body has an Epiq-Ref: line naming the ticket's ref, the seven characters :yank ref copies: git commit -m "fix the parser" -m "Epiq-Ref: A1B2C3D". One line can name several refs, comma-separated. A subject that starts with the ref links too: git commit -m "A1B2C3D fix the parser". Linked commits show in the ticket's Code tab. An Epiq-Ref line survives a squash merge that keeps the squashed messages, as GitHub's default does; a prefix needs the commits rebase-merged as they are.

Other MCP clients

Add this to the client's MCP config file:

{
  "mcpServers": {
    "epiq": {
      "command": "npx",
      "args": ["-y", "-p", "epiq", "epiq-mcp"]
    }
  }
}