Skip to content

Local-First Architecture

ProGit is built on a local-first architecture. Your data lives on your machine first, with optional synchronization to remote services.

Local-first software stores the primary copy of data on the user’s device:

┌─────────────────────────────────────────┐
│ Your Computer │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ Git Repo │ │ .project/ │ │
│ │ │ │ │ │
│ │ • Source │ │ • Issues │ │
│ │ • History │ │ • Sprints │ │
│ │ • Branches │ │ • Kanban │ │
│ └──────────────┘ │ • Config │ │
│ └──────────────┘ │
│ ↕ Optional │
│ ┌──────────────┐ │
│ │ Remote │ │
│ │ (GitLab/) │ │
│ └──────────────┘ │
└─────────────────────────────────────────┘

When you run progit init, ProGit creates a .project/ directory:

my-project/
└── .project/
├── config.toml # Project configuration
├── issues/
│ ├── issue-001.json
│ ├── issue-002.json
│ └── index.json # Issue index
├── sprints/
│ ├── sprint-2024-01.json
│ └── current.json # Current sprint
├── kanban/
│ └── board.json # Board configuration
└── plugins/
└── local/ # Local-only plugins

All data is stored as human-readable JSON:

.project/issues/issue-042.json
{
"id": 42,
"title": "Fix memory leak in parser",
"description": "## Description\n\nThe parser leaks...",
"status": "in-progress",
"labels": ["bug", "performance"],
"priority": "high",
"assignee": "jane@example.com",
"created_at": "2026-03-13T10:00:00Z",
"updated_at": "2026-03-13T14:30:00Z",
"sprint_id": "sprint-12",
"git_branch": "fix/parser-leak",
"linked_commits": ["a1b2c3d"]
}

ProGit uses atomic file operations to prevent data corruption:

  1. Write to temporary file
  2. Sync to disk
  3. Rename to target (atomic)
Terminal window
# Internally, ProGit does:
echo '{"id":42,...}' > .project/issues/issue-042.json.tmp
sync
mv .project/issues/issue-042.json.tmp .project/issues/issue-042.json

No network latency. Everything is instant:

Terminal window
# Fast - local file access
$ progit issue list
42 issues found (0.003s)
# Slow - network request
$ gh issue list
42 issues found (1.247s)

Work without internet:

Terminal window
# On a plane, no wifi
$ progit issue create "Refactor auth"
Issue #43 created
$ progit kanban move 43 "In Progress"
Issue moved
# Changes sync when reconnected
$ progit sync
Syncing 3 new issues to GitLab...
Sync complete

Your data stays on your machine:

  • Export anytime: progit export --format=json
  • No vendor lock-in
  • Works with any git forge (or none)

Sensitive issue data never leaves your machine unless you choose:

.project/config.toml
[sync]
# Only sync public issues
private_issues = false
# Encrypt sync data
encryption = true

When you do want to sync, ProGit uses a bidirectional sync model:

┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ ProGit │ ←──→ │ Sync Queue │ ←──→ │ Remote │
│ (Local) │ │ (Changes) │ │ (GitLab/) │
└──────────────┘ └──────────────┘ └──────────────┘

When changes happen in both places:

  1. Local changes take priority (local-first)
  2. Remote changes are merged if possible
  3. Conflicts are flagged for manual resolution
Terminal window
$ progit sync
Syncing with GitLab...
Conflict detected on issue #42
Local: "Fix memory leak"
Remote: "Fix parser leak"
Resolve: [l]ocal, [r]emote, [m]erge, [s]kip? m
Merged: "Fix memory leak in parser"

ProGit stores data alongside your git repository:

Terminal window
# Git tracks source code
git add src/
git commit -m "Fix memory leak"
# ProGit tracks project metadata
# (in .project/, which can be git-ignored or committed)
echo ".project/" >> .gitignore # Don't commit
# or
git add .project/ # Commit for team sync
Terminal window
# ProGit automatically links commits to issues
$ git commit -m "Fix parser #42"
# Or use ProGit's commit wrapper
$ progit commit -m "Fix parser" --issue=42
Commit a1b2c3d created
Linked to issue #42
Issue #42 moved to "Done"

Since data is local, you control backups:

Terminal window
# Include .project/ in git
echo "!.project/" >> .gitignore
git add .project/
git commit -m "Update project metadata"
Terminal window
# Configure sync
progit config set sync.remote gitlab
progit config set sync.auto true
# Auto-sync on commit
progit hook add post-commit "progit sync"
Terminal window
# Export all data
progit export --format=json --output=backup-$(date +%Y%m%d).json
# Import later
progit import backup-20260313.json
FeatureProGit (Local-First)Cloud-First (Jira, etc.)
SpeedInstantNetwork dependent
OfflineFull functionalityLimited or none
PrivacyYou own the dataVendor owns the data
CostFree$7-15/user/month
CustomizationUnlimitedLimited by vendor
ExportAnytimeOften difficult