crefft Source 2026.10.4

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

TemplatePurposeTriggerNeeds
workflows/sync-crefft.ymlAgents, commands, and configWeekly, manual1
workflows/doc-sync.ymlRemind pull-request authors which documents a source change touchesPull 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 crefftDestination 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:

ActionVersionSHA
actions/checkoutv7.0.13d3c42e5aac5ba805825da76410c181273ba90b1
actions/github-scriptv9.0.03a2844b7e9c422d3c10d287c895573f7108da1b3
peter-evans/create-pull-requestv8.1.15f6978faf089d4d20b00c7766989d076bb2fc7f1
tj-actions/changed-filesv47.0.69426d40962ed5378910ee2e21d5f8c6fcbf2dd96

See Also

Footnotes

  1. Requires contents: write and pull-requests: write to propose updates to crefft-owned Claude configuration files in your project. ↩