> ## Documentation Index
> Fetch the complete documentation index at: https://platform.atlan.com/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> To act on Atlan objects, use the Atlan MCP server at https://api.atlan.com/mcp or the atlanai CLI; `atlanai --map json` prints its command map. Run a read-only identity check before any write.
> The docs MCP server at /mcp searches these docs only. It cannot read or change Atlan objects.
> SDK packages: Python `atlanai` (PyPI) and TypeScript `@atlanai/sdk` (npm). Show Python first, then TypeScript.

# Sync skills from GitHub

> Review skill changes in pull requests and publish approved versions from a protected branch.

Atlan SkillSync keeps Git as the source of truth for a collection of skills. A
pull request receives a read-only impact report. After an approved change
reaches the protected publish branch, a separate workflow publishes changed
skills and waits for the Registry security scan.

The workflow uses the supported `@v0` Action tag. The Action verifies its
pinned installer, then runs the current CLI from Atlan's signed release channel.
Its `cli-version` output records the installed CLI build for troubleshooting.

## Before you start

You need:

* a GitHub repository with Actions enabled
* a protected publish branch, normally `main`
* an Atlan workspace ID
* a dedicated Atlan API key that can publish to that workspace
* one or more repository directories containing skill packages

Each skill package must contain a case-sensitive `SKILL.md` file:

```text theme={null}
skills/
├── meeting-brief/
│   ├── SKILL.md
│   └── references/
└── release-notes/
    └── SKILL.md
```

List every destination workspace ID in the repository manifest. The API key
authenticates the publisher, but it does not choose a destination workspace.

### Keep configuration responsibilities separate

| Configure in | It controls |
| - | - |
| `.atlan/package.json` | Destination workspaces and skill roots. Do not add a `branch` or protected-branch field; the CLI rejects unknown manifest fields. |
| `.github/workflows/atlan-skill-sync.yml` | The one branch allowed to invoke publishing, through `on.push.branches`. |
| GitHub branch protection | Required pull requests, reviews, and direct-push policy for that same branch. |

## 1. Find the destination workspace

Sign in with the identity you will use to configure SkillSync, then list the
workspaces it can see:

```bash theme={null}
atlanai workspace list
atlanai workspace list --query platform
```

The first column contains the stable `workspace_...` ID. Verify the selected
workspace and your effective role before adding it to the repository:

```bash theme={null}
atlanai workspace get workspace_01example --json id,display_name,effective_role
```

Alternatively, in the Agent Registry desktop app, open the workspace menu in
the sidebar, open the menu beside the destination workspace, and select **Copy
workspace ID**. Paste that value into the `publishConfig.workspaces` list in
`.atlan/package.json`.

These commands are read-only. The API key used by GitHub must independently
have permission to publish to every selected workspace.

In GitHub, protect the same branch named in the workflow. Require reviewed pull
requests and prevent direct pushes. Protect changes to
`.github/workflows/**` and `.atlan/package.json` through the repository's normal
code-ownership process.

## 2. Declare what to publish

Create `.atlan/package.json` at the repository root. This manifest lists the
destination workspace and every repository-relative skill root:

```json theme={null}
{
  "publishConfig": {
    "workspaces": ["workspace_01example"],
    "skills": {
      "paths": ["skills", ".claude/skills", ".agents/skills"],
      "exclude": [".agents/skills/internal-only"]
    }
  }
}
```

| Field | Value |
| - | - |
| `workspaces` | One or more destination workspace IDs. The publishing credential must be allowed to publish to each workspace. |
| `skills.paths` | One or more non-overlapping repository-relative skill roots. |
| `skills.exclude` | Exact repository-relative skill directories to leave out of publishing and pruning. |

Every direct child of a configured root is a skill package and must contain a
case-sensitive `SKILL.md` file. Skill names must be unique across all roots.
For example:

```text theme={null}
skills/
├── meeting-brief/
│   └── SKILL.md
└── release-notes/
    └── SKILL.md
.claude/skills/
└── review-pr/
    └── SKILL.md
.agents/skills/
└── internal-only/
    └── SKILL.md   # excluded from publishing
```

