Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

0. What is hawser?

hawser — the beam that binds the repos

Welcome! If you’ve ever worked on a product that lives in more than one Git repository, this course is for you. By the end of it you’ll be composing repos, running work across a whole fleet, opening cross-repo pull requests, and driving it all from a keyboard cockpit — comfortably.

Let’s start with the why. Because once the problem clicks, every command in haw suddenly makes sense.

Version control across many repositories

Many repos, one coordinated whole — that’s the puzzle hawser solves.

🎯 In this chapter, you’ll learn to…

  • Recognize the three taxes of a multi-repo product: version coordination, cross-repo PRs, and reproducibility.
  • Explain hawser in one line — a package.json + lockfile, but for a fleet of Git repos.
  • Hold the whole mental model in your head: manifest → lockfile → stacks.
  • Tell when hawser is the right tool for your world.

🧩 The problem: one product, many repos

Picture a real product. It’s rarely a single repository anymore. It’s a shared library, three or four services, an SDK, some infrastructure — each in its own Git repo, each with its own branches, its own CI, its own history.

A product split across many repositories

One product, scattered across a shelf of separate repos.

That split is good engineering. But it comes with a tax:

  • “Which versions go together?” Service A works with version 2.1 of the shared lib — but which commit is 2.1, exactly? And does your teammate have the same one?
  • “One feature, five pull requests.” A single change touches four repos. You branch each one by hand, open four PRs, and pray you merge them in the right order.
  • “It works on my machine.” Nobody can reproduce the exact set of commits that were live last March, because that set was never written down anywhere.
This is fine — a cartoon dog sipping coffee as the room burns

Managing ten repos and their versions by hand. This is fine. 🔥

Here’s the thing: a single repo already solved these problems years ago. Your package.json (or Cargo.toml) declares what you depend on, and a lockfile (package-lock.json, Cargo.lock) pins the exact resolved versions so everyone — you, your teammate, the CI runner — rebuilds an identical tree.

The mental model in one line: hawser is a package.json + lockfile, but for a fleet of Git repos instead of a fleet of npm packages.

⚓ What hawser does

hawser composes a software stack from many Git repos, pins it to a lockfile, and lets you drive every cross-repo build, PR, review, and CI run from one place.

It’s not a Git wrapper and it doesn’t reimplement Git. It’s the layer above Git — the part your package.json and your project board and your PR dashboard were quietly doing for a single repo, now done for many.

The command-line tool is called haw. It’s a single binary, written in Rust, with no runtime to install.

🧠 The mental model: manifest → lockfile → stacks

Three concepts carry the whole system. Learn these now and everything else follows.

  1. The manifest — haw.toml. This is your intent. You declare which repos exist, where they live, and which revision you want. Think of it as the dependencies block.

  2. The lockfile — haw.lock. This is the resolved reality. When you sync, haw pins every repo to an exact commit SHA and writes it here. You commit this file. Now a teammate — or CI, or an auditor — rebuilds the identical tree, byte for byte.

  3. Stacks. A stack is a named composition of repos. One manifest can define several stacks that share the same repos without copying them. (A stack in haw is just “these repos, together, under this name.”)

haw.toml   (intent)  ─────►  haw sync  ─────►  haw.lock   (pinned SHAs, committed)
   │                                               │
   └── declares repos + stacks                     └── the reproducible baseline

On disk there are no submodules, no symlinks, and no detached HEADs — each repo is a plain, complete Git clone. haw just keeps them in sync and coordinated.

🎯 When to reach for hawser

hawser is domain-agnostic — a repo is a repo, a build is whatever shell command you declare. It shines whenever a product is spread across repos:

If your world looks like……hawser gives you
Backend microservices — a feature spanning N services + a shared proto/libone branch + linked PRs across exactly the repos it touches
ML / data platforms — model + pipeline + serving infraone pinned, reproducible baseline of all three
Platform / infra — Terraform modules + Helm chartsa versioned, drift-checked deployed baseline
Mobile — an app + its in-house SDKapp and SDK changed and released in lockstep
Embedded / automotive — shared HAL/BSP reused across many ECUsaudit-grade, reproducible baselines + compliance evidence

The loop — compose → pin → change → build/test → govern — is the same in every one. Only the repos and the declared build commands differ. See Domains for how each maps on.

🚀 What you’ll be able to do by the end of this course

  • Write a haw.toml, sync it, and read the lockfile with confidence.
  • Run builds, tests, commands, and searches across an entire fleet in parallel.
  • Ship a feature across N repos as one changeset — branch, PR, land in order.
  • Live in the TUI cockpit and merge, approve, and inspect without leaving the terminal.
  • Extend haw with a plugin you wrote yourself.
  • Wire it into CI with reproducibility, signing, and audit evidence.

That’s a real, productive skill set — and we’ll build it one small step at a time.

And here’s where we’re going — the keyboard cockpit you’ll be living in by Chapter 4:

The haw cockpit: read the fleet, drill into any repo or PR, and act — without leaving the terminal.

🙌 Your turn

Before we touch a single command, do the thought experiment. Picture the last product you worked on that lived in more than one repo. Jot down:

  • How many repos was it, really?
  • The last time one feature forced you to open PRs in several of them at once — how did you keep track?
  • Could you reproduce, today, the exact set of commits that were live three months ago? Hold those answers. By Chapter 3 you’ll have a one-command answer to each.

✅ Recap

  • Splitting a product across many Git repos is normal, but it costs you version coordination, cross-repo PRs, and reproducibility.
  • hawser is a manifest + lockfile for a fleet of repos — like package.json + package-lock.json, but for whole repositories.
  • Three concepts: manifest (haw.toml, intent) → lockfile (haw.lock, pinned reality) → stacks (named compositions of repos).
  • The CLI is haw: one Rust binary, no runtime.
  • It fits any domain where a product spans repos.

👉 Next

Let’s get the tool onto your machine and open the cockpit for the first time → 1. Install and first run.