A serverless, database-free CMS built on Git plumbing.
"I'm using
git pushas my API endpoint."
git-cms treats your Git repository as a distributed, cryptographically verifiable database. Instead of files, it stores content as commit messages on "empty trees," creating a linear, append-only ledger for articles, comments, or any other structured data.
# Clone this repo
git clone https://github.com/flyingrobots/git-cms.git
cd git-cms
# Run setup (checks Docker + validates environment)
npm run setup# Option 1: See a demo (recommended first time)
npm run demo
# Option 2: Interactive menu
npm run quickstart
# Option 3: Just start the server
npm run dev
# Open http://localhost:4638Everything runs in Docker - completely safe for your local Git setup.
This project manipulates Git repositories at a low level. ALWAYS use Docker for testing.
The tests create, destroy, and manipulate Git repositories. Running low-level plumbing commands on your host filesystem is risky - a typo could affect your local Git setup. That's why we built Docker isolation into everything.
Read more: TESTING_GUIDE.md | docs/GETTING_STARTED.md | docs/CONTENT_ID_POLICY.md
- Database-Free: No SQL, No NoSQL. Just Git objects (Merkle DAG).
- Fast-Forward Only: Enforces strict linear history for provenance.
- Atomic Publishes: "Publishing" is just a pointer update (CAS).
- Infinite History: Every draft save is a commit. Scrub back to any point in time.
npm run dev
# OR
docker compose up appThe API and Admin UI will be available at http://localhost:4638.
npm test
# OR
docker compose run --rm test# From source (recommended until npm publish):
git clone https://github.com/flyingrobots/git-cms.git
cd git-cms
npm link
# After publish, global install will work:
# npm install -g git-cmsTo use git-cms securely, you should pair it with git-stargate.
Stargate is a minimal, bash-based Git gateway that enforces:
- Fast-Forward Only: No force pushes allowed.
- Signed Commits: Every update must be cryptographically signed by an authorized key.
- Mirroring: Validated updates are automatically mirrored to public repositories (like GitHub).
# Bootstrap a local stargate for testing
./scripts/bootstrap-stargate.sh ~/git/_blog-stargate.git
# Link it
git remote add stargate ~/git/_blog-stargate.git
git config remote.stargate.push "+refs/_blog/*:refs/_blog/*"Attachments are encrypted client-side (AES-256-GCM) before they are ever committed to the repository.
- Keys are managed securely via your OS Keychain (macOS/Linux/Windows).
- The "Stargate" receives only opaque, encrypted blobs.
- This effectively gives you "Row Level Security" on a file system—only users with the key can decrypt the assets.
Content is stored in refs/_blog/articles/<slug>.
echo "# Hello World" | git cms draft hello-world "My First Post"git cms list
# -> refs/_blog/articles/hello-world My First PostPublishing fast-forwards refs/_blog/published/<slug> to match the draft.
git cms publish hello-worldCopyright © 2026 James Ross. This software is licensed under the Apache License, Version 2.0