`.atlan/package.json` is repository configuration. It must not contain a
credential or a branch setting. Keep `skills.paths` and the GitHub workflow path
filters aligned. When a repository uses different skill roots, update the path
filters to match those roots and retain `.atlan/package.json` as a trigger.

## 3. Add the publish credential

In GitHub, open **Settings → Secrets and variables → Actions** and create a
repository secret:

| Name | Value |
| - | - |
| `ATLANAI_TOKEN` | A dedicated workspace-scoped API key from Agent Registry that can publish to every configured workspace. |

To get the key in Agent Registry:

1. Open **Settings**, then select **API keys**.
2. Open **Workspace-scoped API keys** and create a new API key, or select an
   existing key to use.
3. Grant the key access to every workspace listed in
   `.atlan/package.json`. When creating a key, select the required workspace;
   for an existing key, add the required workspace access before using it.
4. Copy the API key value and save it as the `ATLANAI_TOKEN` GitHub secret.

The key represents a service account. You must be able to administer a
workspace to grant the key access to it. The key value is shown only when it is
created, so copy it then and store it only in GitHub Secrets.

Do not put the key in `.atlan/package.json`, workflow inputs, logs, or
screenshots. Use one credential per repository rather than a personal key or a
key shared by unrelated repositories.

A GitHub Environment is optional. The standard setup uses the repository secret
without an Environment.

To add an Environment approval gate:

1. Create an Environment such as `atlan-publish` in the repository settings.
2. Store `ATLANAI_TOKEN` as an Environment secret instead of a repository
   secret.
3. Configure its required reviewers and allowed deployment branches.
4. Bind the publish job to it:

```yaml theme={null}
jobs:
  publish:
    environment: atlan-publish
```

Creating an Environment without the job-level `environment` setting does not
gate the workflow or expose its Environment secret to the job.

## 4. Publish from the GitHub-controlled branch

Create `.github/workflows/atlan-skill-sync.yml`:

```yaml theme={null}
name: Sync skills to Atlan

on:
  push:
    branches: [main]
    paths:
      - "skills/**"
      - ".claude/skills/**"
      - ".agents/skills/**"
      - ".atlan/package.json"

permissions:
  contents: read

concurrency:
  group: atlan-skill-sync-${{ github.repository_id }}
  cancel-in-progress: false

jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
      - name: Check out full Git history
        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
        with:
          fetch-depth: 0
          persist-credentials: false

      - name: Publish skills
        uses: atlanai/agent-registry-action@v0
        with:
          working-directory: .
          prune: "false"
        env:
          ATLANAI_TOKEN: ${{ secrets.ATLANAI_TOKEN }}
```

`fetch-depth: 0` is required. The CLI uses complete history for source
provenance, contributor details, rename tracking, and change detection.

Replace `main` in `on.push.branches` with the exact branch that your GitHub
branch protection protects. This workflow setting, not the manifest, controls
which pushes can publish. Use `@v0` to receive compatible Action updates. Do
not use `@main` in a consumer workflow.

The Action downloads the installer only from its fixed Atlan endpoint, rejects
redirects, and gives the installer no publishing credential. The CLI receives
`ATLANAI_TOKEN` only after installation completes.

## 5. Add pull request preflight

Keep preflight separate from publishing. It must not check out or execute pull
request code, and it must not receive `ATLANAI_TOKEN`.

Create `.github/workflows/atlan-skill-preflight.yml`:

```yaml theme={null}
name: Atlan Agent Registry preflight

on:
  pull_request_target:
    types: [opened, synchronize, reopened]
    paths:
      - "skills/**"
      - ".claude/skills/**"
      - ".agents/skills/**"
      - ".atlan/package.json"

permissions: {}

concurrency:
  group: atlan-agent-registry-preflight-${{ github.event.pull_request.number }}
  cancel-in-progress: true

jobs:
  comment:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      pull-requests: write
    steps:
      - name: Register Atlan Agent Registry preflight
        uses: atlanai/agent-registry-action@v0
        with:
          mode: preflight
          github-token: ${{ github.token }}
```

The workflow uses `pull_request_target` so GitHub loads the trusted workflow
from the base branch. It does not need a checkout step. Do not add the publish
credential or a step that executes pull request files.

