---
title: "Hangar CLI"
slug: hangar-cli
date: 2025-08-22
url: https://mohammadhameed.dev/projects/hangar-cli
status: published
tags: ["systems", "robotics"]
technologies: ["Go", "SQLite", "Cobra"]
---

{/* Sample case study for the design refresh — repo is a placeholder link
    until the first public cut; metrics are illustrative. */}

Small drone fleets run on a spreadsheet, a shared calendar, and a mechanic's
memory. That works until a battery that needs retirement takes off anyway.
Hangar is the tool I wished existed on every team I've worked on: boring,
local, and impossible to argue with.

## Six commands

```bash
hangar log flight <airframe> --hours 1.4 --pilot m.hameed
hangar battery cycle <pack-id>          # counts against rated life
hangar gate check                       # exits non-zero if anything is overdue
hangar report week                      # flight hours, cells retired, tail numbers down
```

No server. A single SQLite file in the repo — versioned like the code it
guards. The CI idea that matters: *gate check* in a pre-flight script turns
"the airframe is grounded" from an argument into an exit code.

<Callout type="outcome">
On one team that adopted it, the pre-takeoff conversation shrank from fifteen
minutes of "is that pack still good?" to one command that answers for
every tail number at once.
</Callout>

<Figure src="/images/projects/hangar-cli-alt.svg" alt="gate check output" caption="One snapshot: what can fly, what can't, and why." />

## Design rules I held to

- **No cloud, no accounts, no dashboards.** If the hangar Wi-Fi is down,
  the tool works better than the alternative.
- **The ledger is the product.** Every command appends; nothing is deleted,
  audit lives forever, which is exactly what an aviation regulator wants.
- **Non-zero exits are safety features.** In automation, a green light must
  mean *verified*, not *probably fine*.

## Why it exists in public

Because every operations team I've joined rebuilt some version of this at
2 a.m. before a demo. If that's your Tuesday, [steal it, or tell me what the
seventh command should be](/contact).
