# GitHub Sync

> Push your ontology to GitHub as a structured markdown bundle for AI agents and programmatic consumption.

**Category:** GitHub Sync | **Tab:** integrations

---

> **GitHub Sync is optional.** It is off by default and only runs if a workspace owner connects a repository. If you don't enable it, your ontology stays in the EU. See [How Black Ice works](/docs/getting-started/how-black-ice-works).

## Overview

GitHub Sync pushes your approved ontology to a GitHub repository as a structured bundle of Markdown files. Every sync writes an `ontology/` directory that your AI localization pipeline, Claude Code project, or CI job can read straight from the file system or through the GitHub API.

GitHub Sync is **one of three integration paths** into Black Ice, alongside the [Workspace API](/docs/integrations/workspace-api-access) and the [MCP server](/docs/integrations/claude-desktop-mcp). None of them replaces the others — pick the one that matches your use case, or combine them.

## Choosing an integration path

| Path | Best for | Access model | Direction |
| --- | --- | --- | --- |
| [Workspace API](/docs/integrations/workspace-api-access) | Custom pipelines, CI jobs, bulk reads and writes, dashboards | API key, JSON over HTTPS | Read + write |
| [MCP server](/docs/integrations/claude-desktop-mcp) | Live agent access from Claude, Cursor, and other MCP clients | OAuth or API key, MCP tools | Read + write |
| GitHub Sync | Repo-resident agents, PR review workflows, versioned snapshots, offline use | GitHub PAT, Markdown files | Push from Black Ice |

**Rules of thumb**

- Need **live, queryable, writable** access to terminology? Use the API or MCP.
- Need the ontology to **live next to your code**, be reviewed in pull requests, and be readable without network access? Use GitHub Sync.
- Many teams run both: MCP for interactive agent work, GitHub Sync for a versioned snapshot the build pipeline consumes.

See [API & MCP rate limits](/docs/integrations/rate-limits) for the caps that apply to the programmatic paths.

## What gets exported

When you sync, Black Ice generates an `ontology/` directory in your repository containing:

```
ontology/
├── CLAUDE.md              # Agent instructions and ontology overview
├── classes/               # One file per concept class
│   ├── feature.md
│   ├── plan.md
│   └── platform.md
├── markets/               # One file per target market
│   ├── de-DE.md
│   ├── fr-FR.md
│   └── ja-JP.md
├── terminology/           # Term definitions per locale
│   ├── en-US/
│   ├── de-DE/
│   └── fr-FR/
└── relationships/         # Semantic relationships between concepts
    └── relationships.md
```

**CLAUDE.md** is the entry point. It tells your AI agent what the ontology contains, how it is structured, and how to use it.

**Classes** define the taxonomy — what types of concepts exist (Feature, Plan, Platform, etc.) and their translation policies.

**Markets** contain the Culture DNA for each locale — tone of voice, cultural pragmatics, grammar rules, brand identity, and golden examples that guide how content should sound in that market.

**Terminology** holds the actual term definitions — source terms, target translations, allowed/forbidden variants, usage context, and approval status.

**Relationships** maps how concepts connect to each other semantically (e.g. a Plan *hasFeature* relationships).

## Creating a GitHub token

GitHub Sync writes files to your repository, so it needs a token with **write access to repository contents**. A fine-grained personal access token scoped to a single repository is the recommended option.

### 1. Create a fine-grained token

In GitHub, go to **Settings → Developer settings → Personal access tokens → Fine-grained tokens → Generate new token**. Give it a name, choose the account that owns the repository as the **Resource owner**, and set an expiration you can live with.

<img src="/docs/github-pat-create.png" alt="GitHub new fine-grained personal access token form showing token name, resource owner and expiration fields" loading="lazy" />

> Fine-grained tokens **expire**. Note the expiry date — when the token lapses, syncs start failing with a permission error until you generate and save a new one.

### 2. Scope it to the repository and grant Contents: Read and write

Under **Repository access**, choose **Only select repositories** and select the repository you want to sync to. Then under **Permissions → Repository permissions**, add **Contents** and set it to **Read and write**. GitHub adds **Metadata: Read-only** automatically — that is expected.

<img src="/docs/github-pat-permissions.png" alt="GitHub token repository access set to only select repositories with Contents permission set to read and write" loading="lazy" />

