Ham ham
Set up and maintain Hierarchical Agent Memory (HAM) for Codex using scoped local memory files. Trigger on "go ham", "set up HAM", "ham commands", "ham help", "ham route", "ham remove", "ham update", "ham status", "ham benchmark", "ham baseline start", "ham baseline stop", "ham metrics clear", "HAM savings", "HAM stats", "HAM dashboard", "HAM sandwich", "HAM insights", "HAM carbon", or "HAM audit".
git clone https://github.com/kromahlusenii-ops/ham
T=$(mktemp -d) && git clone --depth=1 https://github.com/kromahlusenii-ops/ham "$T" && mkdir -p ~/.claude/skills && cp -r "$T/ham" ~/.claude/skills/kromahlusenii-ops-ham-ham-b1b25a && rm -rf "$T"
ham/SKILL.mdHAM
Use this skill to apply the file-based HAM workflow from this repo in Codex. Work through
CLAUDE.md, scoped CLAUDE.md files, .memory/*, and .ham/*. Do not introduce MCP-based behavior into this skill.
Current HAM skill version:
2026.02.28
Pro Guard
Before any HAM command, check for Pro signals:
with.ham/config.json"pro": true
with more thanenabledImporters"claude"- any
files**/AGENTS.md
If Pro is detected:
- allow
in Pro-aware modego ham - allow
because it has its own removal logicham remove - for all other HAM commands, print
and stopHAM Pro detected — this project is managed by HAM Pro. Manage at goham.dev
Never create, modify, or delete
AGENTS.md files from this skill.
Commands
ham commands / ham help
List the supported HAM workflows and what each one does:
: set up HAM and detect project structurego ham
: remove HAM safely while preserving Pro-owned filesham remove
: runham update
and updatebash <skill-dir>/scripts/update.sh.ham/version
: show version, update status, memory file count, and last setup signalham status
: add or updateham route
in root## Context RoutingCLAUDE.md
: launch the dashboard on port 7777ham dashboard
: show token and cost savingsHAM savings
: run the carbon reportham carbon
: generate actionable inbox items from session dataham insights
: compare baseline and HAM performanceham benchmark
: begin baseline captureham baseline start
: stop baseline capture earlyham baseline stop
: clear benchmark data after confirmationham metrics clear
: check memory system healthham audit
go ham
- Compare
to.ham/version
. If outdated, print an update notice. Never block setup.2026.02.28 - Detect platform signals:
or*.xcodeproj
: iOSPackage.swift
: Androidbuild.gradle*
: Flutterpubspec.yaml
with framework hints: Web or React Nativepackage.json
orpyproject.toml
: Pythonrequirements.txt
: RustCargo.toml
: Gogo.mod
- Detect maturity:
- 0-2 code directories: greenfield
- 3+ code directories: brownfield
- For large repos, apply a monorepo guard:
- if there are more than 20 candidate code directories, present a sorted list
- pre-select the top 15 most likely directories
- let the user adjust when needed
- never create more than 20 scoped
filesCLAUDE.md
- Generate files silently, then confirm what was created.
Pro-aware mode:
- if Pro is detected, skip directories that already have
CLAUDE.md - fill gaps only
- never touch
AGENTS.md
Generated structure:
project/ ├── CLAUDE.md ├── .ham/ │ ├── version │ └── metrics/state.json ├── .memory/ │ ├── decisions.md │ ├── patterns.md │ ├── inbox.md │ └── audit-log.md └── [major code dirs]/CLAUDE.md
Greenfield: create root files only. Brownfield: also create scoped
CLAUDE.md files in major code areas.
Append the HAM block to
.gitignore if missing:
# HAM - AI agent scaffolding (local, do not commit) .ham/ .memory/ **/CLAUDE.md !CLAUDE.md # end HAM
Before creating files, capture
.memory/baseline.json:
{"captured_at":"YYYY-MM-DD","existing_claude_md":{"found":true,"chars":4820,"tokens":1205},"notes":"Migrated from monolithic CLAUDE.md"}
If no existing root
CLAUDE.md exists:
{"captured_at":"YYYY-MM-DD","existing_claude_md":{"found":false},"estimated_baseline_tokens":7500}
Create
.ham/metrics/state.json with baseline mode enabled:
{"mode":"baseline","tasks_completed":0,"tasks_target":10,"started_at":"ISO-8601","memory_reads":0,"total_prompts":0}
The next 10 non-trivial tasks should log to baseline mode without HAM memory loading. Auto-transition to active after 10 completed tasks.
If root
CLAUDE.md is over 3,000 tokens, warn that it is oversized, list sections that should probably move into scoped CLAUDE.md files, and offer migration guidance one section at a time.
Operating Instructions
Embed these ideas in the generated root
CLAUDE.md:
- read root
before workCLAUDE.md - read the target directory
before changesCLAUDE.md - if root
hasCLAUDE.md
, use it to find the right scoped file## Context Routing - check
before architectural changes.memory/decisions.md - check
before implementing common functionality.memory/patterns.md - check if audit is due: if 14 or more days or 10 or more sessions have passed since the last audit in
, suggest running one.memory/audit-log.md - create
in new directories when they need distinct guidanceCLAUDE.md - update relevant memory files after work
- keep uncertain inferences in
.memory/inbox.md - never record secrets or user data
- never overwrite historical decisions; mark them superseded
ham route
- Find all scoped
files excluding the root file.CLAUDE.md - Build a
section in root## Context Routing
.CLAUDE.md - Add or update entries without deleting unrelated user-written content.
ham status
Report:
- installed version from
if present.ham/version - whether root HAM files exist
- scoped memory file count
- last setup signal if discoverable
- whether baseline tracking is active
- whether an update appears available
ham audit
Check:
- root
sizeCLAUDE.md - oversized scoped
filesCLAUDE.md - missing scoped memory in major code directories
entry counts.memory/- unreviewed inbox items
Append a short result to
.memory/audit-log.md.
HAM savings / HAM stats
Read
.memory/baseline.json, estimate token load from all CLAUDE.md and .memory/*.md files, and compare baseline versus current HAM setup. If no baseline exists, show raw counts and tell the user savings percentage requires a real baseline.
Use this calculation model:
root_tokens = count_tokens(read("CLAUDE.md")) subdir_files = glob("**/CLAUDE.md", exclude="root") avg_subdir = sum(count_tokens(read(f)) for f in subdir_files) / len(subdir_files) if subdir_files else 0 memory_tokens = sum(count_tokens(read(f)) for f in glob(".memory/*.md")) state = read_json(".ham/metrics/state.json") memory_weight = state["memory_reads"] / state["total_prompts"] if state.get("total_prompts", 0) >= 10 else 0.30 ham_tokens = root_tokens + avg_subdir + (memory_tokens * memory_weight) if exists(".memory/baseline.json"): baseline_mid = baseline_data["old_claude_md_tokens"] + max(500, len(subdir_files) * 300) baseline_is_measured = True else: code_dirs = count_dirs_with_code() baseline_mid = max(1000, ham_tokens * 1.5) if code_dirs <= 2 else max(3000, ham_tokens * 2.5) if code_dirs <= 10 else max(5000, ham_tokens * 3.5) baseline_is_measured = False
Display rules:
- if baseline is estimated, show raw token counts only
- do not show savings percentage or monthly projections without a real baseline
- label
weighting as estimated until at least 10 prompts are tracked.memory/
ham baseline start / ham baseline stop
: writestart
with.ham/metrics/state.jsonmode: "baseline"
: setstop
and report captured tasksmode: "active"
Task Metrics Logging
Each non-trivial task should log two JSONL entries to
.ham/metrics/tasks.jsonl, or baseline.jsonl while baseline mode is active:
{"id":"task-<hex8>","type":"task_start","timestamp":"ISO-8601","description":"...","ham_active":true,"model":"codex","files_read":0,"memory_files_loaded":0,"estimated_tokens":0} {"id":"task-<hex8>","type":"task_end","timestamp":"ISO-8601","status":"completed"}
Skip trivial queries such as HAM commands, yes or no answers, and clarifications.
Baseline mode rules:
- If
, write tomode = "baseline"
, setbaseline.jsonl
, skip scopedham_active: false
andCLAUDE.md
reads, and increment.memory/
only for completed tasks.tasks_completed - If
, or the state file is missing or unparseable, write tomode = "active"
, settasks.jsonl
, and use HAM memory normally.ham_active: true - If the state file is corrupt, warn once and treat the repo as active mode.
ham benchmark
Run
node <skill-dir>/dashboard/benchmark-cli.js [--days 30] [--model name] [--json].
ham dashboard / HAM sandwich
Run
node <skill-dir>/dashboard/launch.js --port 7777 from the project root and tell the user to open http://localhost:7777.
ham carbon
Run
node <skill-dir>/dashboard/carbon-cli.js [--last] [--days 30].
ham insights
Run
node <skill-dir>/dashboard/insights-cli.js --days 30, extract actionable items, deduplicate against .memory/inbox.md, append new items, and log the audit event.
ham update
Run
bash <skill-dir>/scripts/update.sh, then update .ham/version.
ham metrics clear
Require confirmation before deleting benchmark data.
ham remove
- Detect Pro state.
- Inventory HAM-owned versus Pro-owned files.
- Show a dry run.
- Confirm with the user.
- Remove only HAM-owned files and sections:
.memory/*
except Pro-owned config.ham/*- scoped
files created by HAMCLAUDE.md - HAM sections from root
CLAUDE.md - HAM block from
.gitignore
- Preserve user content and Pro files.
Templates
See references/templates.md for starter file shapes and references/platforms.md for platform-specific source roots and brownfield analysis cues.
Writing Rules
- Write memory into the narrowest scope that will still be useful.
- Keep root
short and global.CLAUDE.md - Use scoped
files for purpose, conventions, integrations, patterns, and gotchas that only apply in one subtree.CLAUDE.md - Never overwrite existing memory blindly; read first and merge carefully.
- Never store secrets, API keys, tokens, or user data.
- Never promote uncertain findings from
into canonical memory without user confirmation..memory/inbox.md
Session Discipline
- For non-trivial work, read memory before coding and write back durable learnings after coding.
- Skip memory churn for trivial one-shot asks.
- Record accepted architecture changes in
..memory/decisions.md - Record reusable implementation rules in
..memory/patterns.md - Keep speculation, cleanup ideas, and uncertain inferences in
..memory/inbox.md
Read references/setup-and-scopes.md when deciding where scoped
CLAUDE.md files belong.