cc-guides

module
v0.1.22 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 14, 2026 License: MIT

README

cc-guides

Write the prose you own; import the guides you share. cc-guides composes AGENTS.md, CLAUDE.md, and shell scripts from local fragments and shared guides pulled in by reference, and cc-guides check fails CI the moment an artifact drifts.

Release CI

Get started

brew install yasyf/tap/cc-guides

A repo describes each generated file with a .claude/fragments/<target>/ directory: a layout.toml that composes local *.fragment.* prose with imports of shared guides, plus the local pieces. Each imported alias names its source in a [sources.<alias>] table. render fetches each import at a pinned commit, writes the target with a version-free GENERATED marker, and records every pin in a lock file:

$ cat .claude/fragments/AGENTS.md/intro.fragment.md
# Acme

House rules for agents.

$ cat .claude/fragments/AGENTS.md/layout.toml
fragments = [
  "intro",
  "cc-skills:ccx",
]

[sources.cc-skills]
source = "github:yasyf/cc-skills@main"

$ cc-guides render
rendered .claude/fragments/AGENTS.md -> AGENTS.md

$ head -6 AGENTS.md
<!-- GENERATED by cc-guides from .claude/fragments/AGENTS.md/ — do not edit; edit the fragments and run 'cc-guides render'. -->
# Acme

House rules for agents.

## Compact Context (ccx)

intro is your prose; cc-skills:ccx arrives verbatim from the shared guides in cc-skills, identical across every repo that imports it. Change the shared guide once and every repo re-renders. render also writes .claude/fragments/cc-guides.lock, which pins every source to the exact commit the artifacts were built against; check and the CI action read it, so a new cc-guides release never reddens a repo that has not re-rendered.

Driving with an agent? Paste this:

Install cc-guides (`brew install yasyf/tap/cc-guides`). Give AGENTS.md a
.claude/fragments/AGENTS.md/ layout: a layout.toml composing my local
*.fragment.md prose with the shared guides I import, then run `cc-guides render`
(it writes AGENTS.md and .claude/fragments/cc-guides.lock) and wire
`cc-guides check` into CI. Reference: `cc-guides --help`.

Use cases

Fail CI when an artifact drifts

An artifact edited by hand, or left stale after a shared guide changed, should redden the build. check re-composes each target in memory — pinned to the commits the lock records — and byte-compares against disk:

$ cc-guides check
OK	AGENTS.md

$ echo "agent slop" >> AGENTS.md
$ cc-guides check
STALE	AGENTS.md
$ echo "exit: $?"
exit: 1

OK, STALE, and MISSING go to stdout as TSV; exit 1 signals drift, 2 an invalid layout. In GitHub Actions, one step gates every artifact:

- uses: actions/checkout@v7
- uses: yasyf/cc-guides@action-v1

The action installs the exact cc-guides version the lock records, so a new release never reddens a repo that has not re-rendered yet.

Keep one repo's spin on a shared guide

A repo needs its own version of a guide the rest of the fleet shares. Compose a local fragment in the slot where the import would sit — no import, no shadowing:

fragments = [
  "intro",
  "ccx",          # local ccx.fragment.md, not cc-skills:ccx
]

render reads ccx.fragment.md from the artifact dir instead of fetching the shared guide, and a layout that imports nothing locks no sources at all.

Adopt the lock on an older repo

A repo rendered by an older cc-guides (0.1.12 or earlier) carries a per-artifact banner and no .claude/fragments/cc-guides.lock. check and the CI action are lock-only, so adopt the lock with one render against the current binary — it rewrites each artifact with a version-free marker and writes the lock:

$ cc-guides render
rendered .claude/fragments/AGENTS.md -> AGENTS.md

$ git add .claude/fragments/cc-guides.lock AGENTS.md

Commit the lock alongside the artifacts. From then on a new cc-guides release re-renders byte-identically, so the lock never needs a manual bump.

Composition

An artifact dir is any directory under .claude/fragments/ that holds a layout.toml, and its path below that root is the target it renders. .claude/fragments/AGENTS.md/ renders AGENTS.md; a nested path renders a nested target. The kind — Markdown, shell comment style, or JSON — comes from the target extension. A JSON target deep-merges its pieces (arrays concatenate, objects merge) and carries no marker; the lock is its only drift record.

layout.toml is an ordered, heterogeneous fragments array. The array comes first, before any [sources.*] table: a top-level key written after a table header nests inside that table, and the binary hard-errors on that shape instead of composing empty.

