carbon
Carbon ⚡
Automated commit-based version control, human-friendly YAML changelogs, and Crystal DSL for modern apps and shards.
Carbon eliminates manual version bumping, release friction, and commit desyncs through a clean, automated Git workflow:
$$\textbf{Version Format:} \quad \mathbf{\langle major \rangle.\langle minor \rangle.\langle commit_number \rangle}$$
commit_number: Automatically advances with every Git commit, ensuring every build and commit is distinctly and monotonically identified.major.minor: Left entirely under developer control to bump when cutting feature milestones or breaking changes.- Zero-Friction Git Hooks: Automatically stages updated manifests during
pre-commitso that each commit carries its exact chronological build number in its own Git tree. - YAML-Driven Changelogs (
changelog.yml$\to$CHANGELOG.md): Human-editable YAML source of truth that compiles into structured Markdown. Never overwrites existing entries, preserving all your hand-written descriptions, typo fixes, custom notes, and bullet choices permanently. - Multi-Target File Synchronization: Automatically updates
shard.yml,src/**/version.cr, and C/C++ version headers simultaneously, ending version drift across multi-component projects. - Git Tag & Release Manager: Seals changelog entries, tags annotated Git releases (
vX.Y.Z), updates floatinglatesttags, and pushes with zero friction. - Compile-Time Macro DSL: Injects version and Git metadata into your classes with zero runtime overhead via
Carbon.version!. - Repository Doctor (
carbon doctor): Audits Git health, hook integrity, and version consistency across all files, offering--fixto repair issues automatically. - Self-Versioning: Carbon automatically version-controls and changelogs itself on every commit.
How Carbon Version Control Works
sequenceDiagram
autonumber
actor Dev as Developer
participant Git as Git (pre-commit hook)
participant CLI as Carbon CLI (bump --hook)
participant Manifest as shard.yml & target files
participant History as Git History (HEAD)
Dev->>Git: git commit -m "..."
Git->>CLI: Invokes pre-commit hook
CLI->>History: Queries git rev-list --count HEAD (+1 upcoming)
CLI->>Manifest: Updates version to <major>.<minor>.<next_commit>
CLI->>Git: git add shard.yml (stages updated manifests)
Git->>History: Finalizes commit containing the bumped version
Git-->>Dev: Commit landed with version matched to history!
Why pre-commit Instead of post-commit?
Most version bouncers run on post-commit, which requires generating an unwanted secondary "bump version" commit or running git commit --amend, causing messy Git graphs and detached heads.
Carbon's pre-commit architecture computes the exact upcoming commit index ($N+1$), writes it to shard.yml (and any configured version.cr or C headers), and stages them. When Git seals the commit, the commit's tree already contains the exact version matching that commit.
Quick Start (30 Seconds)
1. Add to shard.yml
development_dependencies:
carbon:
github: sol-vin/carbon
branch: main
Run shards install.
2. Initialize Carbon in Your Repo
From your repository root, run:
bin/carbon init
This will:
- Format or create
shard.ymlto themajor.minor.commit_numberstandard (default:0.1.0). - Install a non-destructive Git
pre-commithook in.git/hooks/pre-commit. - Create a human-friendly
changelog.ymland compileCHANGELOG.md.
3. Commit As Usual!
git commit -m "feat(api): add automatic stream parsing"
[carbon] Auto-bumped version to 0.1.1 (commit #1)
[main 7f2e1a0] feat(api): add automatic stream parsing
3 files changed, 52 insertions(+)
Your shard.yml, target files, and CHANGELOG.md are automatically updated and staged with the commit!
Automatic Changelogs (changelog.yml $\to$ CHANGELOG.md)
Most changelog generators either destroy hand-written edits or produce unformatted walls of text. Carbon solves this by decoupling the human-editable source (changelog.yml) from the compiled Markdown (CHANGELOG.md).
flowchart LR
DevEdits["Developer Edits (typo fixes, notes)"] --> YAML["changelog.yml (Source of Truth)"]
GitCommits["Git Commits (feat, fix, perf)"] -->|Append New Only| YAML
YAML -->|Compile| MD["CHANGELOG.md (Output)"]
Absolute Non-Destructive Invariant
[!IMPORTANT] Carbon NEVER overwrites an existing entry. Each entry is tracked by its Git
hashand subject. When new commits are scanned, Carbon only appends unseen commits. If you edit a description, fix a typo, rephrase a bullet, remove sensitive text, or change bullet icons inchangelog.yml, your changes are 100% permanent.
Layout of changelog.yml
settings:
title: "CARBON CHANGELOG"
output_file: "CHANGELOG.md"
ascii_banner: |
____ ___ ____ ____ ___ _ _
/ ___/ _ \| _ \| __ ) / _ \| \ | |
| | | |_| | |_) | _ \| | | | \| |
| |__| _ | _ <| |_) | |_| | |\ |
\____/_/ \_|_| \_\____/ \___/|_| \_|
header: |
All notable changes to this project are documented in this file.
Maintained automatically by Carbon.
# Category definitions, custom titles, and default bullets
categories:
breaking:
title: "💥 Breaking Changes"
bullet: "▲"
features:
title: "✨ Features & Improvements"
bullet: "✦"
fixes:
title: "🐛 Bug Fixes"
bullet: "✓"
perf:
title: "⚡ Performance Optimizations"
bullet: "🚀"
docs:
title: "📚 Documentation"
bullet: "📖"
maintenance:
title: "🛠️ Chores & Tooling"
bullet: "•"
releases:
- version: "0.1.2"
date: "2026-10-01"
status: active # 'active' (receives new commits) or 'released'
summary: "Stabilization release with dynamic macro version assertions and test hardening."
entries:
- type: test
description: "dynamically assert macro version against shard.yml"
bullet: "✓"
hash: "1e4bc97"
author: "Ian Rash"
- version: "0.1.1"
date: "2026-10-01"
status: released
summary: "Initial public release of Carbon version control shard."
entries:
- type: feat
description: "initial commit for carbon version control shard"
bullet: "✦"
badge: "[CORE]"
hash: "55eff71"
author: "Ian Rash"
Custom Bullets and Badges
You can customize bullets on a per-entry level or per-category level:
bullet: "🚀"or"✓","✦","▲","•"badge: "[SECURITY]"or"[CLI]","[BREAKING]"
To synchronize or compile your changelog:
# Pull new commits and compile CHANGELOG.md
carbon changelog
# Preview without writing to disk
carbon changelog --dry-run
# Recompile existing changelog.yml to CHANGELOG.md after manual editing
carbon changelog --compile
Multi-Target File Synchronization
In complex Crystal codebases, version numbers often exist in multiple places:
shard.yml(version: 0.2.0)src/my_app/version.cr(VERSION = "0.1.0")- C/C++ bridge headers (
#define LIB_VERSION "0.1.0")
Carbon automatically locates and synchronizes all version constants whenever you bump or set a version:
# Bumps minor version across shard.yml, src/**/version.cr, and headers
carbon bump --minor
# Explicitly set major and minor
carbon set 2.0
Tagging & Release Management
Carbon provides a single command to tag and seal releases:
carbon tag v1.0.0 --message="Initial stable release" --push
This will:
- Seal the current active release in
changelog.yml(marksstatus: released, stamps today's date). - Recompile
CHANGELOG.md. - Create an annotated Git tag
v1.0.0. - Update the floating
latestGit tag to point to this release. - Push the branch and both tags (
v1.0.0,latest) toorigin.
Repository Health Doctor (carbon doctor)
Audit your project's versioning and release hygiene with carbon doctor:
carbon doctor
Carbon Doctor Audit Findings:
1. [Hooks] Carbon pre-commit hook is not installed in .git/hooks/pre-commit [auto-fixable]
2. [Version] src/my_app/version.cr version (0.1.0) differs from shard.yml (0.1.2) [auto-fixable]
Run 'carbon doctor --fix' to automatically repair fixable issues.
To automatically repair detected issues:
carbon doctor --fix
Non-Destructive Git Hook Chaining
If your project already uses a pre-commit hook (for linters, formatting, or tests), Carbon will never overwrite it. It encapsulates its commands within explicit managed markers:
#!/bin/sh
# Existing user linters:
crystal tool format --check
# >>> CARBON AUTO-VERSION HOOK >>>
# Generated by Carbon. Do not edit this block manually.
if [ -f "bin/carbon" ]; then
./bin/carbon bump --hook
elif [ -f "bin/carbon.exe" ]; then
./bin/carbon.exe bump --hook
elif command -v carbon >/dev/null 2>&1; then
carbon bump --hook
elif command -v crystal >/dev/null 2>&1; then
if [ -f "src/carbon/cli.cr" ]; then
crystal run src/carbon/cli.cr -- bump --hook
elif [ -f "lib/carbon/src/carbon/cli.cr" ]; then
crystal run lib/carbon/src/carbon/cli.cr -- bump --hook
fi
fi
# <<< CARBON AUTO-VERSION HOOK <<<
Running carbon hook uninstall safely strips only Carbon's block and restores your original hook.
Crystal Macro DSL
Access version metadata in your app with zero runtime cost:
require "carbon"
module MyApp
# Embeds version constants at compile time from shard.yml
Carbon.version!
end
puts "Running #{MyApp::NAME} v#{MyApp::VERSION}"
# => "Running MyApp v0.1.2"
# Comparison support:
if MyApp.carbon_version >= Carbon::Version.parse("0.1.0")
puts "Enabled!"
end
Full CLI Reference
carbon <command> [options]
| Command | Options | Description |
|---|---|---|
carbon init |
--no-hook, --no-changelog, --major=N, --minor=N |
Initialize Carbon in the project, install Git hook & changelog |
carbon bump |
--commit, --minor, --major, --hook, --stage |
Bump version (default: next commit count) |
carbon sync |
--stage |
Align shard.yml & target files with exact Git commit count |
carbon set <major.minor> |
--stage |
Set major and minor versions (e.g. carbon set 1.2) |
carbon get, version |
-p, --porcelain |
Display current project version |
carbon check |
(none) | Verify whether shard.yml is in sync with Git commits |
carbon changelog |
--sync, --compile, --dry-run, --from=REF, --to=REF |
Manage changelog.yml & compile CHANGELOG.md |
carbon tag, release |
[version], --latest, --no-latest, --push, -m MSG |
Seal changelog, create release tag, & update floating latest |
carbon doctor |
--fix |
Audit repository health, version parity, and auto-repair issues |
carbon hook |
install, uninstall, status |
Manage Git pre-commit hook non-destructively |
carbon help |
(none) | Display help manual |
GitHub Actions CI Integration
Add .github/workflows/ci.yml to your project to run tests, formatting checks, and verify version integrity:
name: CI
on:
push:
branches: [ main, master ]
pull_request:
branches: [ main, master ]
jobs:
test:
name: Test & Build
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0 # Full commit history required for commit counting
- name: Update apt package index
run: sudo apt-get update
- name: Install Crystal
uses: crystal-lang/install-crystal@v1
with:
crystal: latest
- name: Check Formatting
run: crystal tool format --check
- name: Run Test Specifications
run: crystal spec --error-trace
- name: Build Carbon Binary
run: shards build carbon
- name: Verify Version Alignment & Changelog
run: |
bin/carbon check
bin/carbon changelog --compile
bin/carbon doctor
Running Specs
# Run full test specifications (47 passing specs)
crystal spec --error-trace
# Build CLI binary
shards build carbon
License
MIT License. Copyright (c) 2026 Ian Rash. See LICENSE for details.
carbon
- 0
- 0
- 0
- 2
- 0
- about 1 hour ago
- October 1, 2026
MIT License
Thu, 01 Oct 2026 21:14:58 GMT