Commands

chamoji init

init.mdEdit on GitHub

Set this clone up to share project memory through origin, and take in what origin already has. With --agents, also connect Claude Code in this repo: the chamoji MCP server in .mcp.json and a commit hook in .claude/settings.json.

SETUP SINCE 0.11.0 CHANGES YOUR REPO

Git doesn’t clone chamoji’s memory ref, or the setting that fetches it, so every clone runs chamoji init once. It never pushes: chamoji memory sync shares what you have.

SETUPchamoji init

What it does, in order

  1. With --agents, checks both files. .mcp.json and .claude/settings.json at the repo root, wherever you run it. Both are read and checked before either is written. If chamoji can’t safely change one, it changes neither, skips the memory step and exits 1.
  2. With --agents, merges into them. The MCP server and the commit hook, unless they’re there already. Your other entries are kept. Each file is replaced in one step, so a failure never leaves half a file.
  3. Makes origin fetch memory. Adds +refs/chamoji/*:refs/chamoji/remotes/origin/* to remote.origin.fetch, once. It leaves remote.origin.push alone, so a plain git push still pushes your branch. Without an origin, it says so and changes nothing.
  4. Takes in origin’s memory. Fetches it and merges it into yours, so a fresh clone needs nothing else. If the fetch fails, it says why on stderr, and the setting stays for the next memory sync.

After init, a plain git fetch or git pull also downloads origin’s memory, to a side ref that chamoji memory doesn’t read. chamoji memory sync takes it in. chamoji release --push syncs memory too, but only in a clone that ran init. Once per clone, outside CI, init ends with a one-line hint about chamoji setup on stderr.

setup runs the same two steps as setup memory and setup agents, alongside the release settings and the commit composer hook.

What --agents writes

Both files are meant to be committed, so everyone who uses Claude Code in the repo gets the same setup. A changed file is written back as plain JSON with its indent kept, so other layout, such as blank lines, may differ.

chamoji on your PATH

{
  "mcpServers": {
    "chamoji": {
      "command": "chamoji",
      "args": [
        "mcp"
      ]
    }
  }
}

When chamoji isn’t on your PATH, the server starts with npx --yes @chamoji/cli mcp and the hook runs npx --yes @chamoji/cli agent-hook || true. A node_modules/.bin on the PATH doesn’t count, since npx and package scripts add one just for the run.

  • Name
    .mcp.json
    Description

    Gets mcpServers.chamoji, which runs chamoji mcp. A chamoji server that’s already there is yours to keep, whatever it runs.

  • Name
    .claude/settings.json
    Description

    Gets an entry in hooks.PreToolUse that runs chamoji agent-hook before Claude Code’s Bash tool runs a git commit. Any entry whose command already runs chamoji agent-hook counts as there. The || true is for a chamoji too old to know the hook: it would exit 2, which Claude Code reads as “block this”, and the file is shared.

Claude Code won’t start a server from a project’s .mcp.json until you approve it. Until then, claude mcp list shows it as pending approval.

chamoji leaves a file alone, and changes nothing, when it is a symlink or in a symlinked folder, isn’t valid JSON or a JSON object, has an mcpServers, hooks or hooks.PreToolUse of the wrong type, or holds a number that can’t be written back exactly.

On native Windows, the .mcp.json entry may need a cmd /c wrapper for npx or a chamoji shim. This hasn’t been tested there yet.

The commit hook

chamoji agent-hook is the hook itself. Claude Code runs it before a Bash command and passes the command on stdin. When the command is a git commit whose message has no card line, it prints a denial, and the agent sees this reason:

Add why this change was made: put a "Why: <reason>" line at the end of the commit message, after a blank line. Constraint:, Gotcha: and Follow-up: lines are welcome too. Only if the user told you to skip this, prefix the command with CHAMOJI_NO_CARD=1.
  • What counts: any of Why:, Constraint:, Gotcha: or Follow-up:, below the subject paragraph, in -m, --trailer or a heredoc. -m "Why: because" alone is a subject, not a card. A bare git commit has no message to read, so it’s denied too.
  • What passes: CHAMOJI_NO_CARD=1 in front of the command, a message from a file or another commit (-F, -C), --no-edit with no new message, and commands that only look, such as --dry-run and --help. Every other command passes too.
  • What it can’t see: it reads the command text, so a commit inside sh -c '…', xargs or a shell alias isn’t checked.
  • It never blocks by failing: whatever goes wrong, it prints nothing and exits 0, and the command goes through.

The hook covers Claude Code only. Other agents can use the MCP server, and write their cards by hand.

Arguments

chamoji init takes no arguments. Extra words are ignored.

Flags

  • Name
    --agents
    Type
    boolean
    Description

    Also connect Claude Code in this repo, before the memory step: the MCP server in .mcp.json and the commit hook in .claude/settings.json, at the repo root. Safe to run again: what’s there already is left as it is.

  • Name
    --no-update-check
    Type
    boolean
    Description

    Don’t check npm for a newer chamoji. See the update notice.

Common combinations

chamoji init

Once in each clone: share memory through origin, and take in what it has.

chamoji init --agents

The same, and connect Claude Code. Commit the two files it writes.

chamoji memory sync

Afterwards, whenever you want to share what you remembered.

Output

These are from real runs in fresh clones of a small repo called widgets, whose origin had one workstream in memory:

chamoji init

origin now fetches chamoji memory.
A plain git fetch or git pull downloads origin's memory but doesn't change what chamoji memory shows. Run chamoji memory sync to take it in and share yours.
Took in memory from origin: 1 entry.
chamoji setup also sets up releases, AI agents and the commit composer.

chamoji init --agents

.mcp.json: added the chamoji MCP server
.claude/settings.json: added the commit hook
These files are meant to be committed, so everyone who uses Claude Code here gets the same setup. A changed file is written back as plain JSON with its indent kept, so other layout, such as blank lines or how short lists wrap, may differ.
origin now fetches chamoji memory.
A plain git fetch or git pull downloads origin's memory but doesn't change what chamoji memory shows. Run chamoji memory sync to take it in and share yours.
Took in memory from origin: 1 entry.
chamoji setup also sets up releases, AI agents and the commit composer.

Run again, it changes nothing:

chamoji init --agents

.mcp.json: already has the chamoji MCP server
.claude/settings.json: already has the commit hook
origin already fetches chamoji memory.
A plain git fetch or git pull downloads origin's memory but doesn't change what chamoji memory shows. Run chamoji memory sync to take it in and share yours.
Took in memory from origin: 1 entry.

Run through npx, in a clone whose .claude/settings.json already allowed npm test. The file keeps its tabs and its entry:

npx @chamoji/cli init --agents

.mcp.json: added the chamoji MCP server
.claude/settings.json: added the commit hook
These files are meant to be committed, so everyone who uses Claude Code here gets the same setup. A changed file is written back as plain JSON with its indent kept, so other layout, such as blank lines or how short lists wrap, may differ. chamoji is not on your PATH, so they start it with npx.
…

.claude/settings.json

{
	"permissions": {
		"allow": [
			"Bash(npm test)"
		]
	},
	"hooks": {
		"PreToolUse": [
			{
				"matcher": "Bash",
				"hooks": [
					{
						"type": "command",
						"if": "Bash(git commit *)",
						"command": "npx --yes @chamoji/cli agent-hook || true"
					}
				]
			}
		]
	}
}

What the hook prints when Claude Code hands it git commit -m "✨ Add the date picker", which has no card. For a command it lets through, it prints nothing:

chamoji agent-hook

{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"deny","permissionDecisionReason":"Add why this change was made: put a \"Why: <reason>\" line at the end of the commit message, after a blank line. Constraint:, Gotcha: and Follow-up: lines are welcome too. Only if the user told you to skip this, prefix the command with CHAMOJI_NO_CARD=1."}}

Problems

$ chamoji init
No remote named origin, so there is nothing to share memory with. Add one and run chamoji init again.

Exit codes

  • Name
    0
    Description

    Memory sharing is set up. Also when there is no origin to share with, and when the fetch from origin failed: the message says why.

  • Name
    1
    Description

    --agents can’t safely change .mcp.json or .claude/settings.json, or can’t write one. Also outside a git repo, and anything else that fails.

chamoji agent-hook always exits 0. Its answer is what it prints. Exit codes has every command’s codes.

Was this page helpful?