$ catena status
connection lost
$ catena reconnect
attempting to reach server...
server unreachable.

How it Works

Everything you need to know to work with Catena.

What is Catena?

Catena is a patch-based version control system. Every change is a Patch — an atomic package of file operations. Patches are chained together in a linear sequence.

+
Patches, not Commits
Every change is a self-contained, reviewable package
Trunk, not Branches
One single truth, no diverging histories
!
Overlap Detection
Conflicts are detected immediately, not at integration time
Online-first
The server is the source of truth, sync is trivial
💬
Inline Comments
Comment directly on code lines in a patch

Core Concepts

Patches

A patch is a collection of file operations:

+ Insert ~ Modify - Delete > Rename

Every patch has an author, description, timestamp, and a Maturity level.

Trunk

The trunk is the current, correct state of the project. No main branch, no develop. Just the trunk. When a patch is accepted, the trunk grows — patch by patch, linearly.

Maturity — The Lifecycle of a Patch

DraftLocal
DraftSynced
DraftShared
Proposed
Accepted
← withdraw
DraftLocal Created locally, not yet synced
DraftSynced Saved on server, only visible to you
DraftShared Shared with team, others can build dependencies on it
Proposed Submitted for review — candidate for the trunk
Accepted Merged into trunk — now part of the truth
Withdraw: A proposed patch can be pulled back to DraftSynced with catena withdraw to continue working on it.

Overlaps (Conflicts)

When two proposed patches modify the same file, Catena detects it immediately:

Payment Retry
overlap
Email Notifications
Auto-Apply — Different files, no problem
Deduplicated — Same change, merged automatically
Conflict — Same file, different change → must be resolved

Overlaps are highlighted in red on the Timeline and in the Patches view.

Dependencies

Patches can depend on each other. A patch can only be accepted once all its dependencies are accepted.

Frontend Types
API Auth Refactor
Payment Retry
Email Notify
Trunk (accepted)

Accept order: Payment + Email → API Auth → Frontend Types

Sync

Your Workspace
💻
sync up ↑
↓ sync down
Server (Trunk)
☁️
$ catena sync down # Server → Local (Pull)
$ catena sync up -m "My fix" # Local → Server (Push)
$ catena sync down --patch abc123 # Trunk + test a patch
Safety: catena sync without down asks for confirmation if you have local changes. With explicit catena sync down it doesn't ask — you know what you're doing.

Roles

Developer Create patches, propose, withdraw, view status
Maintainer + Accept patches, create releases
Admin + Manage users, assign roles

Getting Started

1

Start the server

$ dotnet run --project src/Catena.Server
Admin API Key: xxxxxxxx

On first run an admin key is displayed. Save it!

2

Create a project

$ catena init --new "My Project" --api-key <KEY>
Workspace initialized in .catena/
3

Make changes & check status

$ echo "Hello" > hello.txt
$ catena status
+ hello.txt
1 added, 0 modified, 0 deleted
4

Push changes

$ catena sync up -m "Add hello"
Synced up: patch abc123 created (1 ops)
5

Propose & Accept

$ catena propose
Patch abc123 proposed.
$ catena accept abc123
Patch abc123 accepted. Trunk updated.

Workflows

Daily Workflow

catena sync downPull trunk state
Edit files
catena statusWhat changed?
catena sync up -m "..."Push changes
catena proposeSubmit for review
Team comments inline
catena accept <id>Maintainer accepts

Resolving Conflicts

# Alice and Bob modify the same file
OVERLAP detected: Payment Retry × Email Notifications
# Bob withdraws, Alice gets accepted
$ catena withdraw <bob-id>
$ catena accept <alice-id>
# Bob syncs, adjusts, re-proposes
$ catena sync down
$ catena sync up -m "Email v2"
$ catena propose

Building on a Patch

# Pull Alice's patch as your base
$ catena sync down --patch <alice-id>
# Work on top, push with dependency
$ catena sync up -m "Auth service"
$ catena draft --depends-on <alice-id>
$ catena propose
# Accept enforces order: Alice → Bob

Hotfix on Release + Trunk

$ catena release v1.0.0
# Hotfix targeting both
$ catena sync up -m "Hotfix login"
$ catena draft --target trunk --target v1.0.0
# After accept: patch applied to trunk + release

CLI Reference

catena initCreate or connect a workspace
catena statusShow local changes
catena sync upPush changes to server
catena sync downPull trunk state
catena proposeSubmit patch for review
catena accept <id>Accept patch into trunk
catena withdraw <id>Pull back a proposed patch
catena logShow patch history
catena diff <id>Show patch details
catena release <v>Create release snapshot
catena draftSet dependencies / targets

Web UI

Available at /app after login.

Dashboard

Overview: stats, activity feed, overlap count

Patches

Master-detail with diff, inline comments, overlaps

Timeline

Patch chain graph with dependencies and overlaps

Files

Trunk file tree with code viewer

Releases

Frozen snapshots with version tags

Settings

Team, roles, API keys, webhooks

The UI updates live — when someone creates or accepts a patch via CLI or API, you see it instantly in the browser.

Design Decisions

Trunk, not Branches

Catena has one trunk — the single source of truth. Parallel work happens through proposed patches: they live side by side, not in separate histories. Overlap detection shows immediately when two patches collide.

Online-first

The server is the source of truth. Sync is trivial, overlaps are instantly visible, comments are native. You can still work offline: catena draft creates local drafts.

Linear History

Every patch is atomic — either fully in trunk or not at all. The history is a chain, not a graph. This makes it easier to understand and debug.