diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index d3aa4c8..4dc6d3d 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -41,7 +41,7 @@ jobs:
run: npm audit --omit=dev --audit-level=high
rust-check:
- runs-on: macos-latest
+ runs-on: macos-26
steps:
- name: Check out repository
uses: actions/checkout@v6
diff --git a/.github/workflows/deploy-pages.yml b/.github/workflows/deploy-pages.yml
new file mode 100644
index 0000000..cb95930
--- /dev/null
+++ b/.github/workflows/deploy-pages.yml
@@ -0,0 +1,36 @@
+name: deploy-pages
+
+# Deploys the static marketing site in website/ to GitHub Pages whenever it
+# changes on main. Requires Pages to be enabled with "Source: GitHub Actions"
+# in repo Settings -> Pages (one-time). Runs on demand via workflow_dispatch too.
+on:
+ push:
+ branches: [main]
+ paths:
+ - 'website/**'
+ - '.github/workflows/deploy-pages.yml'
+ workflow_dispatch:
+
+permissions:
+ contents: read
+ pages: write
+ id-token: write
+
+concurrency:
+ group: pages
+ cancel-in-progress: false
+
+jobs:
+ deploy:
+ runs-on: ubuntu-latest
+ environment:
+ name: github-pages
+ url: ${{ steps.deployment.outputs.page_url }}
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/configure-pages@v5
+ - uses: actions/upload-pages-artifact@v3
+ with:
+ path: website
+ - id: deployment
+ uses: actions/deploy-pages@v4
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 0c546fd..4456e99 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -73,7 +73,7 @@ jobs:
build-macos:
permissions:
contents: read
- runs-on: macos-latest
+ runs-on: macos-26
needs: decide
if: ${{ needs.decide.outputs.skip != 'true' }}
strategy:
@@ -167,7 +167,7 @@ jobs:
- name: Normalize macOS artifact filenames
shell: bash
- working-directory: src-tauri/target/${{ matrix.target }}/release/bundle
+ working-directory: target/${{ matrix.target }}/release/bundle
env:
ARCH: ${{ matrix.arch }}
run: |
@@ -186,9 +186,9 @@ jobs:
with:
name: release-macos-${{ matrix.arch }}
path: |
- src-tauri/target/${{ matrix.target }}/release/bundle/dmg/*.dmg
- src-tauri/target/${{ matrix.target }}/release/bundle/macos/*.app.tar.gz
- src-tauri/target/${{ matrix.target }}/release/bundle/macos/*.app.tar.gz.sig
+ target/${{ matrix.target }}/release/bundle/dmg/*.dmg
+ target/${{ matrix.target }}/release/bundle/macos/*.app.tar.gz
+ target/${{ matrix.target }}/release/bundle/macos/*.app.tar.gz.sig
if-no-files-found: error
release:
@@ -219,6 +219,7 @@ jobs:
path: release-assets/macos-x86_64
- name: Group the changelog
+ id: group
env:
PREV_TAG: ${{ needs.decide.outputs.previous_tag }}
VERSION: ${{ needs.decide.outputs.version }}
@@ -227,13 +228,18 @@ jobs:
[ -n "$PREV_TAG" ] && range="${PREV_TAG}..HEAD"
git log "$range" --no-merges --pretty='%s' \
| node scripts/ci/gen-changelog.mjs > grouped-changelog.md
+ echo "chars=$(wc -c < grouped-changelog.md | tr -d ' ')" >> "$GITHUB_OUTPUT"
echo "----- grouped-changelog.md -----"
cat grouped-changelog.md
- name: Rewrite the changelog (GitHub Models)
id: changelog_ai
+ # gpt-5 via GitHub Models caps the request body near 4000 tokens; skip the
+ # AI rewrite for an oversized changelog (e.g. the first release, which spans
+ # all history) and fall back to the grouped changelog in the next step.
+ if: ${{ fromJSON(steps.group.outputs.chars) <= 10000 }}
continue-on-error: true
- uses: actions/ai-inference@v1
+ uses: actions/ai-inference@v2
with:
model: openai/gpt-5
system-prompt: |
diff --git a/CLAUDE.md b/CLAUDE.md
index b30d970..0b1f5d3 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -5,8 +5,9 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
**Git It** — a native macOS git client (commit graph, branches, merges, rebases, working-copy
diffs, remotes) with first-class commit-time editing. Also hosts the headless **agent** that
lets the sibling iOS app drive local git remotely. Tauri 2 (Rust) + SvelteKit 5 (runes).
-macOS only; window uses native `NSVisualEffect` vibrancy (glass panels). Private; `UNLICENSED`
-— licensing is intentionally undecided, do not add a LICENSE.
+macOS only; window uses native `NSVisualEffect` vibrancy (glass panels). Licensed
+**CC BY-NC-SA 4.0** (source-available, noncommercial — see `LICENSE`); **not** OSI
+open source, so never describe it as "open source".
## Commands
@@ -28,7 +29,7 @@ Frontend-only changes hot-reload under `npm run tauri dev`. **Vitest and the bro
cannot exercise Tauri-only paths** (anything behind `invoke`: native dialogs, working-copy
staging, reword, real git). Those require a running `tauri dev`/`build`.
-Requires system `git` on `PATH`. Commit-time editing additionally shells out to `git-filter-repo`.
+Requires system `git` and `python3` on `PATH` (both ship with the Xcode Command Line Tools). Commit-time editing runs the **bundled** `git-filter-repo` script (`src-tauri/resources/git-filter-repo/`) via the host `python3` — it is not a `PATH` binary.
## Architecture
@@ -47,9 +48,12 @@ Three-layer split; a **cargo workspace** (root `Cargo.toml`, members below) with
`relay.rs` (Convex client + message loop), `auth.rs`, `repos.rs`, `crypto/` (HPKE/Ed25519 E2E).
- **`src/`** — SvelteKit 5 SPA (static adapter, single `+page.svelte` route). `lib/store.svelte.ts`
is central runes state; `lib/gitActions.ts` calls Tauri commands; `lib/graph/` renders the lane
- graph; `lib/diff/` is Shiki-highlighted diffs; `lib/github/` is the GitHub dashboard screen.
+ graph; `lib/diff/` is Shiki-highlighted diffs; `lib/github/` is the GitHub dashboard screen;
+ `lib/theme/` (`nerv.css`, `nerv-motion.css`, `themeMode.ts`) is the Classic↔NERV theme system.
**Pure logic modules are unit-tested with vitest** and must stay Tauri-free: `dates.ts`,
`fileTree.ts`, `refTree.ts`, `commitBody.ts`, graph windowing (`.test.ts` alongside each).
+- **`website/`** — the static NERV-themed marketing site (git-it.app), deployed by
+ `.github/workflows/deploy-pages.yml`; plain HTML/CSS/JS, independent of the SvelteKit app build.
**Data flow:** Svelte `invoke` (`@tauri-apps/api`) → `src-tauri/commands.rs` → `git-core` →
shells out to system `git` (and `gh` for the GitHub screen).
@@ -64,6 +68,8 @@ shells out to system `git` (and `gh` for the GitHub screen).
whole app during the call (this exact bug froze the GitHub screen).
- Business logic that can be pure belongs in a testable `src/lib/*.ts` module (vitest), not inside
a `.svelte` component — the graph/date/tree logic is covered this way.
+- **NERV theme CSS:** never use `:global()` in plain `src/lib/theme/nerv.css` — it isn't a Svelte
+ `
+
+
+
+
+
+
+
+ macOS git client · Apple Silicon + Intel
+
+
+ Bend the
+ timeline.REV 0.2.0
+
+
+
Commit-time editing — shift, set, or compress any range. Preview, then undo.
+
+
Git It is a fast, native git client for macOS — commit graph, branches, merges, per-hunk diffs, remotes, and a built-in GitHub dashboard. Everything runs locally. No account, no telemetry.
Commit-time editing — shift, set, or compress any range. Preview, then undo.
+
+
A fast, native git client for macOS — commit graph, branches, merges, per-hunk diffs, remotes, and a built-in GitHub dashboard. Local-first: no account, no analytics, no tracking.
+ No account
+ No tracking
+ Native — no Electron
+ ● Auto-updates
+
+
+
+
+
+
+ ◇ MAGI // Commit Graph
+ LIVE
+
+
+
+
+
+
+ 150 commits
+ 3 branches · 2 remotes
+ clean
+
+
+
Diagram: a commit graph with one commit's timestamp being rewritten from 14:22 to 09:05.
+
+
+
+
+
+
+
+
Why Git It
+
+
+ 01
+
Commit-time editing
+
Reshape when history happened, right in the client. A rarity in any git GUI.
+
+
+ 02
+
A safety net for every rewrite
+
Automatic backup (a git bundle) + one-click undo before any destructive op, plus a reflog browser.
+
+
+ 03
+
Local-first & free
+
No account, no analytics; native (no Electron); source-available for noncommercial use.
+
+
+
+
+
+
+
+
+
+
Platform
macOS 12.3+
+
Architecture
Apple Silicon · Intel
+
Engine
Rust · Tauri 2 · Svelte 5 (no Electron)
+
Price
Free · Source-available
+
+
+
+
+
+
+
+
+
+
+
+ OP // GRAPH
+
Read history at a glance.
+
Multi-lane commit graph with curved or angular edges, ref badges (branches, tags, remotes, HEAD), infinite-scroll loading, right-click checkout / branch / tag / fetch.
+
+
Curved & angular lanes
+
Ref badges — branch · tag · remote · HEAD
+
Infinite-scroll history
+
Right-click: checkout · branch · tag · fetch
+
+
+
+
+
+
+ ◇ MAGI // Commit Graph
+ LIVE
+
+
+
+
+
+ 150 commits
+ 3 branches · 2 remotes
+ clean
+
+
+
Diagram: a multi-lane commit graph. The tip commit "ship: release v1.0" carries HEAD, main, and origin/main badges; a second lane branches and rejoins with green edges; the base commit is tagged v1.0. One row is highlighted as selected.
+
+
+
+
+
+
+ OP // TIME
+
Commit-time editing.
+
Select a range and shift by an offset, set an exact time, or compress the range proportionally into a new window. Preview before it rewrites; undo in one click. Powered by a bundled git-filter-repo.
Diagram: a vertical timeline of seven commits, each with a timestamp. A bracket labeled SELECTED marks a three-commit range; two of those commits show their times being rewritten — 14:22 to 09:05 and 11:58 to 08:30, old times struck through, new times in green. A REWRITE control offers three modes — OFFSET (active), EXACT, and COMPRESS — with a delta of minus five hours seventeen minutes, and a PREVIEW / UNDO strip below, noting an automatic backup bundle was written.
+
+
+
+
+
+
+ OP // MERGE
+
Integrate, and resolve.
+
Merge (plain or --no-ff), cherry-pick, and revert — with an in-app conflict resolver: use-ours, use-theirs, continue, or abort, file by file.
+
+
Merge · cherry-pick · revert
+
Plain or --no-ff
+
Resolver: ours / theirs / continue / abort
+
File-by-file, in-app
+
+
+
+
+
+
+ ◇ MAGI // Merge & Resolve
+ PAUSED
+
+
+
+
+
+ merge --no-ff
+ 1 file · 1 hunk
+ resolvable
+
+
+
Diagram: two branch lanes, OURS and THEIRS, converging into a single merge commit that reports one conflict. A conflict resolver panel for the file src/app.rs shows the two conflicting versions with use-ours and use-theirs toggle chips (use-ours selected), plus continue and abort controls.
+
+
+
+
+
+
+ OP // REWRITE
+
Rewrite history — safely.
+
Soft/mixed/hard reset, amend, rebase-onto, and interactive rebase (reorder / squash / drop / reword). Every destructive op takes a configurable auto-backup (a git bundle) first, with one-click undo and a reflog browser.
+
+
Reset · amend · rebase-onto
+
Interactive: reorder / squash / drop / reword
+
Auto-backup bundle before every op
+
One-click undo · reflog browser
+
+
+
+
+
+
+ ◇ MAGI // Interactive Rebase
+ ARMED
+
+
+
+
+
+ 5 commits · 1 drop
+ 1 squash
+ backup ready
+
+
+
Diagram: an interactive-rebase todo list of five commits, each with a drag handle and an action chip — pick, reword, squash (highlighted), drop (struck through), and pick. Below, a green BACKUP CREATED confirmation names a pre-rebase git bundle, alongside a one-click UNDO control.
+
+
+
+
+
+
+ OP // DIFF
+
Stage exactly what you mean.
+
A working-copy file list with whole-file and per-hunk stage / unstage / discard, syntax-highlighted diffs (unified or split, highlighted offline via bundled Shiki), a commit composer, and stash.
Diagram: a side-by-side split diff of a file. The first hunk is unstaged with a STAGE chip: a removed line "timeout(30)" in red on the old side, and two added lines "timeout(60)" and "retry(3)" in green on the new side. The second hunk is already staged (STAGED chip) with an added "fsync()" line. Below, a commit composer shows one hunk staged, with commit and stash controls.
+
+
+
+
+
+
+ OP // REMOTE
+
Push, pull, and GitHub — in one place.
+
Streamed pull (merge or rebase) and push (--force-with-lease, --set-upstream) with live progress, cancel, and an ahead/behind indicator. Plus a built-in GitHub dashboard: pull requests, issues, releases, and CI runs. Credentials are prompted on demand and never stored (a transient 0600 file, deleted immediately after).
+
+
Streamed pull & push — live progress
+
Ahead / behind indicator
+
GitHub: PRs · issues · releases · CI
+
Credentials never stored on disk
+
+
+
+
+
+
+ ◇ MAGI // Sync & GitHub
+ PUSHING
+
+
+
+
+
+ push --force-with-lease
+ ↑2 ↓1
+ CI passing
+
+
+
Diagram: a remote sync readout for origin/main showing an ahead-by-two, behind-by-one indicator, a streaming git push log with a progress bar at 69% and a cancel control, and a note that credentials are a transient 0600 file. Below, a mini GitHub dashboard shows a pull-request chip, an issue chip, and a green CI-passing chip.
+
+
+
+
+
+
+ OP // THEME
+
Everything here is a theme.
+
The console you’ve been reading — orange on void, corner brackets, scanlines — isn’t just the website. It’s NERV, one of Git It’s two built-in themes. Prefer something quieter? Classic wears native macOS vibrancy: frosted glass over your desktop. Switch anytime, and tune the accent across six schemes, in Settings → Appearance.
+
+
Classic — native macOS glass
+
NERV — this exact console
+
Six accent schemes
+
Switch in Settings → Appearance
+
+
+
+
+
+
+ ◇ MAGI // Appearance
+ LIVE
+
+
+
+
+
+ 2 themes
+ 6 accent schemes
+ no restart
+
+
+
Diagram: two theme swatches side by side — a light frosted-glass “Classic” panel and a dark orange-on-void “NERV” console with corner brackets and a mini commit graph — with a swap arrow between them, showing you can switch from one theme to the other.
+
+
+
+
+
+
Also — open several repos at once, as tabs or a sidebar list, your choice.
+
+
+
+
+
+
+ OP // DOWNLOAD
+
Download Git It.
+
Open the .dmg, drag Git It into Applications, launch. It keeps itself up to date after that — with an optional beta channel in Settings → Updates.
No account, no backend, no analytics. Your repos and credentials stay on your Mac. The only network calls are the git/GitHub operations you trigger, plus a version check for updates. Credentials are prompted on demand and never written to disk beyond a transient 0600 file that's deleted right after.
+
+
+ Do I have to bypass Gatekeeper?
+
No — the release is signed and notarized by Apple; it opens with a normal double-click. (Only self-built ad-hoc copies trigger the Gatekeeper prompt.)
+
+
+ Why macOS only?
+
Native vibrancy and title-bar handling are macOS-specific. Apple Silicon and Intel builds are both fully native (no Electron).
+
+
+ Is rewriting history safe?
+
Destructive ops take an automatic git-bundle backup first, force-push is always --force-with-lease, and there's one-click undo plus a reflog browser.
+
+
+ What do I need installed?
+
git and python3 — both from the Xcode Command Line Tools (xcode-select --install). git-filter-repo is bundled.
+
+
+ How do updates work?
+
In-app auto-updates, with an optional beta channel in Settings → Updates.
+
+
+ Apple Silicon or Intel?
+
Download the .dmg that matches your Mac; each runs fully native. Updates then track the right build.
+
+
+ What's the license?
+
Free and source-available under CC BY-NC-SA 4.0 — use it for any work (including at your job); you just can't resell or repackage the app itself, and forks stay under the same license. Not an OSI open-source license.
+
+
+
+
+
+
+
+
+
+ OP // COMMUNITY
+
Built in the open.
+
Git It is developed in public. Read the source, file an issue, or open a pull request — everything happens on GitHub.
+ Source-available under CC BY-NC-SA 4.0 — not an OSI open-source license.
+ Contributions welcome — accepted under the project's CC BY-NC-SA 4.0 license.
+