diff --git a/public/content/index.json b/public/content/index.json
index 9b48291..ffc936e 100644
--- a/public/content/index.json
+++ b/public/content/index.json
@@ -1,5 +1,26 @@
{
"projects": [
+ {
+ "title": "git-fleet",
+ "slug": "git-fleet",
+ "type": "projects",
+ "summary": "A Git extension written in OCaml for managing repositories across multiple Git hosts, keeping a single remote mirrored to several push destinations.",
+ "label": "Project",
+ "date": "2026-10-17",
+ "status": "Active",
+ "github": "https://git.sowinski.dev/SowinskiBraeden/git-fleet",
+ "demo": null,
+ "featured": true,
+ "order": 1,
+ "tags": [
+ "OCaml",
+ "CLI",
+ "Git",
+ "Dune",
+ "Developer Tools"
+ ],
+ "path": "./public/content/projects/git-fleet.md"
+ },
{
"title": "Reforger Mods API",
"slug": "reforger-mods-api",
@@ -11,7 +32,7 @@
"github": "https://github.com/SowinskiBraeden/ReforgerWorkshopAPI",
"demo": "https://api.reforgermods.net",
"featured": true,
- "order": 1,
+ "order": 2,
"tags": [
"Go",
"REST API",
@@ -33,7 +54,7 @@
"github": "https://git.sowinski.dev/SowinskiBraeden/boker",
"demo": "https://myboker.org",
"featured": true,
- "order": 2,
+ "order": 3,
"tags": [
"Python",
"Flask",
@@ -55,7 +76,7 @@
"github": "https://git.sowinski.dev/SowinskiBraeden/ScheduleGeneratorApp",
"demo": null,
"featured": true,
- "order": 3,
+ "order": 4,
"tags": ["Python", "Desktop App", "Scheduling", "Data Processing"],
"path": "./public/content/projects/schedule-generator-app.md"
},
@@ -70,7 +91,7 @@
"github": "https://git.sowinski.dev/SowinskiBraeden/dayz-reforger",
"demo": null,
"featured": true,
- "order": 4,
+ "order": 5,
"tags": ["Node.js", "Discord.js", "MongoDB", "Analytics", "Nitrado"],
"path": "./public/content/projects/dayz-reforger-bot.md"
},
@@ -85,7 +106,7 @@
"github": "https://github.com/LinesMerrill/police-cad",
"demo": "https://www.linespolice-cad.com/",
"featured": false,
- "order": 5,
+ "order": 6,
"tags": ["Node.js", "Express", "MongoDB", "Web App"],
"path": "./public/content/projects/lines-police-cad.md"
},
@@ -100,7 +121,7 @@
"github": "https://git.sowinski.dev/SowinskiBraeden/SowinskiBraeden",
"demo": null,
"featured": false,
- "order": 6,
+ "order": 7,
"tags": ["HTML", "CSS", "JavaScript", "Portfolio"],
"path": "./public/content/projects/portfolio.md"
},
@@ -115,7 +136,7 @@
"github": null,
"demo": "https://vairo-performance.com",
"featured": false,
- "order": 7,
+ "order": 8,
"tags": ["Freelance", "Web Design", "Domain Setup", "Client Work"],
"path": "./public/content/projects/vairo-performance-website.md"
},
@@ -130,7 +151,7 @@
"github": "https://git.sowinski.dev/SowinskiBraeden/school-management-api",
"demo": null,
"featured": false,
- "order": 8,
+ "order": 9,
"tags": ["Go", "API", "Documentation", "Education Tech"],
"path": "./public/content/projects/school-management-api.md"
},
@@ -145,7 +166,7 @@
"github": "https://git.sowinski.dev/SowinskiBraeden/XP-System",
"demo": null,
"featured": false,
- "order": 9,
+ "order": 10,
"tags": ["Web App", "Education Tech", "Gamification"],
"path": "./public/content/projects/xp-system.md"
}
diff --git a/public/content/projects/git-fleet.md b/public/content/projects/git-fleet.md
new file mode 100644
index 0000000..b21b321
--- /dev/null
+++ b/public/content/projects/git-fleet.md
@@ -0,0 +1,43 @@
+---
+title: git-fleet
+slug: git-fleet
+summary: A Git extension written in OCaml for managing repositories across multiple Git hosts, keeping a single remote mirrored to several push destinations.
+label: Project
+date: 2026-10-17
+status: Active
+featured: true
+order: 1
+github: https://git.sowinski.dev/SowinskiBraeden/git-fleet
+tags: OCaml, CLI, Git, Dune, Developer Tools
+---
+
+## Overview
+
+`git-fleet` is a native CLI that simplifies the Git workflows I use across self-hosted Git services and public hosts. I run my own Gitea instance but still mirror most repositories to GitHub, and keeping both in sync meant hand-editing remote configuration in every new project.
+
+The project started as a handful of personal shell scripts for configuring dual-push repositories, and is being rebuilt in OCaml as a single, reusable command. Because Git exposes any `git-*` executable on `PATH` as a subcommand, the tool installs as `git fleet`.
+
+## How It Works
+
+Rather than inventing its own state, `git-fleet` configures ordinary Git remotes. A remote fetches from one URL and may push to several, which is how one repository stays mirrored across more than one host.
+
+The subtlety is that a remote with no `pushurl` pushes to the URL it fetches from, but as soon as it has one `pushurl`, Git pushes *only* to the URLs listed there. So `git fleet add` writes out the existing destination before adding a new one, and `git fleet remove` collapses the configuration back to plain Git behaviour once the only destination left is the fetch URL.
+
+```sh
+git fleet status
+git fleet add git@github.com:user/project.git
+git fleet remove git@github.com:user/project.git --dry-run
+```
+
+## Focus Areas
+
+- Modelling remote configuration as a plan that can be previewed before it is applied, so `--dry-run` works on every command that changes something
+- Invoking Git directly as a subprocess rather than through a shell, avoiding quoting and injection problems entirely
+- Keeping the resulting configuration indistinguishable from what someone would write by hand
+- Testing against temporary repositories so the test suite never touches the configuration of the repository it runs in
+
+## Notes
+
+This is my first real project in OCaml, and the language has been a good fit for it. The remote state is a small, closed set of shapes, and the type system makes it awkward to forget a case — which matters when the tool's whole job is rewriting configuration that people's pushes depend on.
+
+Version 0.2.0 covers remote management: `status`, `add`, and `remove`. The longer-term goal is to cover the rest of the multi-host workflow, starting with creating a repository on several hosts at once.
diff --git a/sitemap.xml b/sitemap.xml
index 6cbbd24..59804ed 100644
--- a/sitemap.xml
+++ b/sitemap.xml
@@ -18,6 +18,11 @@
weekly
0.7
+
+ https://sowinski.dev/entry.html?type=projects&slug=git-fleet
+ 2026-10-17
+ 0.5
+
https://sowinski.dev/entry.html?type=projects&slug=schedule-generator-app
2023-08-01