CommunityEscrita e Ediçãogithub.com

appvillis-com/agent-sync

Coordination for concurrent coding agents — leases, id reservation, run journal and a generated board over a pluggable knowledge cloud.

O que é agent-sync?

agent-sync is a Claude Code agent skill that coordination for concurrent coding agents — leases, id reservation, run journal and a generated board over a pluggable knowledge cloud.

Funciona comClaude CodeCodex CLICursor
npx skills add appvillis-com/agent-sync

Installed? Explore more Escrita e Edição skills: steipete/notion, affaan-m/seo, affaan-m/brand-voice · View all 6 →

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

agent-sync — one project, many agents, no collisions

Two planes, and one rule between them:

Git is the record plane. The cloud is the coordination plane. A fact that must survive is written to git first and referenced from the cloud. A fact about who is doing what right now lives in the cloud and expires.

No cloud object is ever the only home of a durable fact. Everything below exists to keep that true while several agents write at once.

Four traps — read these before anything else

1. No backend offers compare-and-swap. Outline's documents.update has editMode: append|replace|prepend|patch and no lastRevision. So a mutable table of claims is a race: two agents read it, both write, the second wins and the first believes it holds a lease it lost. Never model coordination state as a document you rewrite. Append, then read back, and let document order decide.

2. atomicAppend: false means you are NOT the lease authority. If the configured adapter cannot append server-side, say so out loud, fall back to git-file leases, and mark the run ungated. A pretended lease is worse than no lease, because the other agent trusts it.

3. Hooks exist only in Claude Code. On Cursor, Codex and every other agent the skills CLI serves, there is no PreToolUse and nothing blocks a guarded edit. Run guard yourself before touching a guarded file and record the run as ungated. Do not describe the project as protected when it is not.

