How it works
This page covers installation, the core model, every command, keyboard shortcuts, synchronization, and agent integration.
Installation
Epiq ships as a single binary (with an npm package alternative).
The binary installs to ~/.local/bin by default.
Quick install (binary)
curl -fsSL https://raw.githubusercontent.com/ljtn/epiq/main/install.sh | sh
Override the location with EPIQ_INSTALL_DIR (or
XDG_BIN_HOME), and pin a version with
EPIQ_VERSION=v1.0.0.
Via npm
npm install --global epiq
Verify
epiq --version
Getting started in two steps
Epiq lives inside a Git repository — your issues can live where your code lives.
-
Make sure you are inside a Git repository. For collaboration,
use a repo with a remote (e.g. cloned from GitHub).
# if needed git init -
Run epiq:
epiq
On first run this opens an interactive setup wizard that gets you going in about 30 seconds. Once your project is set up, you can also launch the browser GUI:
epiq gui
~/.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
The hierarchy
State is a tree of nodes. From the top down:
workspace → board →
swimlane → issue. Issues hold a
description, tags, assignees, comments, and a full history log.
Commands are context-aware — for instance
:close only exists for issues.
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.
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 description of the selected issue in your preferred external editor (no inline text — also bound to 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 |
: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
|
: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>
|
Update editor, username, view, auto-sync, sync debounce, or log level |
: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 ☕ |
Filtering
Apply a filter with :filter followed by a target and
a value. To show every issue carrying an urgent tag:
:filter tag urgent
Run several :filter commands in succession to build a
combination. Targets are tag, assignee,
description, and title. Clear everything
with:
:filter clear
Closing & reopening
Close an issue with :close. This moves it to a
special board named Closed, which you can reach
by navigating up (press q) a few times.
To bring it back, open the Closed board, select
the issue, and run :reopen. The issue is restored to
its previous location, resolved from its history log.
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
While peeking, the board is read-only; only viewing, exporting, and configuration are available.
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 |
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.
:config autoSync on to sync automatically.
MCP & agents
Epiq ships an MCP (Model Context Protocol) server via the
epiq-mcp binary, so AI agents can interact with your
local instance.
Claude Code
The reliable way to register the server is with
claude mcp add — it writes the correct config for
you:
# available everywhere (recommended)
claude mcp add --scope user epiq -- npx -y -p epiq epiq-mcp
# or only in the current project
claude mcp add epiq -- npx -y -p epiq epiq-mcp
Verify with claude mcp list (it should report
epiq … ✔ Connected). MCP servers load at startup, so
restart Claude Code after adding the server.
Other MCP clients
For hand-configured clients, add the following to the client's MCP config file:
{
"mcpServers": {
"epiq": {
"command": "npx",
"args": ["-y", "-p", "epiq", "epiq-mcp"]
}
}
}
Export
Run :export to write the current board layout to a
markdown file — handy for sharing a snapshot, generating reports,
or feeding context to other tools.
:export