lapbar 🎢
🇰🇷 한국어: README.ko.md
Named after the lap bar on a roller coaster: it keeps you in your seat, it is not a cage.
An expensive model for thinking, cheap models for the legwork - a Claude Code harness enforced by hooks, plus a report that shows how much it saved.
One line:
lapbar installdrops a small set of Claude Code hooks, rules and skills into~/.claude;lapbar reportreads your own transcripts and shows how much cheaper your subagents were than running everything on the head model.
Install
# From PyPI (coming soon)
pipx install lapbar # or: uv tool install lapbar
# From source (works today)
git clone https://github.com/mysoul7306/lapbar && cd lapbar
pipx install . # or: pip install .
Then:
lapbar install --dry-run # what would be installed, nothing written
lapbar install # hooks + rules + skills + agent into ~/.claude, settings.json wired (backup kept)
lapbar doctor # everything in place, hook self-tests pass
lapbar report --since 2026-10-13 # your own savings, from your own transcripts
lapbar session # one session: hook injection, rules loaded, subagent models, tokens
Why
The most expensive thing in Claude Code is the head model doing the legwork. Subagent work - scanning files, review lenses, collection - is just as good on a cheaper model, but an Agent / Workflow call that doesn't name a model inherits the head model. So hooks block that.
- model and effort must be literals -
subagent-model-guard.pydenies a missing model, a variable, or a ternary inAgent/Task/Workflowcalls. The top tier (fable) and the bottom tier (haiku, blocked by default after quality incidents) are allowed only with an[owner-approved: <model>]tag inside that same call. Effort follows the same rule (low / medium / high / xhigh literals). Allowed model names live in the hook's singleTIERStable. - lane loop -
/lane(the head only decodes, decomposes and synthesizes; read is opus high, collect is sonnet low, refute is opus xhigh) and/review-lane(3 lenses → 2 refuters, agent cap 10) turn that split into a procedure. - protected-branch push block -
git-push-guard.pydenies pushes to develop / main / master, resolving refspec and upstream to decide, and failing closed when it can't. Merges by the AI, pushes by a human. - memory hygiene -
memory-lint-hook.pychecks the memory directory for broken links, public IPs, secrets and router size at session start.
Both guards are regex-based: a safety net against the AI accidentally pushing or forgetting a model, not a sandbox against deliberate evasion (eval, config injection, shell tricks). Known evasion shapes are closed one by one as self-test cases (push 60, model 80); an AST-parser rewrite is the next milestone.
How much it saves
lapbar report reads the transcripts (jsonl) under ~/.claude/projects/, collects per-request model and tokens (input, output, cache read / write), and compares actual cost against a counterfactual: every subagent request re-priced at the head model's rate. It needs no before/after setup, so numbers show up on day one.
Measured by the person who built this harness (10 days since turning the hooks on 2026-10-13, lapbar report --since 2026-10-13, run on the night of 2026-10-22):
| Metric | Value |
|---|---|
| Requests | 16,051 (head 6,501, subagent 9,550, of which workflow 8,031) |
| Actual cost (list-price estimate) | $2,897.65 |
| If every subagent had run on the head model | $3,929.62 |
| Savings | $1,031.97 - 26.3% of the counterfactual, 35.6% of actual spend |
| Subagent effort | high 65%, xhigh 33%, medium 2% |
| Share of cache writes at 1-hour TTL | 40% (1-hour writes priced at input rate × 2) |
97% of subagent requests ran on opus (fable 2%, opus 4.8 1%); the savings are that rate gap. Head-side cost (~$1,507) is left untouched, so looking at the subagent share alone, it drops below half.
- Rates are public list price (
src/lapbar/prices.json, dated) × tokens, so they are an estimate, not a real invoice. Override with--prices. - Each requestId is counted once (one response leaves a record per content block; the record with the largest output is kept).
<synthetic>is excluded. Head vs subagent is classified by file path (<session>.jsonlvssubagents/), which assumes the post-2026-10 transcript layout. - Give the head model with
--head, or it is inferred as the costliest model on the head side (shown asinferredin the output). - To see your own numbers, dump them with
lapbar report --json > report.json.
What gets installed
| Kind | File | What it does |
|---|---|---|
| hook | hooks/subagent-model-guard.py (PreToolUse: Task, Agent, Workflow) |
forces model and effort literals, top tier needs a tag. --self-test 80 cases |
| hook | hooks/git-push-guard.py (PreToolUse: Bash) |
denies develop / main / master push, fail-closed. --self-test 60 cases |
| hook | hooks/memory-lint-hook.py (SessionStart) + scripts/memory-lint.py |
checks the memory directory, notifies only on problems |
| hook | hooks/git-readonly-guard.py (agent-scoped PreToolUse: Bash, not wired into settings.json) |
allowlist for read-only git inside the scout-git agent: pipes, redirects, write subcommands and unknown options are denied, --no-ext-diff is forced. --self-test 76 cases |
| rule | rules/zsh-pitfalls.md |
silent-failure traps in the Bash tool's zsh (incident-based) |
| rule | rules/security.md |
output hygiene - keep values from leaking when you read config, env, wrappers |
| rule | rules/memory-scope.md |
four buckets for deciding which scope a memory belongs in |
| rule | rules/subagent-review.md |
review-lane size, model tiers, the read-only principle |
| rule | rules/git-workflow.md |
branches, commits, worktrees, push permissions |
| skill | commands/lane.md, commands/review-lane.md + scripts/*-workflow.js |
the lane loop and review-lane procedures |
| agent | agents/review-readonly.md |
a read-only reviewer with only Read, Grep, Glob (the lane's refute / review role) |
| agent | agents/scout-git.md |
a git history scout for planning ("did this exist before, when and why") whose Bash is limited to read-only git by the hook above, declared in its own frontmatter |
lapbar install never overwrites your files (if contents differ it skips and tells you; use --force to overwrite). Before writing settings.json it keeps a settings.json.bak-<time>, and it won't re-add a hook wiring that is already there.
lapbar doctor checks that every asset is in place and wired, runs each hook's --self-test, feeds each guard a sample input and checks that it really denies or allows (a guard that fails to load is otherwise silent), and verifies that every hook command in settings.json (lapbar's or not) points at a file that exists and compiles.
lapbar session reads one session transcript (the current one when run inside Claude Code, else --latest or a path) and prints, in under 40 lines, how many characters each hook injected (head session only; subagent transcripts are not scanned for hooks yet), which instruction files were loaded and how big they are, which subagent types ran on which model and effort, and the token usage on both sides. Use it before cleaning up memory or trimming rules.
Using it (short)
Assumes a Claude Code where the Agent tool has an effort parameter and the Workflow tool exists (latest as of 2026-10). Without those, use only the model guard and skip /lane and /review-lane.
lapbar install→ restart Claude Code- When you call a subagent, name the model and effort. If you don't, the hook blocks it and shows why.
- Review with
/review-lane, long tasks with/lane. - Occasionally look at the numbers with
lapbar report, and at one session withlapbar session. - For "was this ever here before?" questions during planning, hand the question to the
scout-gitagent; its git is read-only.
Hook messages are English. The rule files and the /lane, /review-lane procedures are in Korean (the working language of the person who uses this harness). Copy and edit them as you like - that is why install never overwrites.
What was removed from the public release
The rules, lane procedures and the review-readonly agent in this repo were extracted from one person's live ~/.claude with lapbar bundle; the hooks and the scout-git agent are authored here (marked keep in the manifest, so bundle never overwrites them). The substitution table (scrub_map.json) holds the originals, so it lives only outside the repo ($LAPBAR_SCRUB_MAP) and the public code carries only digests. The extraction substituted or dropped terms of address, real names, accounts, home paths, project and company names, vendors, wrapper names, IPs and token patterns. lapbar bundle --check is the gate: in CI it looks only at generic patterns (home paths, IPs, JWTs, credential assignments, memory file names), while proper nouns (kept as digests) and terms of address are checked locally by the maintainer with --require-map. The external-access ledger hook (trust-ledger) is tightly coupled to a company wrapper table, so it is coming in a later release.
Development
git clone https://github.com/mysoul7306/lapbar && cd lapbar
python3 -m unittest discover -s tests
PYTHONPATH=src python3 -m lapbar.cli --help
Zero dependencies (Python 3.11+ standard library only).
License
MIT - use, modify, share and sell it freely; keep the copyright notice. Full text in LICENSE.
Why it is public - using an expensive model for thinking and cheap models for the legwork is just sensible spending, and a sensible habit should be something anyone can pick up without asking. So it is public, under MIT.
Credits
- Author and copyright: rok_root (license: MIT)
- Co-author: Claude (Anthropic) - the hooks, rules and this tool were built together in Claude Code sessions; commits carry a
Co-Authored-By: Claudetrailer.
Metadata
Release files for lapbar 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| lapbar-0.1.1.tar.gz | 134.7 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| lapbar-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 257.6 kB
Release files / lapbar-0.1.1.tar.gz
| Download URL | lapbar-0.1.1.tar.gz |
|---|---|
| Size | 134.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
2b7a5fd676637087fbf9cfd6b80d34fa3a11dcbd49f783bcff2dfa8b2d5e3097
|
|
BLAKE2b-256 checksum How to use checksums |
45d50aeeeb2395c87e6bb3bbe132e489a3cd68c457d57f77a5546c24a036c278
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.13.5 {"installer":{"name":"uv","version":"0.13.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / lapbar-0.1.1-py3-none-any.whl
| Download URL | lapbar-0.1.1-py3-none-any.whl |
|---|---|
| Size | 122.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
cd543126b871eabb50b9d0069f29100a214a24d3e4f385b91eeafff911e8def7
|
|
BLAKE2b-256 checksum How to use checksums |
90fc369c77a962f0786933062dc828dd32cb4196795ce8c2a907f3e6d8617b8a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.13.5 {"installer":{"name":"uv","version":"0.13.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Security for lapbar 0.1.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.