Teams often standardize how they work with AI coding tools by adding files such as AGENTS.md, CLAUDE.md, Copilot instructions, prompt templates, and editor rules to every repository. The first copy is easy. Keeping those files aligned across dozens of repositories is where the process becomes fragile.
team-ai-sync is an open-source GitHub Action that treats shared guidance as source-controlled input. It copies selected files or directories into target repositories, creates a sync branch, and opens or updates pull requests for review. It also exposes a dry-run mode so you can inspect the intended changes before the action pushes anything.
This tutorial builds the smallest useful GitHub setup, explains the configuration that controls it, and shows where the tool's safety boundary ends.
TL;DR
- Keep shared AI guidance in one source repository.
- Configure target repositories and paths in
sync-config.json. - Run
paladini/team-ai-sync@v1from GitHub Actions. - Start with
dry-run: true. - Review the generated pull requests before merging them.
The stable action is documented in the v1 repository README, and the project is licensed under MIT.
Prerequisites
You need:
- A GitHub source repository containing the shared files.
- One or more target repositories that the token can read and write.
- A fine-grained personal access token or GitHub App installation token.
- Permission to create files, branches, and pull requests in the targets.
The action itself runs on Node 24 through its GitHub Action metadata. Your source repository workflow can use the standard ubuntu-latest runner.
For GitHub targets, the project documents Contents: Read and write, Pull requests: Read and write, and Metadata: Read. If you use pull request labels, it also documents Issues: Read and write. Store the token as a repository secret. Do not put it in sync-config.json or commit it to the repository.
1. Create the shared files
Use a source repository as the place where the team reviews shared guidance. A small example might look like this:
AGENTS.md
CLAUDE.md
.editorconfig
.github/
└── instructions/
├── code-review.md
└── security.md
The action can sync individual files, whole directories, or both. Keep the source set intentionally narrow. Repository-specific secrets, credentials, local machine settings, and files containing personal data do not belong in a shared guidance bundle.
2. Add sync-config.json
Create this file in the source repository:
{
"targetRepositories": [
"your-org/api-service",
"your-org/web-app"
],
"syncMode": "overwrite",
"deleteOrphans": false,
"files": ["AGENTS.md", "CLAUDE.md", ".editorconfig"],
"directories": [".github/instructions"],
"exclude": [],
"prOptions": {
"title": "chore: sync team AI assets",
"body": "Synced from {{sourceRepo}} at {{sourceCommit}}.",
"commitMessage": "chore(ai-assets): sync team assets",
"branch": "chore/team-ai-sync",
"labels": ["automation", "chore"],
"userReviewers": [],
"teamReviewers": []
}
}
targetRepositories is processed one repository at a time. files names exact repository-relative files. directories are copied recursively. exclude can remove specific paths or glob patterns from either input.
The default syncMode is overwrite, which replaces configured target files with the source version. Use skip when a file should be added only if it does not already exist. deleteOrphans is false by default. When enabled, deletion is limited to files inside configured synced directories, but it is still worth testing with a dry run first.
The placeholders in prOptions.body are replaced with the source repository and source commit from the workflow context. The generated branch, commit, pull request title, labels, and reviewers are also configured here.
For every configured source path, the project validates that the path exists and is a file or directory of the expected type before it processes targets.
3. Add the GitHub workflow
Create .github/workflows/sync-ai-assets.yml:
name: Sync AI Assets
on:
push:
branches: [main]
workflow_dispatch:
jobs:
sync:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v4
- uses: paladini/team-ai-sync@v1
with:
github-token: ${{ secrets.TEAM_SYNC_ADMIN_PAT }}
config-path: sync-config.json
dry-run: true
Create the TEAM_SYNC_ADMIN_PAT secret in the source repository. The workflow's GITHUB_TOKEN only needs to read the source checkout. The separate github-token input is used for target repository operations.
The v1 tag is the stable action reference documented by the project. If your organization requires immutable references, resolve the tag to a commit and apply your own pinning policy.
4. Verify the dry run
Push the configuration and workflow, or start the workflow through workflow_dispatch. With dry-run: true, the action validates the configuration, clones target repositories into temporary worktrees, copies the selected paths, and reports whether changes would be made. It does not push branches or create pull requests.
Check the run for three things:
- Every target was reachable with the configured token.
- The changed paths are limited to the files and directories you intended.
- The output identifies failures per target instead of hiding them behind one aggregate result.
When the dry run is correct, remove dry-run: true or set it to false. The real workflow creates or resets the configured sync branch, commits only when there are changes, pushes that branch, and creates or updates one pull request per changed target.
Expected result
After a real run, each changed target should have a review request from the configured sync branch. The target owner can inspect the diff, request changes, and merge it through the repository's normal controls.
The action does not merge pull requests, approve them, bypass branch protection, or change target repository settings. That is the important operational distinction: synchronization is automated, while acceptance remains a repository-owner decision.
Why this works better than manual copying
The source repository becomes the review boundary for shared guidance. A change to a common instruction file is made once, tested once, and distributed as an ordinary pull request diff. Each target retains its own history and can reject or delay the update.
The configuration also makes scope explicit. Instead of granting a workflow permission to rewrite arbitrary paths, it names the files and directories that are eligible for synchronization. The implementation rejects absolute paths, .. traversal, .git paths, and values that resolve outside the repository root.
The project supports GitHub Actions, a GitLab CI/CD Component, and a Bitbucket Pipe. The configuration shape is similar, but the supported operating model is platform-specific. A GitHub workflow should target GitHub repositories rather than silently mixing platforms.
Failure modes and limitations
The token can reach too much
The action can clone targets, push branches, create pull requests, apply labels, and request reviewers. Use a fine-grained token or GitHub App installation with the smallest target set that supports the rollout. A path validator cannot compensate for an overpowered credential.
deleteOrphans can remove synced files
When deleteOrphans is enabled, files removed from a configured source directory can be removed from the corresponding target directory. Keep it disabled during the pilot, then enable it only with a reviewed dry-run diff.
Shared guidance is not automatically correct
The action distributes files; it does not decide whether an instruction is appropriate for every repository. Keep target-specific rules out of the shared bundle, and review changes for tool compatibility, scope, and unintended policy conflicts.
It does not merge the result
Generated pull requests still need review and merge. That is deliberate. If your process requires approvals, status checks, or security review, configure those controls in the target repositories.
FAQ
Can I sync directories such as .cursor/rules?
Yes. Add the directory to directories and keep the path repository-relative. The project documents .cursor/rules/**, .github/instructions/**, and .github/prompts/** as common use cases.
Can I preview changes without creating a pull request?
Yes. Set dry-run: true. The dry run validates and simulates the sync without pushing branches or opening pull requests.
Does it support files outside GitHub?
The project includes packages for GitLab and Bitbucket, but each package is intended for repositories hosted on its own platform. Use the package matching the target platform.
Where should secrets go?
Do not sync secrets, private keys, credentials, or machine-specific configuration. Store the action token in the source repository's secret store and keep the synchronized bundle limited to reviewable guidance and settings.
AI assistance disclosure
AI assistance was used to organize and edit this tutorial. The commands, configuration fields, security boundaries, stable action reference, and verification results were checked against the public paladini/team-ai-sync repository at the v1 tag and a clean checkout of that tag.
Takeaway
If your team maintains AI guidance in more than one repository, make the source explicit and distribute it through reviewable changes. Start with a small target set, run dry-run: true, inspect the paths and permissions, and expand only after the pull request workflow is predictable.
What is the first shared file your team would synchronize: AGENTS.md, editor rules, prompt templates, or something else?
Top comments (0)