Skip to content

Latest commit

 

History

History

claude-code

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 

README.md

Claude Code Pre/Post-Edit Hooks for lain

These hooks auto-claim files in lain before Claude Code edits them, and release after.

Install

  1. Make sure lain is on $PATH and a lain server is running with HTTP transport.
  2. Set LAIN_URL (default: http://localhost:9999). The MCP /mcp path is appended automatically by the CLI; passing http://localhost:9999/mcp also still works.
  3. Add to ~/.claude/settings.json (project or user):
{
  "hooks": {
    "PreToolUse": [
      { "matcher": "Edit|Write|MultiEdit", "hooks": [{ "type": "command", "command": "/path/to/hooks/claude-code/pre-edit.sh" }] }
    ],
    "PostToolUse": [
      { "matcher": "Edit|Write|MultiEdit", "hooks": [{ "type": "command", "command": "/path/to/hooks/claude-code/post-edit.sh" }] }
    ]
  }
}

Replace /path/to/hooks/... with the absolute path in this repo.

Behavior

  • pre-edit.sh: Calls lain hooks claim to register Claude Code as an agent and claim the file. If lain reports conflicts, the script writes the conflict JSON to stderr — Claude Code surfaces it in the conversation.
  • post-edit.sh: Calls lain hooks release after the edit. If lain is unreachable, the script silently exits 0 (don't break Claude's workflow).

Verification

Edit a file with Claude Code and run curl http://localhost:9999/mcp -d '...list_active_agents...' to see Claude Code's session.

Multiple Claude Code windows

All Claude Code sessions share the same agent name (claude-code) and session token. They appear as ONE agent in lain. If you need per-window tracking, set LAIN_AGENT_NAME differently per shell.

Dynamic Dispatch Caveat

An empty get_blast_radius means no static edges found, not no impact. Before mutating any symbol whose blast radius is empty, run all three:

  1. get_coupling_radar on the touched paths (git co-change partners).
  2. find_anchors on the file to surface nearby high-fan-in hubs.
  3. Check docs/dynamic-boundaries.md in the repo for documented dispatch points (message buses, DI containers, schema-driven routers).

If the file is not in dynamic-boundaries.md and all three queries are empty, proceed with the smoke command. Otherwise treat the result as evidence insufficient and require a broader smoke run before the mutation lands on disk.

You can also call explain_dispatch <symbol> for a single-shot synthesis with a verdict field — insufficient_evidence is the explicit "do not assume safe" signal.

Full reference: docs/dynamic-dispatch.md in the lain repo.