quickstart

Quick Start

Run the Klock OSS v1 proof on a local repo workspace.

Klock OSS v1 is a local workflow for coordinating AI coding agents before they overwrite each other in the same repo.

OSS v1 coordinates cooperative agents that call the SDK or a wrapped tool. It is not yet filesystem-level enforcement.

This quickstart is the canonical path:

  1. reproduce the overwrite without Klock
  2. let Klock auto-start the local server for localhost workflows
  3. run the coordinated version
  4. inspect GRANT, WAIT, and DIE

1. Install the packages

pip install klock klock-langchain

2. Reproduce the failure

cd Klock-OpenSource/examples/oss_v1
python3 without_klock.py

Expected result:

  • both agents report success
  • one change disappears
  • the script ends with SILENT OVERWRITE DETECTED

3. Let localhost auto-start handle the local server

KlockHttpClient("http://localhost:3100") now tries to auto-start klock serve.

It uses this order:

  1. KLOCK_SERVER_COMMAND
  2. installed klock binary
  3. source-tree cargo run --release -p klock-cli -- serve

When auto-start happens, the SDK logs the base URL, launch command, and PID.

Disable auto-start with:

  • KLOCK_DISABLE_AUTOSTART=1
  • autoStart: false in JavaScript
  • auto_start=False in Python

4. Run the coordinated version

cd Klock-OpenSource/examples/oss_v1
python3 with_klock.py
python3 wait_die_trace.py

Expected result:

  • both changes survive
  • the protocol prints GRANT, WAIT, and DIE
  • the protected script ends with WAIT-DIE COORDINATION CONFIRMED

5. Move to the LangChain path

The same local server can sit behind LangChain file tools:

from klock import KlockHttpClient
from klock_langchain import klock_protected
from langchain_core.tools import BaseTool

klock = KlockHttpClient("http://localhost:3100")
klock.register_agent("refactor-bot", 100)

class WriteFileTool(BaseTool):
    name = "write_file"

    @klock_protected(
        klock_client=klock,
        agent_id="refactor-bot",
        session_id="repo-run-001",
        resource_type="FILE",
        resource_path_extractor=lambda kwargs: kwargs["path"],
        predicate="MUTATES",
    )
    def _run(self, path: str, content: str) -> str:
        with open(path, "w", encoding="utf-8") as handle:
            handle.write(content)
        return f"updated {path}"