**"Public repositories (read-only)" will not work** — Black Ice cannot commit with a read-only token.

Click **Generate token** and copy the `github_pat_...` value. GitHub shows it only once.

> Using a classic token instead? It needs the full `repo` scope.

## Setting up GitHub Sync

1. Go to **Settings** in your workspace
2. Open the **GitHub Sync** section
3. Paste the personal access token you just created
4. Specify the repository owner, name, branch, and target path
5. Choose an approval filter — sync all terms, only approved terms, or approved + pending
6. Enable **Auto-sync** to push changes automatically whenever terms are updated
7. Click **Sync now** to verify the connection

## How AI agents consume the ontology

### Direct file access (Claude Code, Cursor, etc.)

If your AI agent runs inside the repo (e.g. Claude Code with a `CLAUDE.md` file), it reads the ontology files directly from disk. No API calls needed.

```
# The agent reads CLAUDE.md first, then navigates the ontology structure
# to find the relevant class, market, and terminology files.
```

If you also want the agent to *query or update* Black Ice live during the same session, connect the [MCP server](/docs/integrations/claude-desktop-mcp) in parallel.

### GitHub API consumption

External systems can fetch ontology files programmatically via the GitHub API:

```bash
# Fetch the agent instructions
curl -H "Authorization: token YOUR_GITHUB_TOKEN" \
  https://api.github.com/repos/OWNER/REPO/contents/ontology/CLAUDE.md

# Fetch a specific market profile
curl -H "Authorization: token YOUR_GITHUB_TOKEN" \
  https://api.github.com/repos/OWNER/REPO/contents/ontology/markets/de-DE.md

# Fetch all terminology for a locale
curl -H "Authorization: token YOUR_GITHUB_TOKEN" \
  https://api.github.com/repos/OWNER/REPO/contents/ontology/terminology/de-DE/
```

### GitHub Actions integration

Trigger downstream workflows whenever the ontology is updated:

```yaml
# .github/workflows/on-ontology-update.yml
on:
  push:
    paths:
      - 'ontology/**'

jobs:
  process-ontology:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Process updated ontology
        run: |
          echo "Ontology updated — trigger localization pipeline"
          # Your pipeline logic here
```

## When Markdown files are the right choice

Black Ice exposes a REST API and an MCP server as well — files are not a workaround for a missing API, they are a different delivery model with different strengths:

- **Diff-friendly** — every ontology change creates a readable Git diff, so terminology updates can be reviewed and rolled back like code
- **Repo-native** — agents that already run inside your repository read the ontology with no extra auth, client, or network round-trip
- **Offline-capable** — once cloned, the ontology works without connectivity
- **Prose over payloads** — Markdown market profiles and translation policies read well as LLM context
- **Existing infrastructure** — branch protection, CODEOWNERS, webhooks, and GitHub Actions apply to the ontology for free

And the trade-offs, which is where the API and MCP win:

- Files are a **snapshot**, not live state — they are only as current as the last sync
- GitHub Sync is **one-way**: changes made in the repo do not flow back into Black Ice
- No filtering or querying at request time — you read whole files

## Troubleshooting

**"Sync failed" with a permission error** — the token is missing **Contents: Read and write**, or it is scoped to a different repository. Regenerate it following the steps above.

**Sync worked before and now fails** — the fine-grained token has most likely expired. Generate a new one and save it in Integrations → GitHub.

**Repository or branch not found** — check the owner, repository name, and branch for typos, and confirm the token repository access includes that repo. The branch must already exist.

**Sync succeeds but few or no terms appear** — your approval filter is excluding them. Switch it to "approved + pending" or "all terms" to confirm.

**Private repository in an organisation** — the organisation may need to approve fine-grained tokens. Ask an owner to enable them under the organisation personal access token policy.

## Availability

GitHub Sync is available on the **Builder** tier. See [Plans and Pricing](/docs/getting-started/plans-and-pricing) for details.

## Token expiry at a glance

Once a token is saved, the **GitHub Personal Access Token** field shows when it expires:

- **Expires in N days** — normal state, read from GitHub when the token is saved or used.
- **Expires in N days** (amber) — fewer than 14 days left; generate a replacement soon.
- **Expired** — syncing will fail until you paste a new token.

Fine-grained tokens always expire (90 days by default), so put a reminder in your calendar or pick a longer expiry when you create one.