---
updatedAt: 2026-09-23T21:58:09.000Z
agentTools:
  siteIndex: https://docs.readme.com/llms.txt
  siteSearch: https://docs.readme.com/agentSearch?query=term1%20term2
  projectIndex: https://docs.readme.com/main/llms.txt
  projectSearch: https://docs.readme.com/main/agentSearch?query=term1%20term2
---

# rdme Upload CLI and GitHub Action

Upload OpenAPI files and Markdown to ReadMe from a terminal or a CI job with rdme. If your project uses bi-directional sync, use the ReadMe CLI instead.

![](https://files.readme.io/13a72ff72ccf41cf818d16f4cf547a7c0adae9a7eafca023c31c01711f4aa773-image.png)

<p align="center">
  <a href="https://npm.im/rdme">
    <img src="https://img.shields.io/npm/v/rdme?style=for-the-badge" alt="NPM Version" />
  </a>
  <a href="https://npm.im/rdme">
    <img src="https://img.shields.io/node/v/rdme?style=for-the-badge" alt="Node Version" />
  </a>
  <a href="https://npm.im/rdme">
    <img src="https://img.shields.io/npm/l/rdme?style=for-the-badge" alt="MIT License" />
  </a>
  <a href="https://github.com/readmeio/rdme">
    <img
      src="https://img.shields.io/github/actions/workflow/status/readmeio/rdme/ci.yml?branch=main&style=for-the-badge"
      alt="Build status"
    />
  </a>
</p>

<p align="center">
  <a href="https://readme.com">
    <img src="https://raw.githubusercontent.com/readmeio/.github/main/oss-badge.svg" />
  </a>
</p>

`rdme` uploads OpenAPI documents and Markdown pages to your ReadMe project from a terminal or a CI pipeline, so your docs update every time you ship code. Use it when your content lives outside a synced Git repository and you want to push it to ReadMe on deploy.

If your project has [Bi-Directional Sync](https://docs.readme.com/main/docs/bi-directional-sync) enabled, you don't need `rdme`. Publishing happens when you merge, and the ReadMe CLI `(@readme/cli)` handles validation, linting, and endpoint maintenance. [Keep Your API Docs Synced With OpenAPI](https://docs.readme.com/main/docs/sync-docs-with-openapi) walks through that setup. The difference is direction: `rdme` pushes one way, from your files to ReadMe, so edits made in the ReadMe editor don't flow back to your repository, and there are no branches or reviews on the ReadMe side.

## Which CLI Should I Use?

Use `rdme` if you push content to ReadMe from CI or your terminal without a synced repository.

Use `@readme/cli` if your docs live in a Git repository synced with ReadMe (Bi-Directional Sync). It lints your pages, validates OpenAPI documents, keeps your API Reference in sync with those documents, and previews changes locally before you push. Publishing happens when you merge. Want local preview, linting, and OpenAPI validation? Turn on [Bi-Directional Sync](https://docs.readme.com/main/docs/bi-directional-sync) and switch to [`@readme/cli`](https://docs.readme.com/main/docs/cli).

## Prerequisites

* A ReadMe API key with write access to the project. Create one under **Project Settings** → **API Keys**.
* Node.js 20 or later, for running `npx rdme` in CI. The GitHub Action supplies its own runtime.
* The `rdme` major version that matches your project architecture:

| Your project              | CLI                                                | GitHub Action       |
| ------------------------- | -------------------------------------------------- | ------------------- |
| ReadMe Refactored         | `rdme@10`                                          | `readmeio/rdme@v10` |
| Legacy (not yet migrated) | [`rdme@9`](https://docs.readme.com/main/docs/rdme) | `readmeio/rdme@v9`  |

Every example on this page uses `@v10`. If you're on legacy, substitute `@v9`. To move between them, see the [ReadMe Refactored migration guide](https://docs.readme.com/main/docs/migration). Configure Dependabot on your repository to keep the action version current.

Full installation instructions and the complete command list live in the [rdme GitHub repository](https://github.com/readmeio/rdme).

## Commands

| Command                             | Uploads                                                                                                                    | Versioned (`--branch`) |
| ----------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | ---------------------- |
| `rdme openapi upload <url-or-path>` | An OpenAPI or Swagger document to the API Reference, bundling external `$ref`s and validating first (OpenAPI 3.1 included) | Yes                    |
| `rdme docs upload <path>`           | A Markdown file or directory to Guides                                                                                     | Yes                    |
| `rdme reference upload <path>`      | A Markdown file or directory to the API Reference                                                                          | Yes                    |
| `rdme changelog upload <path>`      | A Markdown file or directory to the Changelog                                                                              | No                     |
| `rdme custompages upload <path>`    | A Markdown or HTML file or directory to Custom Pages                                                                       | Yes                    |
| `rdme docs export <path>`           | `export <path>`Downloads your Guides as Markdown files into a local directory                                              | Yes                    |
| `rdme reference export <path>`      | Downloads your API Reference pages as Markdown files into a local directory                                                | Yes                    |

| Flag              | Applies to                                    | Effect                                                                                                            |
| ----------------- | --------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
| `--key=<api-key>` | All                                           | Authenticates the request. Required.                                                                              |
| `--branch=<name>` | `openapi`, `docs`, `reference`, `custompages` | Targets a branch (formerly a version). Omit it to target your default branch. Changelog entries aren't versioned. |
| `--dry-run`       | Markdown uploads                              | Validates frontmatter and prints what would be created or updated without changing anything in ReadMe             |

Run every Markdown command with `--dry-run` first when setting up new pages. The output lists each page, whether it would be created or updated, and every attribute it parsed. The export commands go the other way: they pull your published pages down as Markdown, which is useful for a backup, a migration, or moving a project onto bi-directional sync

```shell
rdme docs upload docs/ --key=$README_API_KEY --dry-run
```

## Markdown File Setup

`rdme` is directory-agnostic. It reads each Markdown file's YAML frontmatter to decide where the page goes, so your local folder layout has no effect on the sidebar. Files without frontmatter are skipped.

If you'd rather have your directory structure mirror your sidebar, that's what [Bi-Directional Sync](https://docs.readme.com/main/docs/bi-directional-sync) does.

### Required Attributes

| Attribute      | `changelog upload` | `custompages upload` | `docs upload` | `reference upload` |
| -------------- | ------------------ | -------------------- | ------------- | ------------------ |
| `title`        | Required           | Required             | Required      | Required           |
| `category.uri` | Not used           | Not used             | Required      | Required           |

These are required to create a page. Later uploads of the same file only need the attributes you're changing; anything you omit keeps its current value.

### Category

Set `category.uri` to either the full URI from the [Get all categories](https://docs.readme.com/main/reference/getcategories) endpoint or just its final segment:

```markdown
---
title: Syncing Docs via CLI / GitHub
category:
  uri: /branches/3.0/categories/guides/documentation
---
```

```markdown
---
title: Syncing Docs via CLI / GitHub
category:
  uri: documentation
---
```

### Page Order and Parent Pages

Guides and API Reference pages have a sidebar, so they accept two more hierarchy attributes. `position` sets the page's order within its category. `parent.uri` makes the page a child of another page in the same category.

```markdown
---
title: Example child page
category:
  uri: documentation
parent:
  uri: parent
position: 2
---
```

### Slugs

The slug comes from the file name: `rdme.md` uploaded to Guides publishes at `/docs/rdme`. File names are run through `slugify`, so spaces and special characters change on upload. To decouple the slug from the file name, set it explicitly:

```markdown
---
title: Example page
category:
  uri: documentation
slug: an-alternative-page-slug-example
---
```

### Other Attributes

Any attribute the ReadMe API accepts on page creation can go in frontmatter. `privacy.view` set to `public` or `anyone_with_link` publishes or hides the page. Changelog entries take a `type` such as `added`. Custom Pages set `content.type` to `html` or `markdown` automatically based on the file extension, and you can override it. The complete lists are on the create endpoints: [Create doc](https://docs.readme.com/main/reference/createdoc), [Create reference](https://docs.readme.com/main/reference/createreference), [Create changelog](https://docs.readme.com/main/reference/createchangelog), [Create custom page](https://docs.readme.com/main/reference/createcustompage).

## GitHub Actions

The `readmeio/rdme` action runs any `rdme` command inside a GitHub Actions workflow. The usual triggers are a push to the default branch, a deploy, or a release.

1. Create a workflow file in `.github/workflows/`, or open an existing one.
2. Set the `on` property to the event that should trigger the upload.
3. Add a checkout step and the `rdme` step:

   ```yaml
   # Required so the action can read your repository's contents
   - uses: actions/checkout@v4

   # Runs the rdme command against your repository
   - uses: readmeio/rdme@v10
     with:
       rdme: [your command here]
   ```

The `rdme` input takes the same syntax as the CLI, minus the leading `rdme`. This CLI command:

```shell
rdme openapi upload openapi.yaml --key=$README_API_KEY
```

becomes this step:

```yaml
- uses: readmeio/rdme@v10
  with:
    rdme: openapi upload openapi.yaml --key=${{ secrets.README_API_KEY }}
```

Complete workflow files are on the two example pages: [Syncing an OpenAPI definition](https://docs.readme.com/main/docs/github-actions-openapi-example) and [Syncing a directory of Markdown files](https://docs.readme.com/main/docs/github-actions-docs-example).

⚠️ **Store your API key as a repository secret, never in the workflow file.** Create a secret named `README_API_KEY` under your repository's **Settings** → **Secrets and variables** → **Actions**, and reference it as `${{ secrets.README_API_KEY }}`. This applies to private repositories as well as public ones; a key committed to a private repository is still in every clone and every fork. See [GitHub's documentation on encrypted secrets](https://docs.github.com/en/actions/security-guides/encrypted-secrets).

This page is itself uploaded from the `rdme` repository by the `rdme` GitHub Action. The [source file](https://github.com/readmeio/rdme/blob/main/documentation/rdme.md), the [workflow](https://github.com/readmeio/rdme/blob/main/.github/workflows/docs.yml), and its [run history](https://github.com/readmeio/rdme/actions/workflows/docs.yml) are public if you want a working example to copy.

## Other CI Environments

`rdme` is a Node.js CLI, so any CI system that runs shell commands can call it with `npx rdme@v10`. Store the API key in your CI provider's secrets and load it as `$README_API_KEY`.

Bitbucket Pipelines, `bitbucket-pipelines.yml`:

```yaml
image: node:20
pipelines:
  default:
    - step:
        script:
          - npx rdme@v10 openapi upload openapi.yaml --key=$README_API_KEY
```

CircleCI, `.circleci/config.yml`:

```yaml
version: 2.1
jobs:
  sync-docs:
    docker:
      - image: cimg/node:20.0
    steps:
      - checkout
      - run: npx rdme@v10 openapi upload openapi.yaml --key=$README_API_KEY
workflows:
  sync:
    jobs:
      - sync-docs
```

GitLab CI, `.gitlab-ci.yml`:

```yaml
image: node:20
sync-docs:
  script:
    - npx rdme@v10 openapi upload openapi.yaml --key=$README_API_KEY
```

Travis CI, `.travis.yml`:

```yaml
language: node_js
node_js:
  - 20
script:
  - npx rdme@v10 openapi upload openapi.yaml --key=$README_API_KEY
```

Secrets documentation for each: [Bitbucket Pipelines](https://support.atlassian.com/bitbucket-cloud/docs/variables-and-secrets/), [CircleCI](https://circleci.com/docs/env-vars/), [GitLab CI](https://docs.gitlab.com/ee/ci/variables/), [Travis CI](https://docs.travis-ci.com/user/environment-variables/). If one of these examples stops working, [open an issue on the rdme repository](https://github.com/readmeio/rdme/issues).

## Troubleshooting

**Pages were created in the wrong place, or overwritten.** Run the same command with `--dry-run` and read the output. It shows the category, parent, slug, and create-or-update decision for every file before anything changes.

**The CLI fails or does something unexpected.** Set the `DEBUG` environment variable to print detailed logs:

```shell
DEBUG=rdme* rdme openapi upload openapi.yaml --key=$README_API_KEY
```

Include these logs, and a copy of the files you're uploading, when you contact support. Don't leave `DEBUG` set in production pipelines.

**The GitHub Action fails.** Set the repository secret `ACTIONS_STEP_DEBUG` to `true` to enable step debug logs, then rerun the workflow. GitHub's documentation covers [viewing and downloading logs](https://docs.github.com/en/actions/monitoring-and-troubleshooting-workflows/using-workflow-run-logs).

⚠️ **Step debug logs can expose sensitive information.** GitHub masks values loaded from secrets, but anything else in your workflow's environment is logged in full and visible to everyone with read access to the repository. Enable this only in a private repository. If you're working in a public one, reproduce the workflow in a private test repository first. If sensitive data does land in a log, [delete the log](https://docs.github.com/en/actions/monitoring-and-troubleshooting-workflows/using-workflow-run-logs#deleting-logs).

<br />

# Sub pages

* [GitHub Actions Example: Syncing OpenAPI](https://docs.readme.com/main/docs/github-actions-openapi-example.md)
* [GitHub Actions Example: Syncing Markdown](https://docs.readme.com/main/docs/github-actions-docs-example.md)

# Sibling pages

* [ReadMe CLI (@readme/cli)](https://docs.readme.com/main/docs/cli.md)