Getting Started
Audience: newcomer. This page is the first task: protect one spare project with himmel, see a guardrail refuse a risky edit, make one change in a worktree, then undo it all. If you want to run or develop himmel itself instead, that contributor path is in setup/new-machine.md.
The ten steps below are the same sequence as the adoption trail’s practice climb, and that sequence is the canonical one. On 2026-10-23 it was run end to end on a clean Linux virtual machine with a sandboxed home folder: install, commit, worktree and undo. The editor refusal in step 7 was checked by calling the edit hook directly, not in a live Claude Code session, and macOS was not part of that run. Each step says which folder to run it from and what you should see, and step 10 undoes the install. A different result means stop and read setup/install.md. The daily-loop walkthrough, which narrates every hook, is optional depth; the steps below stand on their own.
What is himmel? A harness that runs Claude Code as a PR-gated, overnight-capable agent: worktree isolation, multi-agent review, guardrail hooks, and durable handover state that survives session boundaries. See the README for the full pitch and the advantages.
The first protected project, in ten steps
Do this on a throwaway or a small repo first. The paths below use
~/try-himmel for the project and ~/himmel for the himmel download; they
are two separate folders, and the install writes into the project, not into
the download.
1. Install the tools
You need git, node with npm, jq, python3 and Claude Code. The installer checks for them and stops with install hints if one is missing.
# Debian or Ubuntu (needs sudo); Ubuntu's nodejs package ships without npmsudo apt-get updatesudo apt-get install -y nodejs npm git jq python3 curlcurl -fsSL https://claude.ai/install.sh | bash
# macOS with Homebrew; the bash and python3 macOS ships are too old for some scriptsbrew install node git jq python bash uvcurl -fsSL https://claude.ai/install.sh | bashuv tool install pre-commitYou should see: claude is found in a new terminal.
2. Sign in to Claude Code
Run claude, finish the sign-in in the browser it opens, and leave with
/exit. An account problem then shows up before himmel is involved.
claude --versionYou should see: a version number followed by (Claude Code).
3. Make a spare project and name the folder you are in
mkdir ~/try-himmel && cd ~/try-himmel && git init -b maingit commit --allow-empty -m "chore: initial commit #1"pwdYou should see: pwd prints the full path of ~/try-himmel, the project
you are about to protect. The installer acts on the folder you run it from,
so a wrong folder here is a wrong install. The commit is made before any himmel hook
exists; it still carries a ticket reference (#1), as every later commit
must. Use your own repository instead if you prefer, but it needs at least one
commit and a clean git status. No remote is needed.
4. Download himmel next to your projects
git clone https://github.com/yotamleo-org/Himmel ~/himmel # once; the installer lives hereYou should see: git ends without an error. This folder is the download; you never work inside it.
5. Preview the footprint
Run from ~/try-himmel:
node ~/himmel/scripts/himmelctl/bin.js install --scope project --dry-runbash ~/himmel/scripts/adopt.sh --profile core --scope project --dry-runYou should see: both change nothing. The first prints a summary of what the
install would run, its list headed
would install (--dry-run — NOTHING below was executed):; the second prints
one DRY: line for each file and setting it would write. git status is
still clean. Node-less machine? Run
bash ~/himmel/scripts/himmelctl/bootstrap.sh first.
6. Install
Run from ~/try-himmel:
node ~/himmel/scripts/himmelctl/bin.js install --scope projectgit status --shortThese steps were run with project scope only. A --scope user install wires the
harness for every project on the machine instead (see
setup/install.md); steps 8 to 10 are not written for it.
This install uses the starter answers; the other answers, and how to move
between them later, are on Install profiles.
You should see: in ~/try-himmel, git status lists .claude/, scripts/
and .gitignore as untracked. The install is on disk but not yet in your
project’s history. That matters in step 9. In your own repository, a path it
already tracks shows as modified instead, or not at all.
7. See the harmless refusal
Start claude in ~/try-himmel and ask it to create hello.txt.
You should see: on main the edit is refused with
block-edit-on-main: refusing to edit …, and hello.txt does not exist. That
refusal is the guardrail working, not an error. Leave Claude with /exit.
8. Commit and merge the install
Run from ~/try-himmel. On a machine without the pre-commit tool the
installer places plain git hooks, and the commit hook then refuses a commit
made directly on main. (With pre-commit present the hooks run whatever
your .pre-commit-config.yaml lists, and a starter install writes none, so
nothing refuses.) Commit on a branch and
fast-forward either way:
git switch -c chore/install-himmelgit add -Agit commit -m "chore: install himmel #1"git switch maingit merge --ff-only chore/install-himmelWhere the plain git hooks run, the commit-msg gate wants a ticket reference in
every message (COMMIT REJECTED: no ticket reference matched). With no
JIRA_PROJECT_KEY set, #<number> satisfies it (as above); for a repo with
no ticket convention, TICKET_ID_REQUIRED=0 git commit … switches the
requirement off. On a repo whose main is branch-protected, push the branch and
merge it through a PR instead; if your default branch has another name, use it
in place of main. If the repo has an origin, push chore/install-himmel
and merge it through a PR before step 9, because the worktree is cut from
origin/main. (The trail’s version of this step lets the installer make the
one commit on main itself, with adopt.sh --commit-install; either way the
install is in main’s history before step 9.)
You should see: git log --oneline -1 on main shows
chore: install himmel #1, and git status is clean.
.claude/settings.json carries the path of your himmel download (the status
line and HIMMEL_REPO point at ~/himmel), so the commit above bakes this
machine’s path into the project. That is fine for a throwaway; in a repo you
share, a teammate whose download sits elsewhere needs those two values changed
to their own path.
9. Create the worktree, then relaunch inside it
Run from ~/try-himmel:
bash scripts/worktree.sh feat/try-himmelYou should see: it prints the path,
.claude/worktrees/feat+try-himmel. With no remote it also warns that it is
branching from local main; that is normal. It does not move a running Claude
Code session: quit, then run claude from inside that path. A worktree is cut
from committed history, so cutting it before step 8 gives you a folder
without the hooks or the edit guard.
10. Verify, preview the undo, then undo
Verify from inside the worktree
(~/try-himmel/.claude/worktrees/feat+try-himmel): .claude/settings.json,
scripts/hooks/block-edit-on-main.sh and scripts/worktree.sh all exist,
claude can create hello.txt there, and
node ~/himmel/scripts/himmelctl/bin.js status shows no drift. Then run the
loop below once before you undo, or go straight to the undo.
Undo from the project folder you installed into (~/try-himmel), not from
the worktree: the uninstaller acts on the folder you run it from.
cd ~/try-himmelnode ~/himmel/scripts/himmelctl/bin.js uninstall --dry-run # lists what stays and what goesnode ~/himmel/scripts/himmelctl/bin.js uninstall --yes # --yes is required without a terminalYou should see: it removes the files the install recorded (git shows them
as deleted), keeps your own files and any copy it does not recognize, and
prints verified: no himmel wiring left in …. Your Telegram pairing and
bridge state stay unless you add --purge-state.
That is the whole install for the common case. The full guide is setup/install.md: prerequisites, what each scope and install profile lands, the Windows caveat, and the adaptation checklist for a repo that is not himmel. Already have himmel wired some older way? See setup/migrating.md.
Developing himmel itself (running the repo standalone, hacking on the harness) is a different path: see setup/new-machine.md.
Minimal config
USER_SLUG is your kebab-case handle (e.g. jane-doe). Skip it and himmel
derives one from your git config user.name. That is the whole required
configuration; luna, Telegram, hermes and Jira are all
opt-in. The details, including the companion vault, are in
setup/install.md.
For your first loop you need none of this, because the installer already did the work. Skip straight to the loop.
Your first loop
The first time, skip the first line below: you are already in the worktree you
opened in step 9, on feat/try-himmel with claude running inside it, so make
your change there and use that branch name in the push line. For every later
change, make a new worktree, cd into the path it prints and relaunch claude
there before you edit. The hooks below only fire inside an active session. The
throwaway project from step 3 has no remote, so the push and PR lines need a
GitHub remote first (git remote add origin <url>); without one, stop after
the commit. The throwaway’s first worktree was cut from local main and
already has the install commit. Once origin exists, every new worktree is cut from
origin/main, which lacks the install commit until you push
chore/install-himmel and merge it there through a PR. The day-to-day loop is:
bash scripts/worktree.sh feat/my-thing # isolated branch + worktree. Branch must be type/slug — # type in feat|fix|chore|docs|refactor|test. Never edit main. # Then cd into the printed path and relaunch `claude` there. # (A full himmel checkout also has the `/worktree` slash # command; a starter install copies only `scripts/worktree.sh`.)# … make a small change with Claude …git add -A && git commit -m "feat: my change #2" && git push -u origin feat/my-thing # conventional-commit gate fires at commit (the #2 is the ticket # reference it wants, see step 8); the pre-push # gates run and record that a review is owed/pr-check # multi-agent review; clears the merge gate when clean# gh pr create / gh pr merge --squash/clean # prune merged-PR worktrees/handover # save notes on what you did + where you left off, so the # next session (or a teammate) resumes with full contextFirst time using
/handover? Run/handover-setuponce to point it at your own state store: an inlinehandovers/folder in the repo, or a separate git repo (viaHANDOVER_DIR). Your cross-session notes land wherever you point it.
How to tell it’s working: if you try to edit a file on main you’ll get a
block-edit-on-main message pointing you back into a worktree (/clean_garden
or /worktree). That message means the guardrail works; it is not an error.
(If you also installed the optional pre-commit gates,
pre-commit run --all-files should pass too.)
You’re done when: /pr-check reports clean, the PR merges, /clean removes
the worktree, and /handover confirms a saved snapshot. To verify, run
cd ~/try-himmel && git checkout main && git pull && git log --oneline -3 and
look for your change on main. (Run it from the project folder: main is
checked out there, so git checkout main fails inside a linked worktree.)
Want every hook and gate explained at the moment it fires, on a real toy change? The optional daily-loop walkthrough runs the real workflow on a real branch. It is the best way to see what each guard does before you rely on it.
Going unattended later: /afk-shift --limit 5 dispatches scoped tickets as
parallel agents that open PRs while you sleep (AFK (unattended) mode).
Initiative mode + planning pipelines
Two optional accelerators sit on top of the loop. Both are opt-in.
HIMMEL_INITIATIVE — drive-to-ship
When set, each session drives finished work toward shipping at natural
completion points (a logical chunk is done and verified), instead of
waiting for you to say “ship it” each time. In the default (interactive)
profile, the all master switch runs four auto-ship steps, in order:
prcheck: run/pr-checkand loop until the review is clean.pr: open or refresh the PR.ticket: transition the Jira ticket.handover: write the handover.
Merging is opt-in. None of the four interactive auto-ship steps merges. The full grammar does include
mergeandpublicauto-ship steps, used by the overnight profile or an explicit subset. Know whatmergemeans before enabling it: the auto-ship step itself authorizes an autonomous private merge.ARMAUTOMERGEonly selects which merge path it takes (the CI-certified sanctioned script vs a plain squash-merge); it is not an extra on/off gate. To turn merging off, do not enable the step. WithARMAUTOMERGE=1that script can also merge the one configured public origin, but only after a live read shows branch protection withenforce_adminsand a non-empty required-status-checks list; any other public repo, or an unreadable protection read, is refused. Thepublicauto-ship step is retired and does nothing. See configuration.md for the complete grammar and gate conditions. The directive also can’t relax any safety rail. Every gate in configuration.md still applies: the review-owed marker still gatesgh pr create, the attestation commit-lines (Platforms tested:/Security reviewed:) are still required, and reactive history rewrites / settings self-edits stay vetoed.
Enable it in the launching shell (it’s read at session start):
HIMMEL_INITIATIVE=all claude # the four interactive stepsHIMMEL_INITIATIVE=prcheck,pr claude # just CR + open the PRGrammar: a master switch 1/true/on/yes/all (= the four auto-ship steps above),
or a comma-separated subset of the full vocabulary
plan,execute,prcheck,pr,ticket,merge,public,handover. Case-insensitive,
whitespace-tolerant; an unset/falsy/typo value is OFF (the default), a
byte-identical no-op. A separate overnight profile (HIMMEL_OVERNIGHT +
HIMMEL_INITIATIVE_OVERNIGHT) widens all to six auto-ship steps for
unattended runs. Grammar, per-step semantics, and profiles are in
configuration.md.
Most people should leave the aggressive auto-ship steps OFF. It is the
default because auto-opening PRs and transitioning tickets is a lot of
initiative. If you want some of it, start conservative (prcheck, or
prcheck,handover) and reserve all (or the overnight profile) for
trusted/overnight contexts.
Per-project override (user default + per-repo tightening). Beyond the
launching-shell variable, you can set it via the env block in
settings.json, which Claude Code makes visible to the session’s hooks. Per
Claude Code’s settings precedence, a project .claude/settings.json
deep-merges over your user ~/.claude/settings.json, so you can set a
machine-wide default and override it per repo:
// ~/.claude/settings.json — your default for every repo{ "env": { "HIMMEL_INITIATIVE": "prcheck,handover" } }
// <repo>/.claude/settings.json — make THIS repo stricter (off) or freer (all){ "env": { "HIMMEL_INITIATIVE": "0", "HIMMEL_INITIATIVE_AFK": "0" } }A value exported in the launching shell takes precedence over settings.json
(per Claude Code’s docs), and any change needs a session restart to take
effect.
/himmel-ops:minerva — idea → critic-hardened plan
Runs brainstorm → spec → plan as one pipeline with an adversarial critic between each stage, so every artifact is red-teamed before it advances. Use it for any feature/design work before writing code. It stops at the plan (it doesn’t implement) and hands off.
You’re in control
himmel makes the workflow structurally safe, but nothing is hidden, and every guard is yours to lift:
- Everything is plain files. Rules live in
CLAUDE.md, hooks and permissions in.claude/settings.json, gates in.pre-commit-config.yaml. Read them; change them. - What himmel adds to your repo: PreToolUse hooks (block edits on
main, block secret reads, gate PR creation on a passing review) and pre-commit/pre-push gates. (The auto-mode classifier you may hit in unattended sessions is Claude Code’s own, not himmel’s; himmel routes sanctioned commands around it.) The full inventory and what each one does:docs/internals/enforcement.md. - Nearly every guard has an off switch. Each session hook is bypassed by an
env var set in the launching shell, e.g.
EDIT_ON_MAIN_OK=1 claudeto editmain, orREAD_SECRETS_OK=1 claudeif the (deliberately strict) secret-read guard blocks a file you need to inspect. A small set of gates is deliberately hard (secret-leak scans, the human-only public merge). The per-gate map, including that list, is in configuration.md; thestuck-playbookhas the recovery flow for each guard. - No surprise network or spend, with three named exceptions. Optional
integrations are opt-in; headless Claude calls are gated; the local
Jira CLI talks only to your own Atlassian site. Each exception has a switch:
a throttled session-start update check (a plain
git fetchof your own himmel clone’s remote, no data sent;UPDATE_CHECK_DISABLE=1); the usage-cap auto-relaunch, which schedules a local session relaunch when a cap approaches (AUTO_ARM_DISABLE=1); and/pr-check’s external review critics, which run only where you configured their lane (CR_PROFILE=noneforces a Claude-only automated review with no external spend). The full map: configuration.md.
Where to go next
| You want to… | Read |
|---|---|
| See one full loop explained | daily-loop.md |
| See every knob, gate, and off switch in one place | configuration.md |
| Understand every hook + gate | internals/enforcement.md |
| Browse the slash commands | commands-catalog.md |
| Browse every tool/script | tooling-catalog.md |
| Run unattended overnight | handover/afk-mode.md |
| Adopt the core in another repo | setup/install.md |
| Full machine setup + gotchas | setup/new-machine.md |
| Update the harness + upgrade the vault | setup/updating.md |
| Uninstall / offboard himmel | node ~/himmel/scripts/himmelctl/bin.js uninstall (execs scripts/uninstall.sh; see updating.md) |
Working as an LLM in this repo? Start from llms.txt — the
machine-readable map.