# Changelog

All notable changes to `@hermes-deploy/cli` are documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

Releases from `1.0.0` onward are managed by
[release-please](https://github.com/googleapis/release-please) and follow
[Conventional Commits](https://www.conventionalcommits.org/). Anything below
the `1.0.0` heading was generated by hand from the M1–M4 commit history.

## [1.6.0](https://github.com/PaulCailly/hermes-deploy/compare/v1.5.0...v1.6.0) (2026-09-01)


### Features

* gateway watchdog + self-healing SSH ingress ([#19](https://github.com/PaulCailly/hermes-deploy/issues/19)) ([722c5b0](https://github.com/PaulCailly/hermes-deploy/commit/722c5b0df2c30a0d05a68d88bcda9f4959c677ec))

## [1.5.0](https://github.com/PaulCailly/hermes-deploy/compare/v1.4.0...v1.5.0) (2026-08-05)


### Features

* **cron:** declarative [[hermes.cron]] reconciled on deploy ([f00b894](https://github.com/PaulCailly/hermes-deploy/commit/f00b8941d07252e2f53ac20e20f08ac6558dc644))


### Bug Fixes

* **cron:** reconcile observed box state; dedupe; all fields; cron-only schedules ([1d97581](https://github.com/PaulCailly/hermes-deploy/commit/1d9758176e4dbeeb49cd8c7a48d0962b846b2528))
* **secret:** encrypt to a temp file and atomically replace — never leave plaintext ([2628324](https://github.com/PaulCailly/hermes-deploy/commit/2628324262d734e13b747aa7adbbf320dae7b80f))


### Documentation

* add design spec for Jarvis Lambda logs integration ([23e56e7](https://github.com/PaulCailly/hermes-deploy/commit/23e56e7fec335b3c13753df3f74eb9141925d323))
* add implementation plan for Jarvis Lambda logs ([0f5b8e7](https://github.com/PaulCailly/hermes-deploy/commit/0f5b8e7194c0cac38f2ad58cb7f19ef01abf561d))

## [1.4.0](https://github.com/PaulCailly/hermes-deploy/compare/v1.3.0...v1.4.0) (2026-05-03)


### Features

* **api:** add /curator and /models backend routes ([b4d1f0e](https://github.com/PaulCailly/hermes-deploy/commit/b4d1f0e5d7bd637c07fe2f35875814f2b90fe78a))
* **api:** add useCurator and useModels hooks ([2be52aa](https://github.com/PaulCailly/hermes-deploy/commit/2be52aa9ddb5f47008544e9bb601a8c34b1a213e))
* **backend:** parameterize HERMES_HOME in agent-data-source ([e9dff91](https://github.com/PaulCailly/hermes-deploy/commit/e9dff91396dc22366e67a7667ad0465bc430047d))
* **backend:** profile-aware agent-data routes with discovery endpoint ([cbd4276](https://github.com/PaulCailly/hermes-deploy/commit/cbd427693556db7e627d5ddedf320a9c6333decf))
* **backend:** profile-aware config routes ([8b1da7d](https://github.com/PaulCailly/hermes-deploy/commit/8b1da7d9cef4ed4579e038ca53740dc81a217037))
* **backend:** profile-aware org stats and activity ([4aa5340](https://github.com/PaulCailly/hermes-deploy/commit/4aa5340754b6732824e50dd0e2173da1cd953dfa))
* **frontend:** add CuratorTab component ([d4a47f8](https://github.com/PaulCailly/hermes-deploy/commit/d4a47f8fd48e479a95b1bc99db731dc9197276ba))
* **frontend:** add ModelsTab component ([aa873be](https://github.com/PaulCailly/hermes-deploy/commit/aa873bea228e0e64bfe494d32850d5dafe36a45c))
* **frontend:** add ProfileSwitcher pill bar component ([217543e](https://github.com/PaulCailly/hermes-deploy/commit/217543e12280726ca97a3542852f5ff504d9e215))
* **frontend:** profile-aware route model and API hooks ([d2aeaf1](https://github.com/PaulCailly/hermes-deploy/commit/d2aeaf1c70022184a634789fb838919e6597cd32))
* **frontend:** show per-profile stats in OrgDashboard ([7af4c23](https://github.com/PaulCailly/hermes-deploy/commit/7af4c23682206bee29b71190d2b57b0467a4eec2))
* **frontend:** wire CuratorTab and ModelsTab into agent workspace ([d6d3511](https://github.com/PaulCailly/hermes-deploy/commit/d6d3511d94f0ab4b3786c40d1efb17d5534593f0))
* **frontend:** wire profile through AgentWorkspace and all tabs ([4dd7fdf](https://github.com/PaulCailly/hermes-deploy/commit/4dd7fdff5a5906c4415029971ded33ae3ca17156))
* **orchestrator:** profile file upload in deploy and update flows ([a537410](https://github.com/PaulCailly/hermes-deploy/commit/a53741022511965dd5b02da30408fb07e433974f))
* **schema:** add optional profile_hashes to state-toml deployments ([99c29ea](https://github.com/PaulCailly/hermes-deploy/commit/99c29eaca2f765ac73959671539bf5e72991e8cd))
* **schema:** add ProfileSchema and [[hermes.profiles]] support to HermesTomlSchema ([d0bd694](https://github.com/PaulCailly/hermes-deploy/commit/d0bd694641206a2ad6bfb939a0bc56a602fc48ce))
* **types:** add Curator and Models response interfaces ([b8362c2](https://github.com/PaulCailly/hermes-deploy/commit/b8362c2134e9040b7ba02a6099838cdf2838330a))
* **types:** add curator and models to AGENT_TABS union ([e11284d](https://github.com/PaulCailly/hermes-deploy/commit/e11284d4a9467da84c968b93c3aa6f22a22f7e05))


### Bug Fixes

* address PR review findings ([ac4fe31](https://github.com/PaulCailly/hermes-deploy/commit/ac4fe313dd47bf1adbd67ca17f0534403b2bc9dc))
* address PR review round 2 ([fd3e975](https://github.com/PaulCailly/hermes-deploy/commit/fd3e9758cf3c8d5f104636fcf99776c2eaced061))
* address PR review round 3 ([f555df2](https://github.com/PaulCailly/hermes-deploy/commit/f555df2f8a8b7436e557b9e9ca927266d3da296e))
* **dashboard:** auto-build web assets if missing ([1e0ca9b](https://github.com/PaulCailly/hermes-deploy/commit/1e0ca9bcde7083a9566c040ea3e9e0bbd4b2e292))
* **gcp:** idempotent provisioner, DNS record fix, dashboard listing, and update healthcheck ([87f814f](https://github.com/PaulCailly/hermes-deploy/commit/87f814f1e4531c46158cae38f43a1d994c128a1a))
* **ssh:** prevent SFTP handle leak in uploadFile ([39d3fe5](https://github.com/PaulCailly/hermes-deploy/commit/39d3fe544f6b70781b672bcb338f30cb5f884c2f))
* **test:** add missing zone.record mock in GCP DNS tests ([ba7428c](https://github.com/PaulCailly/hermes-deploy/commit/ba7428c8e3f831e985098e295c32f5badf9859bf))
* **tests:** add profiles field to test config objects ([85924e3](https://github.com/PaulCailly/hermes-deploy/commit/85924e3e7bcb207ac4948a33c5f05c70d2712a0a))
* **types:** add explicit types to ls.ts factory callback params ([5df5571](https://github.com/PaulCailly/hermes-deploy/commit/5df5571d7530f4ffbb77dfc03605671f28251d7a))


### Documentation

* profiles support design spec and implementation plan ([6d3ac08](https://github.com/PaulCailly/hermes-deploy/commit/6d3ac086cb1f5e419552601fac1eced030085477))
* v0.12.0 upgrade implementation plan ([f016f2a](https://github.com/PaulCailly/hermes-deploy/commit/f016f2af9b2e54e67b68774cbf175d1626f9eba1))
* v0.12.0 upgrade, curator & models dashboard design spec ([f2e37ec](https://github.com/PaulCailly/hermes-deploy/commit/f2e37ec0e7e502e5f6badfa17dad2b7c9b61cc9a))

## [1.3.0](https://github.com/PaulCailly/hermes-deploy/compare/v1.2.1...v1.3.0) (2026-04-21)


### Features

* version management, update checking, and one-click upgrade ([#15](https://github.com/PaulCailly/hermes-deploy/issues/15)) ([ba4c9f6](https://github.com/PaulCailly/hermes-deploy/commit/ba4c9f601efa5fa99004916a9423b6e953063a6b))
* Webhooks tab, Plugins tab, and dev startup script ([0e69eb5](https://github.com/PaulCailly/hermes-deploy/commit/0e69eb5cee288a754159a91bd25ac56b88d50f58))

## [1.2.1](https://github.com/PaulCailly/hermes-deploy/compare/v1.2.0...v1.2.1) (2026-04-19)


### Bug Fixes

* **ci:** use Node 24 for npm trusted publishing ([e2efd85](https://github.com/PaulCailly/hermes-deploy/commit/e2efd851e002e3f010565631c900accde7dc27a5))

## [1.2.0](https://github.com/PaulCailly/hermes-deploy/compare/v1.1.1...v1.2.0) (2026-04-19)


### Features

* add Gemini model icon and fallback cost estimation ([68e2f0a](https://github.com/PaulCailly/hermes-deploy/commit/68e2f0a831d5289f2acf436fb22337ece3b7902f))
* add React TypeScript web dashboard with full CLI parity ([#9](https://github.com/PaulCailly/hermes-deploy/issues/9)) ([2b9976d](https://github.com/PaulCailly/hermes-deploy/commit/2b9976db49d839d5298c6aa552249470012adce0))
* domain management with DNS, nginx, TLS & health verification ([#12](https://github.com/PaulCailly/hermes-deploy/issues/12)) ([ba4358b](https://github.com/PaulCailly/hermes-deploy/commit/ba4358bd1f12af3ebdc23a52b1e83f88b9a12d71))


### Bug Fixes

* use falsy check for cost fallback (0 is not null) ([0db2c47](https://github.com/PaulCailly/hermes-deploy/commit/0db2c474637638b3e54fd1f94d9b026c257d9aab))

## [1.1.1](https://github.com/PaulCailly/hermes-deploy/compare/v1.1.0...v1.1.1) (2026-04-11)


### Bug Fixes

* **package:** rename to @paulcailly/hermes-deploy for first publish ([#6](https://github.com/PaulCailly/hermes-deploy/issues/6)) ([0496e20](https://github.com/PaulCailly/hermes-deploy/commit/0496e20f5d4e6b5890330596c742b5d76ea6d279))

## [1.1.0](https://github.com/PaulCailly/hermes-deploy/compare/v1.0.0...v1.1.0) (2026-04-11)


### Features

* **ci:** implement scripts/e2e-sweep.mjs for nightly resource cleanup ([10a4398](https://github.com/PaulCailly/hermes-deploy/commit/10a43985877168f204fe6ede4f6c37588f1771a8))
* **cli:** destroy command with confirmation prompt ([65d91f9](https://github.com/PaulCailly/hermes-deploy/commit/65d91f9ecfa48678814d7cfc6cdb1a8dc8178bf9))
* **cli:** init command scaffolds hermes.toml + SOUL.md + .gitignore ([9d2cd93](https://github.com/PaulCailly/hermes-deploy/commit/9d2cd93e7f88726b13916baca24e8853e48cad08))
* **cli:** init scaffolds M3 file set (hermes.toml + config.yaml + SOUL.md + sops) ([fc56725](https://github.com/PaulCailly/hermes-deploy/commit/fc56725bbe2cc971b3636620993ab13c7d76d978))
* **cli:** key export/import/path subcommands for multi-machine sync ([825ccc8](https://github.com/PaulCailly/hermes-deploy/commit/825ccc869860054290c01901a02b234b10c0c182))
* **cli:** logs command streaming journalctl until Ctrl-C ([7ecccba](https://github.com/PaulCailly/hermes-deploy/commit/7ecccba4699428df99355e4a7a872a7a0174d5b5))
* **cli:** ls command listing all deployments with stored + live status ([b77dd67](https://github.com/PaulCailly/hermes-deploy/commit/b77dd673c12a57ec1e169db8ff14ef79062ba14c))
* **cli:** secret commands operate on dotenv-format secrets.env.enc ([a6c005f](https://github.com/PaulCailly/hermes-deploy/commit/a6c005f851252b7927657342c2bf5e8d33f2c77e))
* **cli:** secret set/get/rm/list/edit subcommands via sops shell-out ([76a3570](https://github.com/PaulCailly/hermes-deploy/commit/76a35709791b8d5deb87c10433005608a1afe26c))
* **cli:** shared resolveDeployment + --name/--project flags everywhere ([2a764a2](https://github.com/PaulCailly/hermes-deploy/commit/2a764a246309bcb62d7b1a0443972f762bdac3a5))
* **cli:** ssh command exec'ing system ssh with stored key ([06f8d8a](https://github.com/PaulCailly/hermes-deploy/commit/06f8d8a9639378a91bb5740dc127170f0fb358f2))
* **cli:** status command showing live and stored state ([3b99c87](https://github.com/PaulCailly/hermes-deploy/commit/3b99c874266ec0982d8862288f8f809930a58d30))
* **cli:** up command and argv router skeleton ([5f553f3](https://github.com/PaulCailly/hermes-deploy/commit/5f553f38587430c47ddce10f8eeb7d5133c05561))
* **cli:** update command for config-only redeploys ([6b174ff](https://github.com/PaulCailly/hermes-deploy/commit/6b174ff11a5df05bedfc026b0f375c1dbe6510e8))
* **cli:** wire GCP through orchestrator and remove provider gate ([58d2329](https://github.com/PaulCailly/hermes-deploy/commit/58d2329b47ffda410d4d0a3c216d17c9258f6d7a))
* **cloud/aws:** add status() reading EC2 instance state ([e38d188](https://github.com/PaulCailly/hermes-deploy/commit/e38d188bf5126d5e724bff42a3c2aa7055d61df9))
* **cloud/aws:** detect deployer public IP for SSH allow rule ([d2904c3](https://github.com/PaulCailly/hermes-deploy/commit/d2904c3e8e2d1983eacc106d940087d8dbc6142c))
* **cloud/aws:** expose cloud.disk_gb to override the AMI's tiny default ([13987dd](https://github.com/PaulCailly/hermes-deploy/commit/13987dd2045353aaa451deac5ad3c4961211cdbc))
* **cloud/aws:** provision sequence with rollback on failure ([7ca6130](https://github.com/PaulCailly/hermes-deploy/commit/7ca6130f5215a584cc1e9c2a5991de991679ad89))
* **cloud/aws:** resolve latest NixOS AMI with 1-hour cache ([2363aa0](https://github.com/PaulCailly/hermes-deploy/commit/2363aa0f7a4108a89ca70f36d4f82d4999d5f014))
* **cloud/aws:** wrap operations behind AwsProvider class ([c4c51b7](https://github.com/PaulCailly/hermes-deploy/commit/c4c51b780032c42d2bac4d317caad80d7add2f09))
* **cloud/gcp:** destroy with idempotent not-found handling ([0d28336](https://github.com/PaulCailly/hermes-deploy/commit/0d283368ac30a40033ab8ae7d6987e9ccf085dd7))
* **cloud/gcp:** firewall rule reconciliation with PATCH support ([22ff13e](https://github.com/PaulCailly/hermes-deploy/commit/22ff13eee5aab1105460e692717924c7b6e25788))
* **cloud/gcp:** GcpProvider class + factory wiring ([7539cc5](https://github.com/PaulCailly/hermes-deploy/commit/7539cc525612ef23af24232f53d8cf5b0d192db5))
* **cloud/gcp:** instance status with GCE state mapping ([c5c551b](https://github.com/PaulCailly/hermes-deploy/commit/c5c551b10e181e3350d4b32b84b8cd242baba00c))
* **cloud/gcp:** NixOS GCE image resolution with 1h cache ([78606cd](https://github.com/PaulCailly/hermes-deploy/commit/78606cdfb98466d35b75b351306d625901b4909e))
* **cloud/gcp:** nixos-infect bootstrap (boot Debian, convert to NixOS) ([3405859](https://github.com/PaulCailly/hermes-deploy/commit/340585923cff5fa160ee172d20196925d3157202))
* **cloud/gcp:** provisioning with static IP, firewall rules, instance, and rollback ([96d5f3c](https://github.com/PaulCailly/hermes-deploy/commit/96d5f3cb953667d81be01f5e46075b3227829e16))
* **cloud:** add @google-cloud/compute dep + update GcpResources schema + SIZE_MAP_GCP ([5ec2973](https://github.com/PaulCailly/hermes-deploy/commit/5ec29738949d685812745d05c82b4eb5587bc28a))
* **cloud:** add CloudProvider interface, types, and error classes ([df3b813](https://github.com/PaulCailly/hermes-deploy/commit/df3b813535f79ea206260d6374b324b1a0981ec0))
* **cloud:** add reconcileNetwork to CloudProvider with AWS implementation ([3e084df](https://github.com/PaulCailly/hermes-deploy/commit/3e084df07f5be39cf1402f0ee0a6519e85fe94dc))
* **crypto:** generate ed25519 SSH keypairs ([7f50757](https://github.com/PaulCailly/hermes-deploy/commit/7f50757c19eca0c1e781f99420f0cb35403ef7f8))
* **crypto:** wrap age-keygen for per-deployment age keypairs ([9330e5a](https://github.com/PaulCailly/hermes-deploy/commit/9330e5a7ae112bd1adb5d2a11bd247d4e9840c92))
* **init:** M3 templates for hermes.toml + config.yaml + gitignore ([d032a54](https://github.com/PaulCailly/hermes-deploy/commit/d032a547e6d81f7ccaea8a9fe29534b3b9c7d3a9))
* **nix-gen:** configuration.nix declares hermes-env dotenv sops secret ([edf81db](https://github.com/PaulCailly/hermes-deploy/commit/edf81dbd4ffb8c44a117fb63a9d0f290f93914cd))
* **nix-gen:** flake.nix conditionally includes hermes.extra.nix ([e90391b](https://github.com/PaulCailly/hermes-deploy/commit/e90391b02a3de6e7b2177616095fc22aa1e5afcf))
* **nix-gen:** generate hermes.nix and configuration.nix from toml ([e626873](https://github.com/PaulCailly/hermes-deploy/commit/e6268730360d2081e1364ed6dc3dc9fef2546ef0))
* **nix-gen:** optional Cachix substituter via [hermes.cachix] ([9bdd0f3](https://github.com/PaulCailly/hermes-deploy/commit/9bdd0f3a2c600bca126eabb2dd2df1c7df781c06))
* **nix-gen:** rewrite generateHermesNix for M3 schema (configFile + documents + environment) ([2131599](https://github.com/PaulCailly/hermes-deploy/commit/21315991cc8c2d434fc5f71c90e2c6bbc8031b87))
* **orchestrator:** implement deploy flow phases 1-5 ([84553bc](https://github.com/PaulCailly/hermes-deploy/commit/84553bcd8d317fe4fdf2001a75b1ec9bb557fcfb))
* **orchestrator:** implement destroy flow ([d7fe211](https://github.com/PaulCailly/hermes-deploy/commit/d7fe2112720cd18ea53d84caea8048eb706f3c7b))
* **orchestrator:** plain-text progress reporter for M1 ([5364817](https://github.com/PaulCailly/hermes-deploy/commit/53648174247bd6545bb57b1f765240ea231c0c69))
* **orchestrator:** runUpdate flow with hash short-circuit and shared helpers ([3903954](https://github.com/PaulCailly/hermes-deploy/commit/3903954490e10a9c7d1fdfb1974c780570e2660c))
* **orchestrator:** upload config.yaml + documents + nix_extra; hash all of them ([e0f29ec](https://github.com/PaulCailly/hermes-deploy/commit/e0f29ecdd85ea02c0a8f7c2a8969d42ef7527c63))
* **remote-ops:** poll systemctl is-active with journal tail on failure ([161952e](https://github.com/PaulCailly/hermes-deploy/commit/161952e043e00e73189c862686900847c4d072af))
* **remote-ops:** run nixos-rebuild over SSH with rolling tail ([d349aea](https://github.com/PaulCailly/hermes-deploy/commit/d349aeab7e6de656fc12e7817087d5353c2bd7c3))
* **remote-ops:** ssh2 session wrapper with exec, stream, and sftp upload ([61a006b](https://github.com/PaulCailly/hermes-deploy/commit/61a006bfd44c42198dc436137753b897112310c1))
* **remote-ops:** wait-for-ssh with TCP poll and backoff ([d5498ee](https://github.com/PaulCailly/hermes-deploy/commit/d5498eeb9154d1b1a93443a2e62e82363cbda185))
* **schema:** add TOML loader with validation and typed errors ([3eecb57](https://github.com/PaulCailly/hermes-deploy/commit/3eecb57bc5fdc7a9b3361104708ad249252a2aae))
* **schema:** add zod schema for hermes.toml with full validation ([8afe9b0](https://github.com/PaulCailly/hermes-deploy/commit/8afe9b05646991d6bde63f112828f53170525fe7))
* **schema:** add zod schema for state.toml ([6ee7455](https://github.com/PaulCailly/hermes-deploy/commit/6ee74556cbe151a0b15ba385daea7c37b2baad7d))
* **schema:** rewrite hermes.toml for M3 (drops model/soul/platforms, adds documents/environment) ([9d2ed94](https://github.com/PaulCailly/hermes-deploy/commit/9d2ed944bc5af3380b5e494882ee61b194b7077e))
* **sops:** bootstrap .sops.yaml and encrypted placeholder secrets file ([3677eaa](https://github.com/PaulCailly/hermes-deploy/commit/3677eaa5ca9b7f73c9d86c0b3d2911d47f8e5c78))
* **sops:** bootstrap secrets.env.enc as dotenv-format sops file ([41fbbe7](https://github.com/PaulCailly/hermes-deploy/commit/41fbbe7a7b49b7b4f8c13c738874785b8d8f5bbb))
* **state:** add config hash helper ([2f08b56](https://github.com/PaulCailly/hermes-deploy/commit/2f08b56a4457bb4d5e1d4df559b3bfcaa9d5c9be))
* **state:** add state store with locking, backup, and validation ([49fa54c](https://github.com/PaulCailly/hermes-deploy/commit/49fa54c8b39b05b774c92a618e29929838815992))
* **state:** add XDG-aware path helpers ([a6609d7](https://github.com/PaulCailly/hermes-deploy/commit/a6609d7d24dd2b71f7b022de9533657795b42c78))
* **state:** bump schema_version to 2 for M3 (no-op deployment shape migration) ([f1154e2](https://github.com/PaulCailly/hermes-deploy/commit/f1154e23ce793fe7f468e6b729ed9789e3501a53))
* **state:** schema migration runner with v0→v1 fixture ([d0afab4](https://github.com/PaulCailly/hermes-deploy/commit/d0afab475163a56ca854ffd5bfe8ff6062209cf4))
* **ui:** InkReporter with DeployTimeline + auto-engage on TTY ([e2d3bb2](https://github.com/PaulCailly/hermes-deploy/commit/e2d3bb2251385ba8fdd46df963ea78c0923fc9c5))
* v1 nice-to-haves — adopt, --json, library entry, E2E scaffold ([d7ba0f3](https://github.com/PaulCailly/hermes-deploy/commit/d7ba0f3799e8b141a9d5064130dad6251472dce5))


### Bug Fixes

* **build:** suppress Node ExperimentalWarning chatter on every CLI run ([666e0b4](https://github.com/PaulCailly/hermes-deploy/commit/666e0b47a5a4fc2e7234517fcf3b519c5929361c))
* **cli:** key path now errors when the deployment's age key is missing ([0e6b8e8](https://github.com/PaulCailly/hermes-deploy/commit/0e6b8e8fd6e3bb577b1670fddbe3a991be216eed))
* **cli:** ls --watch errors instead of silently lying about itself ([608ee4d](https://github.com/PaulCailly/hermes-deploy/commit/608ee4dc78631c92b8c95d93ca5a712dfd018699))
* **cli:** pass zone+project from state to provider for GCP destroy/status/update ([c5781ca](https://github.com/PaulCailly/hermes-deploy/commit/c5781ca734e8eb2d69026fea3126d106f4ec34f8))
* **cli:** remove placeholder secret after first real secret set ([e0e0a00](https://github.com/PaulCailly/hermes-deploy/commit/e0e0a00fc545bc8e445f8175c4376b34a8f16ffd))
* **cli:** secret edit refuses to run without a TTY ([2164b3c](https://github.com/PaulCailly/hermes-deploy/commit/2164b3c35cb47f38ad0ec33577e5dce325df99c3))
* **cloud/aws:** bump NixOS AMI pattern from 24.05 to 25.11 ([f49f7f9](https://github.com/PaulCailly/hermes-deploy/commit/f49f7f940efc4b56089c8760615de277d5127651))
* **cloud/aws:** wait for instance to be running before associating EIP ([dfbf5db](https://github.com/PaulCailly/hermes-deploy/commit/dfbf5dbcb047694e3649436985d1c10fc2678885))
* **cloud/gcp:** bake SSH public key into NixOS config for persistent root access ([e14a9ed](https://github.com/PaulCailly/hermes-deploy/commit/e14a9ed03cae632a849da4a17247e8e4dd1aaac5))
* **cloud/gcp:** check status==='DONE' not done===true in operation waiters ([772df5c](https://github.com/PaulCailly/hermes-deploy/commit/772df5cbcf7803e6ecb9b633c31da68d956d1405))
* **cloud/gcp:** enable root SSH on Debian GCE via startup script ([9758d85](https://github.com/PaulCailly/hermes-deploy/commit/9758d850392f81f3f1c43f57f117902f23f958c0))
* **cloud/gcp:** replace .promise() with v6 SDK operation waiters + wire profile→project ([b650e70](https://github.com/PaulCailly/hermes-deploy/commit/b650e70b7e5f11deebda70fe4ac05d92c89c79df))
* **cloud/gcp:** use image family URL instead of listing nixos-cloud images ([003404c](https://github.com/PaulCailly/hermes-deploy/commit/003404c2fe316130c623249eb09d20bd010af1e3))
* **cloud:** derive ResourceLedger kind from cloud discriminator instead of hardcoding ([375b43c](https://github.com/PaulCailly/hermes-deploy/commit/375b43c70a7ef03a6fca6892dbdbaac3a1ff9e7c))
* **cloud:** include 'shutting-down' in InstanceStatus state union ([843728a](https://github.com/PaulCailly/hermes-deploy/commit/843728aadd961ccdbf7dfe3a6554fc2f5ab569f3))
* **crypto:** shell out to ssh-keygen for OpenSSH private key format ([5d2260f](https://github.com/PaulCailly/hermes-deploy/commit/5d2260ffb98f4cdd82b24d8f785bde8bf3ba773b))
* **init:** default size to large + warn about RAM, comment gitignore ([03b8b8d](https://github.com/PaulCailly/hermes-deploy/commit/03b8b8d166ac4e9825c059474a75f4be11fb3101))
* **m3:** post-review fixes — pre-flight file validation + version bump ([62c606c](https://github.com/PaulCailly/hermes-deploy/commit/62c606c2d1aa6ea21ed4b693afcd261492c5fde2))
* **m3:** secret set works before first up + restartTriggers for secret rotation ([7ebd97e](https://github.com/PaulCailly/hermes-deploy/commit/7ebd97e1fd358918e67705af730f87405242b887))
* **nix-gen:** cloud-aware configuration.nix + optional image override ([1a5dce5](https://github.com/PaulCailly/hermes-deploy/commit/1a5dce5412e3635bd1d8bcfd7e1d620782a67b19))
* **nix-gen:** declare placeholder sops secret to unblock upstream activation dep ([33a1fd8](https://github.com/PaulCailly/hermes-deploy/commit/33a1fd8671f4adef3ee0926123907d6af877f580))
* **nix-gen:** disable Google OS Login on GCE to fix post-rebuild SSH ([fe27e5c](https://github.com/PaulCailly/hermes-deploy/commit/fe27e5c688da5df88ca555633ef1071f1f2812d0))
* **nix-gen:** don't escape quotes inside Nix string interpolation ([869eb6c](https://github.com/PaulCailly/hermes-deploy/commit/869eb6cc3a4b754b09cfa63a6bad4a153a96859f))
* **nix-gen:** emit services.hermes-agent.enable = true ([241790f](https://github.com/PaulCailly/hermes-deploy/commit/241790f6774dda73c9dff57168b43dd3126d7fd3))
* **nix-gen:** prevent sshd restart during nixos-rebuild activation ([8cada2d](https://github.com/PaulCailly/hermes-deploy/commit/8cada2d39df657baeefd102f6f76f35152ab8534))
* **nix-gen:** reject paths with characters invalid in Nix literals ([70bec65](https://github.com/PaulCailly/hermes-deploy/commit/70bec65b8160263d2369f9638b091b1757b6b21c))
* **nix-gen:** use lib.mkForce for googleOsLogin override ([747cac0](https://github.com/PaulCailly/hermes-deploy/commit/747cac0e9cfb225ee3e8b7671484876fecd4b92e))
* **nix-gen:** use sopsFile not path in restartTriggers ([6f0bdd5](https://github.com/PaulCailly/hermes-deploy/commit/6f0bdd5c77837634483b4012bec3e76a5063a0dd))
* **orchestrator:** also unlink project sops files on destroy ([72837e2](https://github.com/PaulCailly/hermes-deploy/commit/72837e223fd891130fdf1e227e9d3001ee058f82))
* **orchestrator:** clean up per-deployment SSH + age keys on destroy ([639718a](https://github.com/PaulCailly/hermes-deploy/commit/639718ac481caef46cc940cc05ce288db09a6f5a))
* **orchestrator:** mkdir /var/lib/sops-nix before uploading age key ([e96d6d6](https://github.com/PaulCailly/hermes-deploy/commit/e96d6d609a99486383e449b91a790f82c7a58a06))
* **orchestrator:** retry SSH session creation for nixos-infect on GCE ([638fc03](https://github.com/PaulCailly/hermes-deploy/commit/638fc03381b5733265f9ca95aba20274e0ff8e9c))
* **remote-ops:** nohup+poll rebuild survives sshd restarts ([262b1d6](https://github.com/PaulCailly/hermes-deploy/commit/262b1d6f5b52e656f26e80661d466e43ea89a5f3))
* retry the infectSession creation up to 10 times with 3s backoff. ([638fc03](https://github.com/PaulCailly/hermes-deploy/commit/638fc03381b5733265f9ca95aba20274e0ff8e9c))
* **sops:** add explicit null check for age-keygen pub key match ([0c09397](https://github.com/PaulCailly/hermes-deploy/commit/0c09397d1332e20342410dfd364799ce91e0ad98))
* **test:** assert non-interleaving instead of FIFO order in state store ([9f29612](https://github.com/PaulCailly/hermes-deploy/commit/9f296128737e78f03ddf6dadcda5253ef8dbde4b))


### Performance Improvements

* **orchestrator:** skip nixos-rebuild when only network rules changed ([034ef13](https://github.com/PaulCailly/hermes-deploy/commit/034ef13f11844ffb93aa23f9209d9569712eee24))


### Documentation

* add README with M1 smoke-test instructions ([c02e9ce](https://github.com/PaulCailly/hermes-deploy/commit/c02e9ceac47875c0690b290bd6fc461319eadbfc))
* **init:** update template to reflect GCP support ([9397624](https://github.com/PaulCailly/hermes-deploy/commit/939762431246af4a97b8246b21add1797ecff6e9))
* M2 README update + getting-started + schema-reference + key-sync guides ([b3ae394](https://github.com/PaulCailly/hermes-deploy/commit/b3ae39497955d1d038ddda81c7f27224211f461c))
* M3 README + getting-started + schema-reference + migration guide ([09e4719](https://github.com/PaulCailly/hermes-deploy/commit/09e4719d9ba79fe43ea1534ec374ef8e187af155))
* **plans:** add M1 AWS skateboard implementation plan ([19b5628](https://github.com/PaulCailly/hermes-deploy/commit/19b5628c290128be63479ac08cee47774ceed70c))
* **plans:** add M2 AWS feature-complete implementation plan ([3e8b1c5](https://github.com/PaulCailly/hermes-deploy/commit/3e8b1c53574f60213b0f04c0420bb057e4f8c80f))
* **plans:** add M3 schema redesign implementation plan ([7cce6fa](https://github.com/PaulCailly/hermes-deploy/commit/7cce6fa7e3109709dc0705aae2d46b33c6f7a43e))
* **plans:** add M4 GCP support implementation plan ([20379a1](https://github.com/PaulCailly/hermes-deploy/commit/20379a1c0c429ea1221114d3384e5fd854520d3b))
* **specs:** add M3 schema redesign design ([317bd24](https://github.com/PaulCailly/hermes-deploy/commit/317bd24ca683b9b2322142b69c5cda0a030c4523))
* **specs:** add M4 GCP support + polish bundle design ([bb776fa](https://github.com/PaulCailly/hermes-deploy/commit/bb776faef0d20018e1ed360cca3ecf3bf86b40c8))
* **specs:** add v1 design for hermes-deploy CLI ([60e0cb4](https://github.com/PaulCailly/hermes-deploy/commit/60e0cb421643511fa6671ba7b772431cb6ebd8dc))


### Code Refactoring

* **cloud:** add provider factory and lift public-ip out of AWS subdir ([b8f9ddf](https://github.com/PaulCailly/hermes-deploy/commit/b8f9ddf4d8c06606539bd469af94929a429cdabc))
* **nix-gen:** switch bootstrap to flake-based redesign ([3066e34](https://github.com/PaulCailly/hermes-deploy/commit/3066e34bbb2370fe5a938b60df19d29d21e127b3))
* **schema:** use discriminatedUnion to couple cloud and cloud_resources ([130dd6c](https://github.com/PaulCailly/hermes-deploy/commit/130dd6cc7a7ef1e920c43abc610b11d7c5dfb94a))
* **state:** hash file content only, not paths, for machine portability ([aeb2d85](https://github.com/PaulCailly/hermes-deploy/commit/aeb2d854ef3218566f7b48845358d75b70e967cd))

## [1.0.0] - 2026-04-11

First stable release. The CLI surface, the `hermes.toml` schema, and the
state-file format are now considered stable and will follow semver. Future
breaking changes ship with state migrations and a major-version bump.

### Features

- **Two-cloud support.** AWS and GCP both ship as first-class providers
  behind a single `CloudProvider` interface, with full lifecycle parity:
  `init`, `up`, `update`, `destroy`, `status`, `logs`, `ssh`, `ls`, `adopt`.
- **`hermes-deploy adopt`.** Rebuild a lost state entry by discovering
  cloud resources via their provision-time
  `managed-by=hermes-deploy` + `hermes-deploy/deployment=<name>` tags
  (AWS) or labels (GCP). Safe by construction: the discovery is scoped
  to resources that carry both markers, so adopt will never touch
  unrelated infrastructure. Supports `--dry-run`, `--force`, and
  `--json` for scripting.
- **`--json` output mode** on `status`, `ls`, `secret list`, `key path`,
  and `adopt`. Emits a stable, machine-readable schema to stdout for
  scripting and managed-service integration. The non-JSON path is
  unchanged.
- **Library entry point.** The package now exposes `src/index.ts` as
  the `@hermes-deploy/cli` main, re-exporting the orchestrator
  (`runDeploy`, `runUpdate`, `runDestroy`), cloud providers
  (`createCloudProvider`, `AwsProvider`, `GcpProvider`), schemas
  (`StateTomlSchema`, `loadHermesToml`), state store (`StateStore`,
  `getStatePaths`, `runMigrations`), error classes, and
  `adoptDeployment`. Follows the same semver contract as the CLI.
- **E2E test suite.** Gated under `tests/e2e/` + `vitest.e2e.config.ts`,
  run via `npm run test:e2e`. Exercises the full CloudProvider lifecycle
  (resolve image → provision → status → adopt → destroy) against real
  AWS and GCP accounts. A new `.github/workflows/e2e.yml` runs these
  nightly and on maintainer-triggered manual dispatch; regular PRs
  continue to run only the unit/integration suite. A companion
  `scripts/e2e-sweep.mjs` script runs after the nightly test jobs and
  tears down any leaked resources older than 4 hours, gated by three
  defense-in-depth safety rails (managed-by tag + `e2e-` deployment
  prefix + cloud-side age threshold).
- **NixOS-native deployment.** Provisions a community NixOS image (AWS AMI
  or GCE family image), bootstraps it over SSH, and runs `nixos-rebuild
  switch` to bring up the `hermes-agent` systemd service. GCE uses
  `nixos-infect` to convert from a Debian boot image.
- **`hermes.toml` schema.** A small TOML schema covers the common case
  (cloud, sizing, network, hermes-agent options), with a Nix escape hatch
  (`[hermes.nix_extra]`) for everything else. Schema is validated with Zod
  and gives file:line:col errors on parse failures.
- **`config.yaml` upload.** hermes-agent's runtime config is uploaded
  verbatim alongside `hermes.toml` and pointed at by
  `services.hermes-agent.configFile`.
- **Secrets via sops-nix.** Per-deployment age keypairs are auto-generated
  by `init`. Secrets live in `secrets.env.enc` (sops-encoded dotenv) and are
  decrypted at activation on the box, exposed at `/run/secrets/<key>`.
- **`secret set/get/rm/list/edit`** subcommands wrap sops with the right
  age key path so users don't need to know sops exists.
- **`key export/import/path`** subcommands support manual multi-machine key
  sync.
- **Per-deployment SSH key** generated on `init`, stored at
  `~/.config/hermes-deploy/ssh_keys/<name>`.
- **Atomic provisioning.** `provision()` either fully succeeds or rolls
  back every cloud resource it created on failure. The state file is never
  half-written.
- **Network-only-update fast path.** `update` skips `nixos-rebuild` when
  only `[network]` rules changed, reconciling firewall rules in place.
- **Idempotent `update`.** With no local changes, `update` is a ~5-second
  no-op (hash compare + early return).
- **Ink UI.** `up` and `update` render a live timeline with phase rows,
  spinners, and a tail of `nixos-rebuild` output when stdout is a TTY.
  Pipes, redirects, and CI runs get a plain stdout reporter. Force the
  plain reporter with `--no-ink` or `HERMES_DEPLOY_NO_INK=1`.
- **Optional Cachix substituter.** `[hermes.cachix]` lets users skip the
  10-15 minute first-deploy build by pointing at a populated Cachix cache.
- **State file with migrations.** `~/.config/hermes-deploy/state.toml`
  stores per-deployment metadata. Schema versions v0→v1→v2→v3 all migrate
  forward automatically. Backups are written to `state.toml.bak.<ts>`
  before every write (last 5 retained). Concurrent invocations serialize
  via `proper-lockfile`.
- **`--name` and `--project` flags** on every command, with cwd-walk
  fallback to find the nearest `hermes.toml`.
- **Apache 2.0 license.**

### Documentation

- Getting-started walkthrough.
- `hermes.toml` schema reference.
- Multi-machine key-sync guide.
- M2 → M3 migration guide.
- Design specs and milestone implementation plans under `docs/specs` and
  `docs/plans`.

### Known limitations

The following are deferred to post-1.0 releases. Each is tracked against a
specific unblocking trigger; see `docs/specs/2026-04-09-hermes-deploy-design.md`
§13 for the rationale.

- No `hermes-deploy ls --watch` dashboard yet.
- No pre-baked AMI / GCE image pipeline; first-deploy builds take 3–8
  minutes on a small instance unless a Cachix cache is configured.
- No automated Cachix population workflow.
- No custom VPCs, private-only networking, or SSM/IAP-based SSH.

## [0.4.0-m4] - 2026-04-10

### Features

- **GCP provider.** Full feature parity with AWS: image resolution with
  caching, atomic provision with rollback, destroy, status,
  reconcileNetwork. Bootstrapped via nixos-infect from a Debian image.
- **Network-only-update optimization.** `update` skips `nixos-rebuild` when
  only `[network]` rules changed.
- **`secret set` cleanup.** First real `secret set` removes the placeholder
  secret seeded by `init`.

### Bug Fixes

- **GCE post-rebuild SSH.** Disable Google OS Login, bake SSH public key
  into NixOS config, prevent sshd restart during activation, retry SSH
  session creation for nixos-infect on GCE.
- **GCP SDK v6 compatibility.** Replace `.promise()` with operation
  waiters; check `status==='DONE'` not `done===true`.
- **GCP image resolution.** Use image family URL instead of listing
  nixos-cloud images.

## [0.3.0-m3] - 2026-04-09

### Features

- **`hermes.toml` schema redesign.** Drops `model` / `soul` / `platforms`
  in favor of `config.yaml` upload + `documents` + `environment` mapping
  to upstream `services.hermes-agent.{settings,environmentFiles,documents,mcpServers}`.
- **`config.yaml` upload.** Uploaded verbatim to the box; hashed for
  change detection alongside `hermes.toml` and the sops file.
- **Secrets as dotenv.** `secrets.env.enc` is a sops-encoded dotenv file;
  `secret` subcommands operate on dotenv keys.
- **State schema v2.** No-op deployment shape migration to bump the
  version field.

### Bug Fixes

- `secret set` works before first `up`.
- `restartTriggers` wired up so secret rotation actually restarts the
  service.
- Pre-flight file validation catches missing `config.yaml` / `SOUL.md` /
  documents before any cloud calls.

## [0.2.0-m2] - 2026-04-09

### Features

- **Full lifecycle on AWS.** `init`, `up`, `update`, `destroy`, `status`,
  `logs`, `ssh`, `ls`, `secret`, `key`.
- **Multi-instance / multi-client.** Single user manages many named
  deployments via the global state file with advisory locking.
- **`update` flow.** Skips provisioning, reconciles network rules,
  re-runs `nixos-rebuild` over SSH, healthchecks. ~30–90 seconds on a
  warm box.
- **`reconcileNetwork`** in the AWS provider.
- **`secret` subcommands** wrapping sops with the per-deployment age key.
- **`key export/import/path`** subcommands for manual multi-machine key
  sync.
- **State migration runner** with v0→v1 fixture exercising the scaffold
  from day 1.
- **Ink UI** with the `DeployTimeline` component, auto-engaging on TTY.
- **GitHub Actions CI** running lint, typecheck, vitest, and build on
  every PR.

## [0.1.0-m1] - 2026-04-09

### Features

- **AWS skateboard.** `CloudProvider` interface, `AwsProvider`
  implementation, atomic `provision()` with rollback, NixOS AMI
  resolution with 1-hour cache, `RunInstances` + `AllocateAddress` +
  `AssociateAddress` sequence, deployer public-IP detection for SSH
  ingress.
- **remote-ops layer.** TCP poll for SSH readiness, `ssh2` session
  wrapper, `nixos-rebuild` over SSH with rolling tail, `systemctl
  is-active` healthcheck with journal tail on failure.
- **Orchestrator.** Phases 1–5 of the deploy flow + the destroy flow.
- **CLI skeleton.** `up`, `destroy`, `status`, `ssh` commands.

[1.0.0]: https://github.com/PaulCailly/hermes-deploy/releases/tag/v1.0.0
[0.4.0-m4]: https://github.com/PaulCailly/hermes-deploy/compare/v0.3.0-m3...v0.4.0-m4
[0.3.0-m3]: https://github.com/PaulCailly/hermes-deploy/compare/v0.2.0-m2...v0.3.0-m3
[0.2.0-m2]: https://github.com/PaulCailly/hermes-deploy/compare/v0.1.0-m1...v0.2.0-m2
[0.1.0-m1]: https://github.com/PaulCailly/hermes-deploy/releases/tag/v0.1.0-m1
