@kaspernj/hermes-compose
v0.0.0
Published
Strict task-scoped Docker Compose lifecycle provider for Hermes
Maintainers
Readme
@kaspernj/hermes-compose
@kaspernj/hermes-compose is the strict optional Docker Compose provider for
Hermes-operated task worktrees. It owns validation, build/start/exec/proof,
Codex auth seeding, exact cleanup, two-stack smoke acceptance, safe templates,
and the Threadwire-to-Compose boundary. Threadwire continues to own worker
sessions and relay behavior.
The package requires Node 24 and never constructs shell commands. Consumer
configuration is the checked-in hermes.config.js at the exact consumer root.
Its schema declares repository origins, worktree/project pairing, Compose
paths, uid/gid, mutable volumes, label namespace, proof inputs, argv-based
checks, smoke conventions, the pinned bootstrap-image CLI, and worker
integration. Unknown fields and unsafe paths fail closed.
Install and bootstrap
npm install --save-dev @kaspernj/hermes-compose
mkdir hermes-setup
./node_modules/.bin/hermes-compose bootstrap hermes-setupbootstrap accepts exactly one existing, empty, canonical, non-symlink
directory. It copies only hermes.config.js, compose.hermes.yml, and
Dockerfile.hermes. Before writing, it reads this installed package's exact
numeric semver and replaces the one reviewed template placeholder in memory.
The files are published atomically without overwrite, generated code is not
imported, and bootstrap neither accesses Docker nor uses npm or the network.
Review and edit the generated configuration before moving the three files to
the repository root.
Generated development images pin and verify OpenCode 1.18.8, Codex 0.145.0,
Claude Code 2.1.220, Kimi Code 0.29.2, and Threadwire 0.1.9. Installation does
not authenticate or select a provider; Threadwire remains the control
boundary. npm 11 runs the global install with strict script approval: only
OpenCode, Claude Code, Kimi Code, and transitive [email protected] are approved
at their exact versions. Threadwire does not support --version; its offline
smoke requires status 2 and the stable
Usage: threadwire run --provider signature. The image also includes the documented universal Debian development
baseline: bash, ca-certificates, curl, wget, git, git-lfs, gh,
openssh-client, gnupg, jq, ripgrep, fd-find, fzf, less, file,
tree, bat, nano, vim-tiny, unzip, zip, xz-utils, bzip2, tar,
gzip, rsync, patch, diffutils, gawk, findutils, coreutils,
procps, psmisc, lsof, iproute2, iputils-ping, dnsutils,
netcat-openbsd, socat, util-linux, tini, python3, python3-venv,
python3-pip, sqlite3, shellcheck, tmux, zsh, man-db,
build-essential, pkg-config, and libssl-dev. Debian's fdfind and
batcat are exposed through stable /usr/local/bin/fd and
/usr/local/bin/bat symlinks.
hermes-compose proof checks all five installed global package identities,
the four supported version commands, Threadwire's captured status/signature,
and fd/bat executable discovery without authenticating or launching any
provider. Threadwire's provider adapter loads the same checked-in configuration
as the lifecycle, so Codex -C and Compose exec --workdir both use the fixed
compose.workspace.
Lifecycle
For a configured prefix project and task review-a:
export HERMES_SOURCE_PATH=/opt/hermes-dind-shared/worktrees/project/review-a
export HERMES_COMPOSE_PROJECT=project-review-a
hermes-compose validate
hermes-compose config
hermes-compose build --pull
hermes-compose up
hermes-compose exec npm ci
hermes-compose proof
hermes-compose exec npm run all-checks
hermes-compose downUse HERMES_CODEX_AUTH_VOLUME=<existing-volume> hermes-compose init-codex to
seed the project Codex volume. The initializer atomically replaces only the
fixed auth.json entry with a verified task-owned 0600 regular file; it rejects
symlinked destination parents and never follows an existing destination
symlink. down inventories and fully inspects every exact same-project
container and network before stopping/removing their IDs, while preserving
volumes and images. Use
HERMES_PURGE_PROJECT="$HERMES_COMPOSE_PROJECT" hermes-compose purge for the
additional exact, labeled, unreferenced volume/image cleanup.
The two-stack smoke workflow populates each clean checkout's task
node_modules volume and runs configured checks in ephemeral Compose services
before auth initialization and up.
Set THREADWIRE_TARGET=telegram:<chat-id>[:<thread-id>] and run
hermes-compose threadwire --prompt 'Work on the task.' to launch Threadwire.
The installed hermes-compose-threadwire-provider binary is reserved for a
Threadwire child with THREADWIRE_ACTIVE=1.
Public API
import {
createLifecycle,
createSmoke,
HermesLifecycle,
HermesSmoke,
loadConfig,
runCli,
startCli,
validateConfig
} from "@kaspernj/hermes-compose"The strict provider is separately importable from
@kaspernj/hermes-compose/threadwire-provider.
Release
For the brand-new package only, after reviewed clean master is on origin and
package.json is still 0.0.0, create the annotated matching bootstrap tag
v0.0.0, then run npm run release:patch -- --resume. The helper atomically
pushes master and the tag, publishes the exact tagged version to npm, and
verifies it. For subsequent patch releases, run npm run release:patch.
Never manually bump package versions or invent tags.
Development
Run npm ci, then npm run all-checks. npm run lint aggregates ESLint and
strict TypeScript checking. npm test names the focused package specs
explicitly. npm run build emits reviewed package artifacts under build/;
node tools/package-manifest.js validates the dry-run tarball contents.
