GitHub Workflow Templates
Source index and context
crefft > Configs > GitHub
The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119.
Reusable GitHub Actions workflows for projects that adopt crefft. These are
templates: they live here rather than in .github/workflows/ so GitHub
cannot schedule them inside crefft itself.
Quick Reference
| Template | Purpose | Trigger | Needs |
|---|---|---|---|
workflows/sync-crefft.yml | Agents, commands, and config | Weekly, manual | 1 |
workflows/doc-sync.yml | Remind pull-request authors which documents a source change touches | Pull requests touching src/, lib/, app/ | pull-requests: write |
Why these are templates, not live workflows
A workflow placed in .github/workflows/ runs in the repository that holds
it. sync-crefft.yml previously sat in crefft’s own workflow directory
and therefore ran against crefft every Monday, copying configs/claude/*
into a second .claude/ tree and attempting a self-referential pull request.
doc-sync.yml triggers on src/**, lib/**, and app/**, none of which
exist in a documentation repository.
Templates MUST NOT be placed in .github/workflows/ of the repository
that publishes them. Copy them into the consuming project instead.
Adopting sync-crefft.yml
Keeps a downstream project’s .claude/ tree in step with crefft.
Install
mkdir -p .github/workflows
curl -fsSL -o .github/workflows/sync-crefft.yml \
https://raw.githubusercontent.com/agh/crefft/v2026.10.1/configs/github/workflows/sync-crefft.yml
Configure
Set CREFFT_REF to the release tag you have reviewed. It MUST NOT be a
branch such as main. The default is v2026.10.1. Optionally set
CREFFT_COMMIT to the independently reviewed full commit SHA:
env:
CREFFT_REPO: agh/crefft
CREFFT_REF: v2026.10.1
CREFFT_COMMIT: ''
The template checks out that release into .crefft-upstream/ and invokes
.crefft-upstream/scripts/sync-claude-config.sh --ref "${CREFFT_REF}", adding
--commit when CREFFT_COMMIT is set. There is no separate copying logic
or configurable SYNC_PATHS mapping. The runner needs Bash, Git, and Python 3.
The applier verifies the checkout against the release tag and optional commit SHA before writing. It installs these fixed mappings:
| Source in crefft | Destination in the project |
|---|---|
agents/ | .claude/agents/ |
commands/ | .claude/commands/ |
configs/claude/skills/ | .claude/skills/ |
configs/claude/infrastructure/ | .claude/infrastructure/ |
configs/claude/settings.json | .claude/settings.json |
Every source component is required; a missing source fails before any write.
Existing settings are preserved. Replacing them requires an explicit
--overwrite-settings argument to the script; the template does not pass it.
Why
One applier keeps automated and manual installs consistent. A release pin prevents weekly jobs from following an unreviewed branch, and an independent commit pin detects a moved tag.
Ownership and adoption
Consumers MUST retain and commit .claude/crefft-receipt.json with the
installed files. It records the release, resolved commit, and SHA-256 of each
installed file. Only previously recorded files can be replaced or removed.
Project-specific files beside them survive.
An unowned conflicting path stops the entire sync with a list of conflicts
and no writes. For an earlier installation without a receipt, consumers
MAY run the pinned script manually with --adopt to claim identical
files. Adoption compares contents only; differing files still conflict.
Locally modified owned files and symlinks also block the sync. Review
conflicts rather than deleting project additions to make a run pass.
Do: use the pinned script for adoption and keep its receipt. Don’t: mirror a whole directory or move project-specific agents into a user’s home directory merely to protect them from sync.
See manual sync for the same applier outside GitHub Actions.
Why
File-level ownership makes upstream deletion safe without granting crefft
ownership of the project’s entire .claude/ tree. Preserving settings
protects project-specific permissions and hooks.
Repository settings
The workflow opens a pull request, so the project MUST enable
Settings → Actions → General → Allow GitHub Actions to create and approve
pull requests. Without it peter-evans/create-pull-request fails with a
permissions error — this is what caused all fourteen historical failures of
this workflow in crefft.
Pull requests authored with the default GITHUB_TOKEN deliberately do not
trigger further workflow runs. If the sync pull request must run your CI, set
a CREFFT_SYNC_TOKEN secret holding a fine-grained personal access token
with contents: write and pull-requests: write on the project; the
template prefers it when present.
Dry runs
Run the workflow manually with Preview changes without creating a pull
request ticked. The dry run reports git status --porcelain to the job
summary after running the applier in a temporary project clone. It neither
changes the project’s .claude/ tree nor opens a pull request; there is no
workspace-wide restore or clean step. dry_run is a Boolean input, so the
conditions compare inputs.dry_run == true.
The workflow validates VERSION as one calendar version before exporting it.
Preview outputs enter the shell through env: and are printed with
printf '%s\n', never interpolated into shell source.
Why
A preview needs the same ownership checks as an install, without applying changes to the working project. Treating version and report values as data prevents filenames or upstream text from becoming shell commands.
Adopting doc-sync.yml
Posts one comment per pull request listing the documents that correspond to the changed source files.
Install
mkdir -p .github/workflows
curl -fsSL -o .github/workflows/doc-sync.yml \
https://raw.githubusercontent.com/agh/crefft/main/configs/github/workflows/doc-sync.yml
Configure
Set DOC_ROOT to the directory holding your prose documentation, and adjust
the paths filter to match your source layout. The mapping strips any
extension, so lib/parser.py maps to docs/lib/parser.md; the original
template assumed TypeScript and produced docs/lib/parser.py.md.
Scope
This check is advisory. It MUST NOT be treated as proof that documentation is current — it only reports which documents exist for the files that changed. It never fails the build.
Pinning policy
Every uses: reference in these templates is pinned to a full commit SHA
with the release tag in a trailing comment, per
GitHub’s secure-use guidance.
A tag is a mutable pointer; tj-actions/changed-files had its tags
retargeted during the March 2025 supply-chain incident, which a SHA pin would
have contained.
crefft has no Dependabot configuration. These templates are not updated
automatically: when the pins in configs/tool-versions.json change, update
the templates, .forgejo/workflows/, and .github/workflows/ in the same commit.
Current pins:
| Action | Version | SHA |
|---|---|---|
actions/checkout | v7.0.1 | 3d3c42e5aac5ba805825da76410c181273ba90b1 |
actions/github-script | v9.0.0 | 3a2844b7e9c422d3c10d287c895573f7108da1b3 |
peter-evans/create-pull-request | v8.1.1 | 5f6978faf089d4d20b00c7766989d076bb2fc7f1 |
tj-actions/changed-files | v47.0.6 | 9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 |
See Also
Footnotes
-
Requires
contents: writeandpull-requests: writeto propose updates to crefft-owned Claude configuration files in your project. ↩