The package manager for agent harnesses

Your agent setup,
made portable.

Your agent is more than a model. It's a harness version, MCP servers, skills, plugins, instruction files, and config you set up by hand on one machine. hlock pins all of it in a harness.lock you commit to git, and brings it back anywhere.

Get started

Works with Claude Code, Codex, Pi, OpenCode, Cursor, Gemini CLI and more.

~/projects/my-app — zsh

        

The problem

It took you weeks to get your agent just right.
Now try doing it again.

The setup that makes your agent good is scattered across your home directory, hand-edited, and invisible to git. It lives on exactly one machine: yours.

~
~/.claude/settings.json ~/.claude.json /mcpServers CLAUDE.md AGENTS.md skills/review-pr/ ~/.agents/skills/ mcp · github (stdio) mcp · linear (http) ~/.codex/config.toml ~/.pi/agent/models.json plugin · code-review@1.4.0 GITHUB_TOKEN=ghp_8kQ… opencode.json model: opus
🧑‍💻

“New laptop. Which MCP servers did I even have?”

Works on my machine

Your harness has no lockfile. Rebuilding it means archaeology through dotfiles and shell history.

👩‍🔬

“How is your Claude so good? Can you send me your setup?”

Unshareable

The config that makes your agent good can't be reviewed, diffed, or handed to a teammate or a CI runner.

🤖

“It worked yesterday. What changed?”

Silent drift

A plugin updates, a model default flips, a settings file gets edited. Nothing tells you.

🔑

“I can't commit this. There's a token in it.”

Secrets everywhere

API keys sit inline next to the config you'd want to version, so none of it gets versioned.

The fix

One file.
Every dependency.

hlock pin reads the harness you already use and writes everything it depends on into harness.lock: versions, sources, digests. Hand-written skills and config are vendored next to it in .hlock/, so the pair is self-contained.

  • Harness version and install source
  • Models per role, and where each came from
  • MCP servers, normalized across config formats
  • Skills, plugins & instructions, each with a digest
  • Secrets as placeholders, never values
harness.lock kind = "pin"
# generated by harness-lock. Do not edit by hand.lock-version = 1kind = "pin" [harness]name    = "claude-code"version = "2.1.285"source  = "brew-cask:claude-code@2.1.285" [[llm]]role     = "default"provider = "anthropic"model    = "opus" [[tool]]name   = "github"kind   = "mcp"source = "npm:@modelcontextprotocol/server-github"[tool.env]GITHUB_TOKEN = "${HLOCK_SECRET_GITHUB_GITHUB_TOKEN}" [[skill]]name   = "review-pr"origin = "local"digest = "sha256:15754ae3867d…74df9e" [[config]]path     = "~/.claude.json"restore  = "pointers"pointers = ["/mcpServers"]digest   = "sha256:b33482f12e0f…ad94cb92"

Familiar by design

You already know how this works.

If you've used uv, cargo, or npm, you already know the shape of hlock.

uv.lock · Cargo.lockharness.lock

Every dependency of your harness, pinned and hashed.

pip freezehlock pin

Record the setup you already have. Re-pin as it grows.

--lockedhlock check

Show exactly what changed since the pin.

uv sync · npm cihlock sync

Rehydrate the locked setup on any machine.

uv runhlock launch

Start a session on the locked setup, isolated from your config.

The workflow

Pin it. Check it. Bring it anywhere.

laptop — zsh

          

Safe to commit

Secrets stay out.
Always.

pin never writes a secret. API keys, tokens, auth headers, and credential-looking values become HLOCK_SECRET_* placeholders. You supply the values when you sync, and a real secret is never replaced with a placeholder.

~/.claude.json
"github": {
  "command": "npx",
  "env": {
    "GITHUB_TOKEN": "ghp_8kQx2LmZ0vYt…""${HLOCK_SECRET_GITHUB_GITHUB_TOKEN}"
  }
}
1 secret redacted · supplied as HLOCK_SECRET_* when syncing

Rehydrate anywhere

Same agent. Any machine.

hlock sync builds a plan: what's already satisfied, what it does for you, and the exact command for anything it can't.

A new laptop

Clone the repo, sync, set your secrets. Your config, skills, and plugins land where the harness expects them.

$ git clone …/my-app && cd my-app
$ hlock sync --install

An isolated env

Like a virtualenv for your harness. Materialize the lock into its own config root and leave yours untouched.

$ hlock sync --prefix .hlock/env
✓ in sync at .hlock/env/claude-code/config

A container

Write a Docker build context with the restored config baked into the image's home. Ship your agent to CI or a cluster.

$ hlock sync --docker
✓ wrote .hlock/docker/pi/Dockerfile
tip

Some steps need a human, like installing an app or setting a secret. hlock sync --skill writes an Agent Skill from the plan, so any agent can finish the job for you.

Then make it better

A locked harness is a baseline.

Once your setup is reproducible, you can measure it. Every lock hlock resolves records its success rate, cost, and latency on your own tasks.

hlock resolve

Find the best stack for your tasks

Draft an eval pack from the sessions your agent already logged, list the models and harnesses to try in harness.toml, and lock the winner with its evidence.

success-rate ≥ 0.5 cost → success → locked: min-cost
hlock tune

Tune what's inside

Go past model choice into prompts, hyperparameters, and fine-tuned small models, on your evals. Run locally, on a devbox, or lift trials to a Flyte cluster for GPUs.

$ hlock tune --backend cluster --depth ft
hlock localize

Go local

Turn any lock into an equivalent on an open-source harness and models served by Ollama or LM Studio. Your MCP servers, skills, and instructions come along.

- harness  claude-code
+ harness  opencode
- llm      anthropic:opus
+ llm      ollama:gemma3:12b

Bring your own harness

Lock the agent you already use.

claude-codecodexpiopencodecursor-agentgemini-clihermescopilot-cligooseamppydantic-ailanggraphopenai-agentsclaude-agent-sdkgoogle-adksmolagentscrewaideepagents

Lock it in under a minute.

quickstart
$ pip install hlock
$ hlock pin                      # lock your current setup into harness.lock
$ git add harness.lock .hlock/   # version it (secrets are placeholders)
$ hlock check                    # see what changed since the pin
$ hlock sync                     # on another machine: rehydrate it
$ hlock launch                   # start a session on the locked setup

Open source · Apache-2.0 · Rust core with Python bindings · pip, uv, or cargo add hlock