4. The store rewrites what you wrote — parse liberally, and never call an unreadable log a lost race. Outline normalises markdown on the way in: a - bullet comes back as * . A parser anchored to the character you emitted then rejects every line the server returns, and the caller is told lost when the truth is the log could not be read. That is a lie pointing at a holder who does not exist. Emit - , accept -/*/+, count anything entry-shaped that fails to parse, and fail loudly once more than 2% is unparseable. Beware the silent pre-filter especially: a continue before the regex hides bad lines from the very counter meant to expose them.

First command in any project: init

Never run anything else against an uninitialised project. init is where the storage question gets asked and answered, once, and written down.

Ask the operator these two things in chat — do not guess, do not pick a default:

  1. Where should coordination state live?
    • a knowledge cloud (outline) — real leases, shared across machines;
    • or local files (fs) — no credentials, but degraded: not the lease authority, every run recorded ungated.
  2. If cloud: the instance URL. The URL is configuration, not a secret, so you may write it. The token is not — you never ask for it in chat, never read it back, and never place it yourself.

Then run it with their answers:

python3 "$SKILL_DIR/scripts/agent_sync.py" init --backend outline --url https://<their-instance>
python3 "$SKILL_DIR/scripts/agent_sync.py" init --backend fs

init writes .claude/agent-sync.json (shape, committed), writes .env.agent-sync with the keys and an empty token line (identity, mode 600), adds .env.agent-sync and .agent-sync/ to .gitignore, and then prints exactly what the operator must do themselves — create the token in their own instance and paste it into that one line. It never overwrites an existing config or env file without --force.

Relay those closing instructions to the operator verbatim. Getting the token into the file is their step, and the design depends on it staying theirs.

Then, before every session

python3 "$SKILL_DIR/scripts/agent_sync.py" status

Idempotent. Inspects, repairs what is missing, prints a status block, names exactly ONE next action.

Read the two awareness sections it prints — they are the point, not decoration.

  • Other runs working this project right now. Who holds what, this minute. Do not take those on, and do not "just look at" the files they cover. A lease you cannot see makes you blocked; a lease you can see makes you coordinated.
  • New since you last looked. Cross-repo dependency moves that landed while you were away. A dependency that moved may unblock what you planned — or invalidate it. This list is watermarked per run, so it stays quiet until something actually changes; when it speaks, it matters.

An agent that skips this block will re-derive work someone else is doing and act on a dependency state that changed an hour ago.

What else status decides for you:

  • No credentials in the environment → degraded mode, reported, and it continues. Missing credentials are not an error, they are a smaller mode.
  • task-pipeline absent → it prints the install line and stops. Do not improvise a substitute flow; without those stages there is nothing to bind to.
npx sshlg-skills install

The commands

CommandDoes
initRun first. Ask where state lives, write config + gitignored env file, print the operator's step
statusInspect, repair, report, name one next action
bootstrapCreate the cloud container and print the id to paste into the env file
acquire <KEY>Take the lease on a task id. Prints won or lost <holder>
renew <KEY>Extend the lease. The PostToolUse hook does this for you
release <KEY>Give the lease back. Always do this, including on failure
reserve <REG>Reserve the next id in a register (DEC, OQ, DEP, …). Prints the id
release-id <REG> <ID>Return an id you did not end up writing to git
journal <text>Append one line to this run's journal
record <text>Append what you actually built--decision DEC-…, --files a,b
reconcileIntent (git) vs as-built (cloud). --set-baseline once per project
signal <DEP-ID> <state>Move a cross-repo dependency: filed/accepted/delivered/closed/refused
guard <path>Answer whether this run may write that path. Exit 0 = yes, 2 = no
boardRegenerate the read-only board and the mirror from git
whoamiPrint this run's id and its held leases

$SKILL_DIR is this skill's own directory. Every command reads .claude/agent-sync.json from the project root and needs no arguments beyond those listed.

Claiming — the shape that matters

acquire → do the work → release

Never skip release, including when the work failed: an abandoned lease blocks the task until its TTL expires, and the next agent cannot tell "in progress" from "crashed an hour ago". A lease is a promise to come back.

The lease is not the claim. The lease says who holds the task now and expires; the durable claim is the tag in git — [name] in the directions board, todo (claimed: <role>) in a service roadmap. acquire writes that tag through in the same run and release clears it, so one fact keeps one home. Do not invent a third place to record who owns a task.

Read references/lease-protocol.md before changing anything about acquisition, expiry, stealing or id allocation — it carries the exact line grammar and the replay rules that make two agents reach the same answer.

Guarded files

The project config lists registry files that several agents write. Before editing one:

python3 "$SKILL_DIR/scripts/agent_sync.py" guard docs/DECISIONS.md

Exit 2 means another run holds it. Do not edit anyway and do not "just fix one line" — those files are exactly where a lost write costs the most, because a clobbered decision looks like a decision.

In Claude Code the PreToolUse hook runs this for you and denies the edit. On other agents nothing does; run it yourself.

Reserving an id

Reading "Next free ID" from a file is not reserving it. Two agents read DEC-0216 and both write DEC-0216.

python3 "$SKILL_DIR/scripts/agent_sync.py" reserve DEC   # → DEC-0216

Allocation is positional over the append log, so every agent computes the same answer without trusting anyone's arithmetic. If you reserve an id and do not write it to git, release-id it — otherwise the number is a hole that the board reports as a leak, and nobody can tell a hole from work in a branch.

Two documentation sources, and the duty to reconcile them

Git docs answer how it should be — written before the code, often without it. The as-built record answers how it actually is — derived from what agents really wrote. Neither is a copy of the other, and neither outranks the other, because they answer different questions. The gap between them is the finding, not a defect.

The duty runs at both ends of every task:

  • Before starting (docs-study stage) — reconcile, then read both sides for the area you are about to touch. Resolve each divergence: the git doc is stale, or the as-built record is wrong, or they genuinely disagree and that is a decision to make. Building on an unresolved divergence means writing code against a system that does not exist.
  • After finishing (docs stage) — record what you actually built, update the git documents that state intent, then reconcile again. A task that updated one side has left the next agent a divergence to find the hard way.

reconcile is mechanical and says so: it compares ids, commits and presence, and refuses to judge whether the built thing matches what the document describes. That is a reading, and it is yours.

Read references/two-sources.md before the first reconcile in a project, and whenever deciding which side a piece of documentation belongs on.

Binding to task-pipeline

This skill supplies stages; it does not define them. Stage names are task-pipeline's own.

StageWhat to do here
0 Intake grillAdd the cloud KB and the board to the harvest's source ledger; acquire before the brief is committed
1 Docs studyreconcile — study git docs and the as-built record, resolve every divergence before writing code
2 Brainstormjournal; warn if a live run holds an overlapping key
3 Specreserve every id before writing it to git
4 PlanRegister file ownership for the plan's parallel groups
5 DevLease renews itself; own the submodule-commit → parent-gitlink bump
6 Tests · 7 Lint · 8 Post-deployjournal each gate result
9 Docs + wikiThe main write point — record what was built, update the git docs, signal the dependency flips, reconcile again, then board
10 Acceptancerelease every lease, write the durable claim tag through to done

Read references/pipeline-binding.md when wiring pipeline.json — it holds the skills[] entries and the gate expressions.

Configuration

Two files, and the split between them is the whole security model.

.claude/agent-sync.jsonshape, committed: which backend, TTLs, which files are guarded, which registers exist, which gates to run.

.env.agent-syncidentity, created by init, mode 600, gitignored:

AGENT_SYNC_BACKEND=outline
AGENT_SYNC_OUTLINE_URL=https://<instance>
AGENT_SYNC_OUTLINE_TOKEN=          # the operator fills this line, nobody else
AGENT_SYNC_OUTLINE_COLLECTION=     # printed by `bootstrap`

Load it before running agents:

set -a && . ./.env.agent-sync && set +a

Never write a host name or a token into the config, a test, an example or a commit. Do not handle a token value, echo it, or pass it as a command-line argument. If the operator offers one in chat, tell them to put it in that file instead.

A submodule's config declares only its own registers. Cross-repository facts belong to the parent repository. A service repo that lists the parent's decision register in its config is a configuration defect.

Backends

BackendatomicAppendRead when
outlineyesreferences/backend-outline.md — before touching any Outline call
fsno (degraded)references/backend-fs.md — the git-file fallback and its limits

Read references/adapter-contract.md before adding a backend. Six primitives, three capability flags, and a degradation path that must be honest.

Generated objects

The board and the mirror are machine-written. Their first line is

<!-- agent-sync:generated source=<repo>@<sha> at=<iso8601> — edit in git, not here -->

A write to an object missing that marker is refused, not forced. If a human took over a generated page, report it and stop; do not restore your version over theirs.

The mirror is a rendering of git, stamped with the source commit. It has no authority. When its stamp and HEAD disagree, the board gate fails — that is drift, not a formatting problem.

Non-negotiables

  • Append, read back, then act. Never rewrite a coordination document.
  • release what you acquire, on every path including failure.
  • Credentials never reach argv, a log line, or the repository.
  • Degrade out loud. ungated is an acceptable state; a false claim of enforcement is not.
  • Everything the cloud holds about a durable fact is a link to git, never a substitute.

References

Each file is loaded on its own trigger, not by default.

FileRead it when
references/adapter-contract.mdadding or auditing a knowledge backend
references/lease-protocol.mdchanging acquisition, expiry, stealing or id allocation
references/backend-outline.mdmaking any Outline API call, or debugging one
references/backend-fs.mdrunning without a cloud backend, or explaining degraded mode
references/pipeline-binding.mdwiring pipeline.json, or adding a stage hook
references/hooks.mdinstalling, debugging or removing the Claude Code hooks
references/two-sources.mdbefore the first reconcile, or when deciding where a document belongs

If this copy arrived without references/, fetch them from https://raw.githubusercontent.com/appvillis-com/agent-sync/main/plugins/agent-sync/skills/agent-sync/references/<file>.

Habilidades Relacionadas

steipete/notion

Notion CLI/API for pages, Markdown content, data sources, files, comments, search, Workers, and raw API calls.

community

affaan-m/seo

Audit, plan, and implement SEO improvements across technical SEO, on-page optimization, structured data, Core Web Vitals, and content strategy. Use when the user wants better search visibility, SEO remediation, schema markup, sitemap/robots work, or keyword mapping.

community

affaan-m/brand-voice

Build a source-derived writing style profile from real posts, essays, launch notes, docs, or site copy, then reuse that profile across content, outreach, and social workflows. Use when the user wants voice consistency without generic AI writing tropes.

community

affaan-m/crosspost

Multi-platform content distribution across X, LinkedIn, Threads, and Bluesky. Adapts content per platform using content-engine patterns. Never posts identical content cross-platform. Use when the user wants to distribute content across social platforms.

community

affaan-m/x-api

X/Twitter API integration for posting tweets, threads, reading timelines, search, and analytics. Covers OAuth auth patterns, rate limits, and platform-native content posting. Use when the user wants to interact with X programmatically.

community

affaan-m/content-engine

Create platform-native content systems for X, LinkedIn, TikTok, YouTube, newsletters, and repurposed multi-platform campaigns. Use when the user wants social posts, threads, scripts, content calendars, or one source asset adapted cleanly across platforms.

community