The first pull request that introduces this workflow cannot test its new
preflight definition. Merge the workflow, then open a second pull request that
adds or changes a skill.

## 6. Review the preflight report

When a pull request opens or receives a new commit, preflight creates or updates
one comment. The report shows:

* eligible skill counts split into added, updated, and removed
* up to five affected `SKILL.md` paths and their line changes
* the expected Registry action after merge
* front matter, name, description, title, section, and word-count checks
* advisory quality and safety signals
* the current base configuration and any proposed configuration change

Preflight maps a changed reference, template, script, or asset to the direct
child skill directory that owns it. The report counts these supporting-file
impacts and analyzes the owning `SKILL.md` when that definition still exists in
the pull request head. Review the complete pull request diff before merging.

Preflight is read-only. It does not publish, run the Registry security scan,
check out pull request code, or receive an Atlan credential. Proposed manifest
changes appear in the report but do not control its behavior until they merge.

The Action inspects at most 200 changed files and reads at most five eligible
skill bodies per run. It never copies a skill body into the comment.

With `prune: "false"` in the publish workflow, a removed count means the skill
was removed from the configured Git source. It does not archive the skill in
Atlan.

## 7. Merge and verify publishing

After review, merge the pull request into the configured publish branch. Open
the **Sync skills to Atlan** workflow run and confirm that it:

1. installs the verified current CLI release
2. validates `.atlan/package.json` and discovers every declared skill
3. uses the push event's prior commit to select changed skills, falling back to
   the complete declared set when that commit cannot be resolved
4. registers or reuses the repository artifact once in the first configured
   workspace when the checkout has a usable remote, then passes its repository
   ID to every skill publish
5. creates a skill or appends a version for changed content and skips unchanged
   packages
6. waits up to 60 seconds for each Registry security scan
7. fails on publishing errors or a blocked scan; an unsettled scan prints
   follow-up commands and leaves the skill unavailable without failing the run

Open the skill in Atlan and inspect **Source**. Confirm the expected files,
repository, commit, path, and contributor provenance. With usable remote Git
provenance, the repository artifact is created or reused in the first configured
workspace before any skill is published, and every uploaded skill carries that
repository ID. Repository registration errors stop publishing. A checkout
without usable remote provenance can publish a skill without a repository link.

The initial publish checks every configured skill. Each later push event
provides its prior commit so the CLI can narrow the work to changed skills. An
unavailable base commit causes the CLI to check every configured skill rather
than risk missing an update.

## Run the same publish locally

```bash theme={null}
atlanai skill publish
atlanai skill publish --changed-since HEAD~1
atlanai skill publish --workspace workspace_01example
```

`.atlan/package.json` is required for `skill publish`. For one local skill
without a repository manifest, use [Publish skills with the CLI](/registry/skills/how-tos/publish-with-cli).
The GitHub workflow owns branch policy. Do not add a branch setting to the
manifest or expect local `skill publish` to infer one.

## Troubleshooting

### Preflight did not run from the workflow in my pull request

`pull_request_target` uses the workflow from the base branch. Merge the trusted
workflow first, then open or update a skill pull request.

### Repository checkout is shallow

Keep `fetch-depth: 0` on `actions/checkout` in the publish workflow.

### Publishing cannot find the workspace

Confirm the workspace ID and check that the identity behind `ATLANAI_TOKEN` can
publish there. The Registry returns a generic not-found response when a resource
is absent or not visible to the caller.

### The installer failed

Retry after a transient network error. If the failure continues, report the
installer output to the Atlan CLI release team. Do not replace the installer
with an unverified download.

### A security scan blocked the skill

The workflow fails and the skill remains unavailable. Use the skill ID from the
run to inspect the result:

```bash theme={null}
atlanai skill runs skill_01example
```

### A security scan did not settle within 60 seconds

The upload succeeded, but the skill is not usable yet. The workflow prints the
skill ID and returns success so a delayed or failed scan can be investigated:

```bash theme={null}
atlanai skill runs skill_01example
atlanai skill get skill_01example
```

### Preflight found several old bot comments

The error lists the conflicting comment IDs. Delete all but one Atlan preflight
comment, then rerun the workflow.