fragments = [
  "agents-md",                       # local: agents-md.fragment.md in this dir
  "cc-skills:ccx",                   # import: the ccx guide from cc-skills
  { use = "cc-skills:install-binary-latest", args = { binary = "slop-cop", plugin = "slop-cop", repo = "yasyf/slop-cop", brew = "yasyf/tap/slop-cop" } },
]

[sources.cc-skills]                  # required: every imported alias declares its source
source = "github:yasyf/cc-skills@main"

A string entry is a local <name>.fragment.<ext> or an alias:name import; an inline table adds args that fill {{token}} placeholders in the imported body. Every imported alias needs its own [sources.<alias>] table — there is no baked-in default. A source spec takes one of two forms: the manifest form github:<owner>/<repo>[@<ref>], which follows the target repo's cc-guides.toml to its guides dir, or the explicit-path form github:<owner>/<repo>//<path>[@<ref>], which points straight at a subtree. Pieces join with one blank line between them, LF only, one trailing newline. Prose is never token-substituted, so ${{ github.sha }} and {{VAR}} survive verbatim.

Commands

One invocation per surface; run cc-guides <command> --help for the full flag list.

Command What it does
render [paths…] Compose each artifact dir to its target and write the lock. No paths: discover every layout under the repo.
check [paths…] Re-compose in memory, pinned to the lock's commits, and byte-compare. TSV OK/STALE/MISSING; exit 1 on drift, 2 on invalid input.
lint <dir> Check a shared-guides directory for purity: LF, one trailing newline, kind, shell shebang.
list List each artifact dir and the fragments it composes.
cat <ref> Print a fragment body: an alias:name import or a local piece by name.

--source alias=<spec> overrides where an import resolves — a github: spec or a local directory for development. --version prints the cc-guides version, which render stamps into the lock.

How it fits together

cc-guides ships two things: this binary and an importable GitHub Action. The content lives in its consumers — cc-skills is the reference home for the shared guides, and each repo carries its own layouts. An import resolves to an immutable commit through git ls-remote, fetches that tree from codeload, and caches it under the user cache dir; every artifact in a run pins the same sha, recorded in .claude/fragments/cc-guides.lock. check reads those pins from the lock, so it reproduces an artifact offline once the cache is warm and never false-fails across binary versions. Build, test, and lint conventions live in AGENTS.md.

task test   # go test -race ./...
task ci     # vet, lint, test, build

Licensed under MIT.

Directories

Path Synopsis
cmd
cc-guides command
Command cc-guides: Canonical agent guides as a shipped Go binary — render AGENTS.md, CLAUDE.md, and shell artifacts from embedded, versioned fragments
Command cc-guides: Canonical agent guides as a shipped Go binary — render AGENTS.md, CLAUDE.md, and shell artifacts from embedded, versioned fragments
Package guide is a generic, kind-aware composer for artifacts built from local prose fragments and imported shared fragments.
Package guide is a generic, kind-aware composer for artifacts built from local prose fragments and imported shared fragments.
internal
cli
Package cli builds the cobra command tree and owns exit-code mapping.
Package cli builds the cobra command tree and owns exit-code mapping.
log
Package log configures the process-wide structured logger.
Package log configures the process-wide structured logger.
version
Package version exposes the build version.
Package version exposes the build version.
Package layout parses and validates a `.claude/fragments/<target>/layout.toml` file — the per-repo config surface that composes an ordered list of local fragments and imports of shared fragments from another repo.
Package layout parses and validates a `.claude/fragments/<target>/layout.toml` file — the per-repo config surface that composes an ordered list of local fragments and imports of shared fragments from another repo.
Package lockfile reads and writes .claude/fragments/cc-guides.lock — the repo-level provenance record: the render version and one commit pin per source alias.
Package lockfile reads and writes .claude/fragments/cc-guides.lock — the repo-level provenance record: the render version and one commit pin per source alias.
Package source resolves shared-fragment imports: it parses a `github:<owner>/<repo>//<path>[@<ref>]` spec, resolves a ref to an immutable commit sha (shelling out to `git ls-remote`), fetches that commit's tree as a codeload tarball, and caches the extracted subpath under the user cache dir.
Package source resolves shared-fragment imports: it parses a `github:<owner>/<repo>//<path>[@<ref>]` spec, resolves a ref to an immutable commit sha (shelling out to `git ls-remote`), fetches that commit's tree as a codeload tarball, and caches the extracted subpath under the user cache dir.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL