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

> ## Agent Instructions
> Orion is a collaborative analytics platform built by Gravity (bygravity.com). It connects to data warehouses, to Looker and dbt for existing business logic, and to a small set of external-context sources, and it lets teams ask questions in natural language to get shared analyses, dashboards, reports, and slide decks. The Connecting Data Sources page is the authoritative list of supported sources. When referencing Orion features, always link to the relevant documentation page. Orion is not open-source; it is a commercial SaaS product accessed at runorion.com.

# Export Orion Snapshots to Git

> Keep exported definitions in Git and review changes through pull requests

export const GistEmbed = ({gistUrl, rawUrl, filename, label = "script"}) => {
  const frame = useRef(null);
  const [dark, setDark] = useState(false);
  const [expanded, setExpanded] = useState(false);
  const [height, setHeight] = useState(320);
  const [copyLabel, setCopyLabel] = useState(`Copy ${label}`);
  useEffect(() => {
    const root = document.documentElement;
    const syncTheme = () => setDark(root.classList.contains('dark'));
    syncTheme();
    const observer = new MutationObserver(syncTheme);
    observer.observe(root, {
      attributes: true,
      attributeFilter: ['class']
    });
    const resize = event => {
      if (event.source !== frame.current?.contentWindow || event.data?.type !== 'gist-height') return;
      const next = event.data.height;
      if (Number.isFinite(next) && next > 0 && next < 20000) setHeight(next);
    };
    window.addEventListener('message', resize);
    return () => {
      observer.disconnect();
      window.removeEventListener('message', resize);
    };
  }, []);
  const copy = async () => {
    setCopyLabel('Copying…');
    try {
      const response = await fetch(rawUrl);
      if (!response.ok) throw new Error('Script unavailable');
      await navigator.clipboard.writeText(await response.text());
      setCopyLabel('Copied!');
    } catch {
      setCopyLabel('Open source to copy');
    }
  };
  const background = dark ? '#111719' : '#f8fafb';
  const foreground = dark ? '#d4dee3' : '#24292f';
  const muted = dark ? '#819198' : '#6e7781';
  const source = `<!doctype html><html lang="en"><head><meta charset="utf-8"><base target="_blank"></head><body>
    <script src="${gistUrl}.js?file=${encodeURIComponent(filename)}"></script>
    <style>
      html,body{margin:0;overflow:hidden;background:${background};color:${foreground};color-scheme:${dark ? 'dark' : 'light'}}
      body{padding:16px 0}
      .gist .gist-file{border:0!important;margin:0!important}
      .gist .gist-data,.gist .blob-wrapper,.gist .file,.gist .highlight{border:0!important;background:${background}!important;overflow:visible!important}
      .gist .gist-meta{display:none}
      .gist table{width:100%;table-layout:fixed;border-collapse:collapse}
      .gist .blob-num{width:42px;min-width:42px;padding:0 12px!important;color:${muted}!important;user-select:none}
      .gist .blob-code{padding:0 18px 0 4px!important;white-space:pre-wrap!important;overflow-wrap:anywhere;color:${foreground}!important}
      .gist .blob-code,.gist .blob-num{font:13px/22px ui-monospace,SFMono-Regular,Menlo,Consolas,monospace!important;background:transparent!important}
      .gist .pl-c{color:${muted}!important}
      .gist .pl-k,.gist .pl-smi{color:${dark ? '#c4b5fd' : '#8250df'}!important}
      .gist .pl-s,.gist .pl-pds{color:${dark ? '#a7d8c0' : '#116329'}!important}
      .gist .pl-c1,.gist .pl-s .pl-s1{color:${dark ? '#93c5fd' : '#0550ae'}!important}
      .gist .pl-en{color:${dark ? '#f0c78a' : '#953800'}!important}
      ::selection{background:${dark ? '#285551' : '#ccebe4'}}
    </style>
    <script>new ResizeObserver(()=>parent.postMessage({type:'gist-height',height:document.body.offsetHeight},'*')).observe(document.body);</script>
    </body></html>`;
  return <div className="not-prose my-6 overflow-hidden rounded-xl border border-gray-200 dark:border-white/10" style={{
    background
  }}>
      <div className="flex flex-wrap items-center justify-between gap-3 border-b border-gray-200 px-4 py-3 dark:border-white/10">
        <span className="font-mono text-sm text-gray-700 dark:text-gray-200">{filename}</span>
        <div className="flex items-center gap-4 text-xs">
          <a href={gistUrl} target="_blank" rel="noreferrer" className="text-gray-500 hover:text-gray-900 dark:text-gray-400 dark:hover:text-white">View Gist ↗</a>
          <button type="button" onClick={copy} aria-live="polite" className="rounded-md border border-gray-300 px-2.5 py-1 font-medium text-gray-700 hover:bg-gray-100 dark:border-white/15 dark:text-gray-200 dark:hover:bg-white/5">{copyLabel}</button>
        </div>
      </div>
      <div className="relative">
        <iframe ref={frame} title={`${filename} — GitHub Gist`} srcDoc={source} width="100%" height={expanded ? height : 320} sandbox="allow-scripts allow-popups allow-popups-to-escape-sandbox" style={{
    display: 'block',
    border: 0
  }} />
        {!expanded && <div className="pointer-events-none absolute inset-x-0 bottom-0 h-16" style={{
    background: `linear-gradient(transparent, ${background})`
  }} />}
      </div>
      <button type="button" onClick={() => setExpanded(!expanded)} aria-expanded={expanded} className="w-full border-t border-gray-200 px-4 py-3 text-sm font-medium text-gray-600 hover:bg-black/5 dark:border-white/10 dark:text-gray-300 dark:hover:bg-white/5">
        {expanded ? `Collapse ${label} ↑` : `Show full ${label} ↓`}
      </button>
    </div>;
};

<span data-page-status="beta" aria-hidden="true" />

Export Orion project definitions and selected tenant configuration to Git for version history and pull-request review. This guide includes a [shell script](#set-up-the-export) that creates snapshots and a [GitHub Actions configuration](#run-on-a-schedule) that schedules exports and opens pull requests. You host the job and manage its credentials, repository access, and failure alerts.

<Note>
  This is a one-way export
  from Orion to Git. Pull requests review changes that have already occurred in
  Orion; merging or reverting a commit does not update Orion.
</Note>

To bring GitHub documentation into Orion, use the separate [Knowledge Base integration](/knowledge-base/wiki-integrations).

## What gets versioned

The script writes the following files under `orion-snapshots/`. It exports selected fields, not a complete tenant backup. IDs in filenames distinguish objects with the same name.

| Content | Output |
| - | - |
| Project definitions: metrics, notebooks, Orion Workflows, linked Knowledge Base pages, data source selections, and group grants | `projects/<id>.dsl.toml` |
| Looker governance rules from **Always Filter Rules** in the project's Schema Explorer | `governance/<id>.json` |
| Knowledge Base document titles, paths, and content, including pages linked to no project | `knowledge-base/<id>.md` |
| Catalog metric definitions | `catalog-metrics/<id>.toml` |
| Company name, context, and profile | `company.md` |
| Data source IDs, names, types, descriptions, and active status | `datasources.json` |
| Users, tenant roles, account status, groups, group project assignments, and memberships | `access/` |

Chat conversations, memories, uploaded files, and generated outputs such as reports and CSV exports are excluded. Project definitions follow the [project export rules](/version-control/export#what-is-not-included), which exclude most private and draft content. This script does not request run history.

Connection credentials are omitted from the data source inventory. Secrets written into exported text, SQL, Python, or Knowledge Base content are **not automatically redacted**.

## Prerequisites

* **An Orion export account:** Use a dedicated user with the **Admin** role and an Orion password set during [onboarding](/profile-settings/user-onboarding). The script uses password authentication, not an interactive SSO login. See [User Management](/configuration/user-management).
* **A Git repository:** Restrict access to people authorized to read the exported definitions and user information. Reserve `orion-snapshots/` for generated files and start from a clean checkout.
* **A runner:** Install Bash, `curl`, `jq`, and `git`. The GitHub Actions example below supplies the runtime and commit identity; another runner needs its own Git identity and push credentials.

## Set up the export

Download [orion-export.sh](https://gist.githubusercontent.com/noahgcook/6a55a32a090a133c10b4aad1ff98a0d1/raw/d4c7aa05c7fe85775edb7a47899a949c2d13bcd9/orion-export.sh), save it as `scripts/orion-export.sh`, and commit it. Both examples are maintained in [orion-examples](https://github.com/Gravity-Foundation/orion-examples/tree/main/git-snapshots).

Supply these environment variables through your runner. Store the password in its secret manager, never in the repository.

| Variable | Value |
| - | - |
| `ORION_URL` | Your tenant's base URL, such as `https://your-tenant.runorion.com` |
| `ORION_USER` | Export account email |
| `ORION_PASSWORD` | Export account password |
| `PROJECT_IDS` | Optional space-separated project IDs; see [Limit project exports](#limit-project-exports) |

Run `bash scripts/orion-export.sh` from a clean checkout. The script authenticates on each run, stages the exports in a temporary directory, replaces its generated files, and commits any differences. If nothing changed, it makes no commit. Pushing and opening a pull request are handled by the scheduled job below.

<GistEmbed filename="orion-export.sh" gistUrl="https://gist.github.com/noahgcook/6a55a32a090a133c10b4aad1ff98a0d1/d4c7aa05c7fe85775edb7a47899a949c2d13bcd9" rawUrl="https://gist.githubusercontent.com/noahgcook/6a55a32a090a133c10b4aad1ff98a0d1/raw/d4c7aa05c7fe85775edb7a47899a949c2d13bcd9/orion-export.sh" />

[Open the script Gist](https://gist.github.com/noahgcook/6a55a32a090a133c10b4aad1ff98a0d1/d4c7aa05c7fe85775edb7a47899a949c2d13bcd9) if the preview does not load.

API errors, redirects, or failed response checks stop the export before it replaces the previous snapshot. A catalog metric without a TOML definition also stops the export. If adapting the script, preserve endpoint paths and trailing slashes: redirects are rejected.

### Limit project exports

Set `PROJECT_IDS` to limit project definitions and governance rules. Find each ID in its app URL: `/projects/<project-id>`. Other exports remain tenant-wide, so this setting does not remove the Admin requirement.

Without `PROJECT_IDS`, the script requests the account's project list, which can include accessible personal projects. Before scheduling, compare the exported objects with Orion to confirm the intended scope. A successful run alone does not prove coverage.

## Run on a schedule

The [GitHub Actions example](https://github.com/Gravity-Foundation/orion-examples/blob/541b041/git-snapshots/orion-export.yml) schedules a daily export at 06:00 UTC and supports manual runs.

1. Download [orion-export.yml](https://gist.githubusercontent.com/noahgcook/370eb8fd810f48de98f8843bcc01de00/raw/02fb79d7b4a9fb2ce2258371dddbdb2014513c3f/orion-export.yml) and save it as `.github/workflows/orion-export.yml`.
2. Set `ORION_URL` to your tenant URL. The example assumes the default branch is `main`; replace each reference if yours differs. Add `PROJECT_IDS` to the `env` block if needed.
3. Add `ORION_USER` and `ORION_PASSWORD` as repository secrets. Enable [Allow GitHub Actions to create and approve pull requests](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/enabling-features-for-your-repository/managing-github-actions-settings-for-your-repository), subject to organization policy. The example creates PRs; it does not approve them.
4. Commit the script and YAML to the default branch. In GitHub, select **Actions → Orion export → Run workflow** to check the first export. Configure failure alerts and retain job logs.

<GistEmbed filename="orion-export.yml" label="YAML" gistUrl="https://gist.github.com/noahgcook/370eb8fd810f48de98f8843bcc01de00/02fb79d7b4a9fb2ce2258371dddbdb2014513c3f" rawUrl="https://gist.githubusercontent.com/noahgcook/370eb8fd810f48de98f8843bcc01de00/raw/02fb79d7b4a9fb2ce2258371dddbdb2014513c3f/orion-export.yml" />

[Open the GitHub Actions workflow Gist](https://gist.github.com/noahgcook/370eb8fd810f48de98f8843bcc01de00/02fb79d7b4a9fb2ce2258371dddbdb2014513c3f) if the preview does not load.

Each run starts from `main`. If the exports differ, the job force-pushes a new commit to `orion-export`, **replacing any unmerged snapshot**. Reserve that branch for the job. Protect the default branch and require renewed approval after updates if your review policy calls for it. If Orion returns to the snapshot on `main`, close any stale export PR; the job does not close it automatically.

To retain every changed snapshot without a PR, replace the final step with `git push origin HEAD:main`, if branch policy permits.

<a id="control-mapping" />

## Review snapshots

Use the diff to review:

* **Metric SQL and Python:** Reconcile changed calculations with source data using Orion or your testing tools.
* **Company information and Knowledge Base pages:** Check changes to definitions and instructions used in analysis.
* **Looker governance rules:** Check whether changes expand access to rows.
* **Orion Workflows:** Review definitions, schedules, and recipients.
* **Access:** Review role changes, account reactivation, group project assignments, and memberships.

Files disappear from the snapshot when objects are deleted, become inaccessible, or fall outside the selected scope. Investigate the cause before accepting a deletion.

For review evidence, link the change request and test results in the PR and record the required approvals. You can [import an exported project for testing](/version-control/import#testing-an-exported-project); import creates a new project and does not restore every tenant-level surface. If approval is required before production changes, enforce it in your Orion change process. The export PR happens afterward.

## Limits

* **Snapshot history:** Changes between runs can be missed. An empty diff means only that the exported fields match the snapshot in the checkout.
* **Consistency:** Exports read multiple endpoints; changes during a run can produce a mix of states.
* **Attribution:** Git records the configured commit identity and commit time, not each original editor or edit time. The job does not enforce independent review.
* **Coverage:** The exports do not capture every setting, permission, or access event. For example, standalone Knowledge Base files contain titles, paths, and content, not page settings.

## Next steps

<CardGroup cols={2}>
  <Card title="Export a Project" icon="file-export" href="/version-control/export">
    Project export contents, options, and API reference
  </Card>

  <Card title="Import a Project" icon="file-import" href="/version-control/import">
    Reconstruct an exported definition as a new project
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.