Golems is a Bun monorepo with two parts: a set of TypeScript agent packages, and
golem-powers, a library of SKILL.md workflows for AI coding agents. Many
skills ship executable evals.
It is for two kinds of reader. The first builds with AI coding agents (Claude Code, Codex, Cursor) and wants skills and evals to reuse or copy. The second wants to see how one developer runs a fleet of coding agents day to day.
This is one person's working setup, published in the open. Many packages and skills assume the author's machine, accounts, and tools. Read them as working examples, not as a supported product.
Two terms:
- A golem is a package that handles one domain (email, finance, planning). It holds the code, prompts, and integrations for that domain.
- A skill is a
SKILL.mdfile that an agent loads and follows. It can come with scripts, references, and evals.
Quick start
Install the nightly skills and CLI wrappers without a Git checkout:
curl -fsSL https://raw.githubusercontent.com/EtanHey/golems/master/scripts/release/install.sh | sh -s -- --channel nightly
The bootstrap uses standard macOS/Linux utilities, curl, tar and shasum; it
verifies the release before switching ~/.golems/current. Skills are linked
for Claude and Codex from the per-client lists in skills/catalog.json.
Add ~/.golems/bin to PATH, then use golems-cli update
to install the newest nightly. Running golems-cli requires Bun; pr-watch requires
Python 3 and GitHub CLI. Existing checkout skill links are kept unless you pass
--replace-checkout-links. Other-repo links and real directories are preserved;
updates remove retired release-owned links. Hook installation is a separate step.
See release installation for pinned and offline installs.
For a former M1 owner install, run the nightly release installer above with
--replace-checkout-links, then run node ~/.golems/current/scripts/hooks/install-hooks.mjs --host client --source ~/.golems/current --migrate-owner-install --apply and verify
node ~/.golems/current/scripts/hooks/install-hooks.mjs --host client --source ~/.golems/current --status reports drift=0. The migration archives the old owner
pin and hooks-live links under ~/.golems/archive/owner-install-<timestamp>-<id>/
with a receipt, and restores the install if a write fails. The MBP owner refuses
this flag. Native Codex /hooks trust review remains a separate step.
For development from a checkout:
You need Bun, Node.js, and Git. CI
reads its Bun version from .bun-version, so install that version locally too.
One test checks for the claude CLI on your PATH. CI stubs it, and you can
do the same.
git clone https://github.com/EtanHey/golems.git
cd golems && bun install
bun run test
bun run test runs bun test ./packages, the same package suite CI runs. Use
it instead of a bare bun test, which also picks up tests from any local
untracked folders.
Packages
There are 10 workspace packages under packages/:
| Package | What it is |
|---|---|
claude |
Persona and Claude CLI status plugin |
coach |
Daily scheduling, calendar sync, habit tracking, briefings |
content |
Content pipelines (LinkedIn, ghostwriting) and Remotion video rendering |
golem-skills |
The CLI, published as golems-cli: installs and lists skills, checks setup |
golems-tui |
Terminal dashboard built on React Ink |
green-invoice-mcp |
MCP server for Green Invoice, an Israeli invoicing service |
mock-mcp |
Mock MCP server for testing agent skills |
services |
Morning briefing, scheduler worker, doctor health checks |
shared |
Supabase, LLM, email, state, and MCP helpers the other packages share |
teller |
Subscription tracking, payment categorization, spending reports, payment-failure alerts |
The package tests need no credentials; CI runs them with no secrets. Running
the domain packages for real is different: they call outside services
(Supabase, calendar and job-board APIs) and read credentials from
the environment. Where a package
has its own README.md or CLAUDE.md, that file says what it needs.
Skill library
Each skill lives in skills/golem-powers/<skill-name>/:
skill-name/
├── SKILL.md # the workflow the agent reads
├── adapters/ # optional: notes for a specific agent harness
├── references/ # optional: supporting material
├── scripts/ # optional: helpers the skill runs
└── evals/ # optional: fixtures and behavior checks
To count the skills, run the checker instead of trusting a number in a README:
node scripts/ci/check-skill-library.mjs # prints skills=<n> and description-size totals
Some skills to start with:
pr-loop: branch, commit, PR, review, and merge, with agent attribution on commitsnever-fabricate: read, run, and verify before claiming something is donelarge-plan: split a big change into phases for parallel agentsplan-council: judges from several model families review a plan, or rank anonymized candidatesgit-guardian: a safety gate in front of force-push, reset, and branch deletestmp-block: a hook that blocks durable writes to/tmpskill-creator: create, audit, and eval skillsorc: coordinate agents;bash skills/golem-powers/orc/scripts/install.shlinks its global Claude agentsunslop: cut AI-sounding filler and keep the facts
An eval checks only the behavior it asserts. It is regression evidence. It does not prove a skill works in every setup.
The Python skill suites and gate evals run with bash scripts/ci/run-skill-tests.sh.
You need python3 with pytest installed.
Human confirmation for destructive commands
The Claude human-confirm gate requires a signed, scoped, one-use token for force pushes, remote deletion, history rewrites and repo administration. Chat text and agent messages never satisfy it. The source implementation must be reviewed and installed through hooks-live before it protects a client; Codex exec_command is currently outside this hook.
The owner provisions a dedicated SSH signing key in the 1Password SSH agent,
exports only its public key to ~/.config/golems/human-confirm.pub, and puts
human <public-key-line> in mode-0600
~/.config/golems/human-confirm-anchor/allowed_signers (directory mode 0700).
Then run ~/Gits/golems/.worktrees/hooks-live/scripts/golems-confirm-pin. It
shows each principal's key fingerprint and waits for you to type PIN. Then it
locks the file and prints a line for
skills/golem-powers/human-confirm-gate/anchor.pins. That line lands by
reviewed PR, and only then does hooks-live install the gate. Use 1Password's per key,
per request authorization setting, and leave Approve for all applications
off. Other approval modes cache authorization; a cached signature is not proof
of new owner presence. See 1Password's authorization model.
No private key is exported, and the helper never calls op.
From a separate owner terminal with the 1Password SSH_AUTH_SOCK configured:
alias golems-confirm="$PWD/scripts/golems-confirm"
golems-confirm /path/to/worker/worktree topic lease --sha <full-remote-sha> --session <Claude-session-id>
The helper prints the exact command/cwd/scope before requesting the signature
and uses ssh-keygen -U to require the agent. Agent ancestry checks only catch
detectable misuse; the 1Password per-request prompt establishes owner presence.
It issues a mode-0600 token with a two-minute TTL, and checks the issuer's public
key against the trust anchor. Execute exactly that displayed command in the
specified worker session. force and delete actions generate their commands;
rewrite and settings require --command with the exact tool command.
Known agent ancestry or non-interactive issuance refuses. Private token/key
separation and an immutable trusted hook/anchor remain deployment assumptions:
a malicious process with the same UID can replace local policy; this is not a
sandbox. See the complete gate contract.
CLI
The CLI lives in packages/golem-skills. Run it from a clone:
bun packages/golem-skills/src/index.ts skills list # skills on the default branch, via the GitHub API
bun packages/golem-skills/src/index.ts setup --check # checks for bun, git, and claude
bun packages/golem-skills/src/index.ts skills install <skill-name> # copies into ~/.claude/skills/
skills list and skills install read the published default branch over the
network. They do not read your working tree. The npm package golems-cli is
behind this repo; use the release wrapper or run the CLI from source.
repoGolem config
scripts/repogolem/repogolem-config.ts builds the per-repo agent launchers
(<repo>Claude, <repo>Codex, ...) from one YAML config. You keep that config
yourself. Golems ships only the generator, the schema
(scripts/repogolem/config.schema.json) and a placeholder example
(scripts/repogolem/config.example.yaml).
export REPOGOLEM_CONFIG=~/somewhere-private/repogolem.yaml
bun scripts/repogolem/repogolem-config.ts init # starter config, with this Mac's machines: section
$EDITOR "$REPOGOLEM_CONFIG" # your projects, MCPs, op:// refs
bun scripts/repogolem/repogolem-config.ts generate # resolve refs, write the launchers
bun scripts/repogolem/repogolem-config.ts generate --check # exit 1 + the stale file if the config changed
- One file, many machines.
projects,mcpDefinitionsandglobalare shared.machines.<LocalHostName>setsreposPath(relative project paths join it),clis(the CLIs that machine has) andoverrides(objects merge, lists replace,nulldrops a project).generatepicks the section byscutil --get LocalHostName, or by--host/REPOGOLEM_HOST. - Secrets use references. Project mappings accept
op://vault/item/fieldorvarlock://NAMEnamed refs; literals are rejected.secrets.backendselects1password(the default),file, orplugin:<npm-package-or-path>. Declare named refs undervalues. The file backend reads a privatesecrets.valuesFile; thefilebackend accepts onlyvarlock://refs. Directop://refs resolve through1passwordor aplugin:adapter. See backend setup. generateresolves refs through the configured backend. The 1Password backend uses one deduplicatedop runbatch (one unlock);fileandplugin:backends use their configured value source or bulk resolver. Generate writes~/.config/repogolem/generated/{registry.json,launchers.zsh,secrets.env}. Each file is stamped with the config's sha256.--checkonly reads these files and never callsop.golem-dispatch.zshreads the generated cache through the installed runtime, so an unattended spawn does not resolve refs or wait on a provider prompt.
The tradeoff: resolved values are on disk. secrets.env holds them in
plain text, so an agent can start without an unlock prompt. The rule is that
secrets are never committed, not that they are never on disk. The guards:
files are 0600 and the directory 0700; generate refuses an output
directory inside a git work tree, a symlink, or one owned by another user;
--check reports a loosened mode as stale; and no command prints a resolved
value, only counts and key paths. If you need values never to touch disk, do
not use secrets:. Read them with op read at launch instead.
Prelaunch commands. global.prelaunch is an optional list of shell
commands, for example a ulimit or an export, that golem-dispatch.zsh runs
in order right before it starts any agent CLI. A machine can replace the list
under machines.<LocalHostName>.overrides.global.prelaunch, or drop it with
null. The commands run in a subshell that then execs the agent, so their
effects reach the agent process but never your interactive shell. A command
that fails, or runs return N, prints a warning with its index (never its
text, since its own stderr is discarded) and the launch goes ahead. Set
variables with export: each command runs in its own function, so typeset
and local stay inside it. exit is not supported: it ends the launch, with a
warning naming the command's index. With no list, launches behave exactly as
before. The config is yours and 0600, so
these commands carry the same trust as your shell rc file: anything you put
there runs at every launch. Prelaunch is not a secrets channel, and generate
refuses any command that contains an op:// ref.
Contributing
- CONTRIBUTING.md: workflow, commit format, test layout
- SECURITY.md: report vulnerabilities privately
- CODE_OF_CONDUCT.md: Contributor Covenant
License
Apache-2.0. See LICENSE.