Skip to main content

Command Palette

Search for a command to run...

オリジン

origin repo clone-fast を使って CI でクローンキットをセットアップする

origin repo clone-fast は、CI ジョブでの git clone を置き換えるコマンドです。ゼロからクローンするのではなく、あらかじめビルドされたクローンキット (クローンキット を有効にしたリポジトリごとに Cherri Code がビルドする、パックされたリポジトリのスナップショット) をダウンロードし、キットのビルド後に追加されたオブジェクトのみを fetch します。このページでは、短命な Origin トークンをランナーに渡す方法と、Buildkite、GitHub Actions、その他の CI システム でこのコマンドを実行する方法を説明します。

仕組み

origin repo clone-fast {owner}/{repo} [DIR] を実行するたびに、以下の処理が行われます。

  1. CURSOR_AUTH_TOKEN のトークンを使って、Origin からキットのマニフェストを取得します。マニフェストには、キットのアーティファクトと tip のコミットが記載されています。
  2. gitcdn.origin.cursor.com からパックのアーティファクトをダウンロードし、そのサイズを確認します。--verify を指定すると、ダウンロード中にハッシュも確認します。
  3. 空である必要がある宛先ディレクトリにインストールします。
  4. クローンを top-up します。キットのビルド以降に追加されたオブジェクトを取得し、default branch の現在の tip をチェックアウトします。--no-top-up を指定した場合、チェックアウト先はキットの tip のままです。--bare は、ワーキングツリーを持たない bare repository を作成します。

キット経路が成功すると、コマンドは標準出力に mode: clone-kit を出力します。いずれかのステップが失敗した場合は、デフォルトの --fallback auto により通常の git clone が実行され、mode: git-clone が出力されます。代わりにステータス 1 で終了させたい場合は --fallback never を指定してください。

トークンとチェックアウトの挙動は、どの CI システムでも同じです。

  • トークンは最大 15 分で期限切れとなり、更新はできません。 クローンの直前に mint してください。
  • CLI は CURSOR_AUTH_TOKEN からトークンを読み取ります。 origin を実行する shell でエクスポートしてください。
  • クローン完了時点では default branch の tip にいます。 特定のコミットをビルドするには、その後に git fetch origin SHA と git checkout SHA を実行してください。Origin は到達可能なコミットであれば SHA で提供します。

Prerequisites

  • ランナー上の Origin CLI。curl -fsSL https://downloads.cursor.com/origin/install.sh | sh でインストールすると、バイナリは $HOME/.local/bin/origin に配置されます。Linux ランナーでは x64 または arm64 上の glibc が必要です。Alpine やその他の musl イメージは非対応です。macOS ランナーはサポートしています。Install the Origin CLI を参照してください。
  • bash、git、jq、curl 7.55 以降、openssl 1.1.1 以降。clone-fast はダウンロードに curl を使用します。
  • 次のホストへのネットワーク egress:
ホスト用途
downloads.cursor.comCLI のインストール
origin.cursor.comキットのマニフェストと git 操作
gitcdn.origin.cursor.comキットのダウンロード
api.cursor.comトークンの発行と Origin App からのミラー同期リクエスト

パスを選ぶ

CI システムトークンの取得元セクション
Buildkite (ホスト型またはセルフホストのエージェント、Origin をリポジトリ プロバイダーとして接続済み)Buildkite Agent API (checkout フック内)Buildkite
GitHub ActionsOrigin App (ワークフローのステップ内)GitHub Actions
GitLab CI、Jenkins、CircleCI、セルフホストのワーカー群Origin App (ジョブ内)その他の CI システム

Buildkite

トークンは Buildkite が発行します。エージェントのデフォルトの Git チェックアウトを、Buildkite Agent API にトークンを要求して origin repo clone-fast を実行する checkout フックに置き換えてください。

Origin を接続するには Buildkite の organization 管理者、Buildkite アプリをインストールするには Origin の管理者である必要があります。

1

Origin を Buildkite に接続する

Buildkite で Settings > Repository Providers > Add Provider > Origin の順に選択するか、New Pipeline ページで Connect Origin account を選択します。オーナーとリポジトリを選択し、Buildkite アプリをインストールします。Buildkite は、リポジトリのコンテンツと Pull Requests への読み取り権限、およびチェックへの読み取り・書き込み権限を要求します。詳細は Buildkite のドキュメントの Origin を参照してください。

2

エージェントに Origin CLI をインストールする

前提条件に従い、curl、git、jq を PATH に配置します。

3

チェックアウトディレクトリを空にしておく

エージェントがビルド間でビルドディレクトリを保持する場合は、フックの実行前に $BUILDKITE_BUILD_CHECKOUT_PATH を空にしてください。clone-fast は空のディレクトリを必要とし、ファイルが残っていると git clone にフォールバックします。

4

checkout フックを追加する

セルフホストのエージェントでは、以下のスクリプトをエージェントの --hooks-path ディレクトリに checkout という名前で保存します。Buildkite ホステッドエージェントでは、vendored でないプラグインの checkout フックとして配布するか、ステップに checkout: { skip: true } を設定し、ステップの command で同じコマンドを実行します。リポジトリはまだチェックアウトされていないため、リポジトリフックで checkout を定義することはできません。Buildkite のドキュメントの Agent hooks と Git checkout を参照してください。

このフックは、パイプラインのリポジトリにスコープされたトークンを要求し、CURSOR_AUTH_TOKEN としてエクスポートしたうえで clone-fast でクローンし、origin auth setup-git で Git の認証情報ヘルパーを登録して、$BUILDKITE_COMMIT をチェックアウトします。エージェントトークンは stdin 経由で curl に渡されるため、コマンドラインに現れることはありません。

#!/usr/bin/env bashset -euo pipefailbody=$(printf '{"repo_url":"%s"}' "$BUILDKITE_REPO")token=$(printf 'Authorization: Token %s\n' "$BUILDKITE_AGENT_ACCESS_TOKEN" \  | curl -fsS -X POST -H @- \      -H 'Content-Type: application/json' -H 'Accept: application/json' \      --data "$body" \      "${BUILDKITE_AGENT_ENDPOINT%/}/jobs/${BUILDKITE_JOB_ID}/cursor_origin_access_token" \  | jq -er '.token')# clone-fast に渡すのは clone URL ではなく owner/repo です。repo=${BUILDKITE_REPO#https://origin.cursor.com/}repo=${repo#git/}repo=${repo%.git}export CURSOR_AUTH_TOKEN="$token"origin repo clone-fast "$repo" "$BUILDKITE_BUILD_CHECKOUT_PATH" --verifyorigin auth setup-gitcd "$BUILDKITE_BUILD_CHECKOUT_PATH"git fetch origin "$BUILDKITE_COMMIT"git checkout -q "$BUILDKITE_COMMIT"

コミットを指定せずにビルドが開始された場合、BUILDKITE_COMMIT は HEAD になります。続く 2 行の git コマンドがリモートの HEAD を取得し、clone-fast がすでにチェックアウトしたデフォルトブランチの tip にワーキングツリーを残します。

  • $BUILDKITE_REPO はそのまま送信してください。 repo_url は、パイプラインに登録されたリポジトリ URL と .git を含めて完全に一致していなければなりません。表記が異なると HTTP 400 が返ります。
  • トークンは参照専用で、パイプラインのリポジトリにスコープされています。 repository:contents:read を持ち、15 分で失効します。後続のジョブや、mint から 15 分以上経過した git 操作では、同じリクエストで新しいトークンを取得する必要があります。
  • 503 の場合はリトライしてください。 Agent API が HTTP 503 を返した場合は、その Retry-After ヘッダーに従って待機してからリトライします。Buildkite 自身の認証情報ヘルパーと同じ動作です。

GitHub Actions とその他の CI providers

GitHub Actions などの CI システムは、それぞれ独自の token を 発行 します。Origin App を一度作成し、clone 対象のリポジトリにインストールしたうえで、各 ジョブ にアプリの 秘密鍵 と 2 つの ID を渡します。ジョブ は 短期有効な app JWT に署名し、それを installation token と交換します。field の詳細なリファレンスは、App JWT と Create Installation Access Token を参照してください。

Origin App を作成する

アプリのインストールには Workspace 管理者権限が必要です。

アプリを登録する

1

Ed25519 キーペアを生成する

使用できるのは Ed25519 キーのみです。

openssl genpkey -algorithm ED25519 -out origin-app-private.pemopenssl pkey -in origin-app-private.pem -pubout -out origin-app-public.pem
2

アプリを作成して公開鍵を追加する

Origin app settings でアプリを作成し、origin-app-public.pem のコンテンツを署名キーとして追加します。1 つのアプリで保持できる有効な署名キーは最大 10 個です。

3

App ID をコピーする

App ID はアプリのページに表示されます。App ID は app_ で始まります。

アプリのインストール

1

owner にアプリをインストールする

同じ設定内にあるアプリのインストールページから、クローン対象のリポジトリを保有する owner にアプリをインストールし、対象のリポジトリを選択します。

2

installation id をコピーする

installation id は、インストールページの URL /codebase/settings/apps/installations/{installationId} に含まれています。installation id は i_ で始まります。

認証情報を保存する

秘密鍵はCIシステムのシークレットとして保存し、PEMテキスト全体を含む環境変数ORIGIN_APP_PRIVATE_KEYとしてジョブに渡します。App IDとインストールIDは、通常の変数ORIGIN_APP_IDおよびORIGIN_INSTALLATION_IDとして保存します。CIシステムがシークレットをファイルとしてマウントする場合は、まずORIGIN_APP_PRIVATE_KEY=$(cat /path/to/origin-app-private.pem)で鍵を読み込んでください。

ジョブ 内でトークンを 発行 する

以下の関数は app JWT に署名し、それを installation token と交換します。この JWT は alg に EdDSA を使用し、iss と kid に App ID、aud に origin-apps を設定し、exp は 15 分先に設定します。App JWT のリファレンスでは有効期間を約 5 分とすることを推奨していますが、installation token は それを 発行 した JWT より長く存続することはないため、このレシピでは 15 分の JWT に署名し、トークンが 15 分をフルに使えるようにしています。リクエストで要求している repository:contents:read は、clone、フェッチ、プル をカバーします。push には repository:contents:write が必要で、その スコープ が installation で grant されている必要があります。トークンの適用範囲を installation の一部の リポジトリ に絞り込むには、request body に "repositoryIds":[...] を追加してください。

秘密鍵 はファイルディスクリプタ経由で openssl に、bearer header は stdin 経由で curl に渡されるため、どちらもコマンドラインには現れません。コマンドラインに現れると、ランナー 上の他の processes から読み取られる可能性があります。この関数は CURSOR_AUTH_TOKEN を直接 set してエクスポートするため、トークンがファイルに書き出されることはなく、発行 に失敗した場合は set -e により ジョブ が stop します。実行には bash、openssl 1.1.1 以降、curl 7.55 以降、および jq が必要です。

origin_app_token() {  b64url() { openssl base64 -A | tr '+/' '-_' | tr -d '='; }  now=$(date +%s)  header=$(printf '{"alg":"EdDSA","kid":"%s","typ":"JWT"}' "$ORIGIN_APP_ID" | b64url)  claims=$(printf '{"iss":"%s","aud":"origin-apps","iat":%d,"exp":%d}' \    "$ORIGIN_APP_ID" "$now" "$((now + 900))" | b64url)  # openssl -rawin にはシーク可能な入力が必要。署名入力に secret は含まれない。  signing_input=$(mktemp)  trap 'rm -f "$signing_input"' EXIT  printf '%s.%s' "$header" "$claims" > "$signing_input"  signature=$(openssl pkeyutl -sign -rawin -in "$signing_input" \    -inkey <(printf '%s\n' "$ORIGIN_APP_PRIVATE_KEY") | b64url)  app_jwt="$header.$claims.$signature"  CURSOR_AUTH_TOKEN=$(printf 'Authorization: Bearer %s\n' "$app_jwt" \    | curl -fsS -X POST -H @- -H 'Content-Type: application/json' \        --data '{"scopes":["repository:contents:read"]}' \        "https://api.cursor.com/v1/origin/app/installations/${ORIGIN_INSTALLATION_ID}/access_tokens" \    | jq -er '.token')  export CURSOR_AUTH_TOKEN}

空のディレクトリへクローンする直前にこれを呼び出し、続けて git の認証情報ヘルパーを登録します。こうすることで、CURSOR_AUTH_TOKEN がエクスポートされたままの状態で、以降の git コマンドが認証されます。acme/widgets は自分のリポジトリに、COMMIT_SHA は CI システムがビルド用に公開しているコミットに置き換えてください。

set -euo pipefailorigin_app_tokenorigin repo clone-fast acme/widgets . --verifyorigin auth setup-gitgit fetch origin "$COMMIT_SHA"git checkout -q "$COMMIT_SHA"

GitHub Actions

GitHub Actions では Origin App の方式を使い、秘密鍵 を Actions のシークレットに、2 つの ID をリポジトリ変数に格納します。ワークフローを起動するのは GitHub なので、リポジトリは GitHub 上にあり、Origin はそれをミラーとして保持します。ワークフローは Origin にビルド対象のコミットの取得を依頼し、空の $GITHUB_WORKSPACE に clone-fast でクローンしたうえで、そのコミットをチェックアウトします。GitHub を一切呼び出さないため、GITHUB_TOKEN の権限は不要で、actions/checkout も使用しません。

1

シークレットを追加する

リポジトリで Settings > Secrets and variables > Actions を選び、秘密鍵 の PEM 全文を ORIGIN_APP_PRIVATE_KEY というシークレットとして追加します。

2

変数を追加する

同じページで、リポジトリ変数 ORIGIN_APP_ID と ORIGIN_INSTALLATION_ID を追加します。

3

ワークフローを追加する

以下のワークフローを .github/workflows/ci.yml として保存し、ORIGIN_REPO に Origin 上のミラーの {owner}/{repo} を設定して、クローンのステップの後にビルドのステップを追加します。

このワークフローは、CLI をインストールし、トークンを発行し、Origin がコミットをミラーするのを待ってからクローンします:

name: cion:  push:    branches: [main]  pull_request:permissions: {}jobs:  build:    runs-on: ubuntu-latest    defaults:      run:        shell: bash    steps:      - name: Install the Origin CLI        run: |          curl -fsSL https://downloads.cursor.com/origin/install.sh | sh          echo "$HOME/.local/bin" >> "$GITHUB_PATH"      - name: Clone from Origin with clone-fast        env:          ORIGIN_APP_ID: ${{ vars.ORIGIN_APP_ID }}          ORIGIN_INSTALLATION_ID: ${{ vars.ORIGIN_INSTALLATION_ID }}          ORIGIN_APP_PRIVATE_KEY: ${{ secrets.ORIGIN_APP_PRIVATE_KEY }}          ORIGIN_REPO: acme/widgets          BUILD_BRANCH: ${{ github.head_ref || github.ref_name }}          BUILD_SHA: ${{ github.event.pull_request.head.sha || github.sha }}        run: |          set -euo pipefail          origin_app_token() {            b64url() { openssl base64 -A | tr '+/' '-_' | tr -d '='; }            now=$(date +%s)            header=$(printf '{"alg":"EdDSA","kid":"%s","typ":"JWT"}' "$ORIGIN_APP_ID" | b64url)            claims=$(printf '{"iss":"%s","aud":"origin-apps","iat":%d,"exp":%d}' \              "$ORIGIN_APP_ID" "$now" "$((now + 900))" | b64url)            signing_input=$(mktemp)            trap 'rm -f "$signing_input"' EXIT            printf '%s.%s' "$header" "$claims" > "$signing_input"            signature=$(openssl pkeyutl -sign -rawin -in "$signing_input" \              -inkey <(printf '%s\n' "$ORIGIN_APP_PRIVATE_KEY") | b64url)            app_jwt="$header.$claims.$signature"            echo "::add-mask::$app_jwt"            CURSOR_AUTH_TOKEN=$(printf 'Authorization: Bearer %s\n' "$app_jwt" \              | curl -fsS -X POST -H @- -H 'Content-Type: application/json' \                  --data '{"scopes":["repository:contents:read"]}' \                  "https://api.cursor.com/v1/origin/app/installations/${ORIGIN_INSTALLATION_ID}/access_tokens" \              | jq -er '.token')            echo "::add-mask::$CURSOR_AUTH_TOKEN"            export CURSOR_AUTH_TOKEN          }          origin_app_token          # Origin による GitHub のミラーリングには遅延があります。この commit を最大 2 分程度待機します。          body=$(printf '{"ref":"refs/heads/%s","sha":"%s","wait":true}' "$BUILD_BRANCH" "$BUILD_SHA")          printf 'Authorization: Bearer %s\n' "$CURSOR_AUTH_TOKEN" \            | curl -fsS -X POST -H @- -H 'Content-Type: application/json' --data "$body" \                "https://api.cursor.com/v1/origin/repos/${ORIGIN_REPO}:syncMirror" \            | jq -e '.synced' > /dev/null \            || { echo "Origin has not mirrored $BUILD_SHA from $BUILD_BRANCH yet" >&2; exit 1; }          origin repo clone-fast "$ORIGIN_REPO" . --verify          origin auth setup-git          git fetch origin "$BUILD_SHA"          git checkout -q "$BUILD_SHA"
  • pull_request では、workflow はプルリクエストの head を build します。 github.sha は GitHub 上にのみ存在する merge commit のため、BUILD_SHA と BUILD_BRANCH には代わりにプルリクエストの head commit とブランチを使用します。
  • sync リクエストは Sync Mirror です。 installation token を受け入れ、repository:contents:read が必要で、"synced": true とともに 200 を返すか、約 2 分の待機 budget の後に "synced": false とともに 202 を返します。Origin が信頼できる情報源で GitHub がミラーの場合は、sync リクエストを削除してください。commit はすでに Origin 上にあり、また Origin は上流ソースから pull しないリポジトリに対する sync リクエストを拒否します。
  • 両方の credentials はマスクされます。 ::add-mask:: は ジョブ ログ内で app JWT と installation token を隠します。
  • 後続の step では改めて mint します。 Origin の git アクセスが必要な後続の step では、関数を再度定義して呼び出します。token は $GITHUB_ENV や $GITHUB_OUTPUT に一切書き出されません。これらはディスク上のファイルです。
  • フォークからのプルリクエストはミラーリングされません。 その head branch は自分のリポジトリには存在しません。それらは GitHub から build してください。

その他のCIシステム

GitLab CI、Jenkins、CircleCI、セルフホストのワーカー群では、Origin App のパスを直接使用します。credentialsを保存する の説明に従って private key と2つのidを保存し、origin repo clone-fast の直前に ジョブでtokenをmintする の関数を実行したうえで、CIシステムがビルド向けに公開しているcommitをフェッチしてcheck outしてください。

初回実行の確認

最初の ジョブ は --fallback never を付けて実行します。キットが見つからない場合、遅い git clone が黙って実行されるのではなく、終了ステータス 1 で ジョブ が失敗します。キットのパスが成功するまで、このフラグは付けたままにしてください。

実行に成功すると、stderr に clone-kit: manifest=...、アーティファクトごとに 1 行のダウンロード行、clone-kit timings: ブロック、clone-kit: ready DIR (head SHA) が出力され、続いて stdout に mode: clone-kit が出力されて、終了コード 0 で終了します。timings ブロックでは、実行を マニフェスト、download、verify、checkout の各フェーズに分けて表示します。効果を測定するには、その合計時間を、同じ ランナー 上で同じリポジトリを通常の git clone した場合と比較してください。

キットのパスが完了しなかった場合、stderr には機械可読な 1 行 clone-kit-result: status=fallback phase=PHASE または clone-kit-result: status=failed phase=PHASE が出力され、続いて理由が出力されます。デフォルトの --fallback auto では、その後 stdout に mode: git-clone が表示されます。

トラブルシューティング

各項目は、ジョブ のログに出力される行から始まります。

マニフェストの fetch が 404 を返す

clone-kit-result: status=fallback phase=manifest と HTTP 404。そのリポジトリのクローンキットがまだ存在しません。Cherri Code アカウント チームに クローンキット の有効化を依頼してください。メッセージ内の URL に https:// が 2 回含まれている場合は、コマンドが {owner}/{repo} ではなく clone URL を受け取っています。

マニフェストの fetch が 401 を返す

clone-kit manifest fetch failed: HTTP 401。Origin がトークンを拒否しました。期限切れである、そもそも有効ではなかった、またはそのインストールが削除されています。クローンの直前に新しいトークンをmintしてください。デフォルトの --fallback auto では、フォールバックの git clone も同じコードと exit ステータス 128 で失敗するため、ログには両方のエラーが出力されます。

マニフェストの fetch が 403 を返す

clone-kit manifest fetch failed: HTTP 403。インストール、または Buildkite のパイプライントークンがこのリポジトリを対象に含んでいません。app を再インストールするか、対象リポジトリを選択し直してください。401 と同様に、フォールバックの git clone も同じコードと exit ステータス 128 で失敗します。

Git がユーザー名を要求する

fatal: could not read Username for 'https://origin.cursor.com'。CLI が古い、または git を実行する shell で CURSOR_AUTH_TOKEN がエクスポートされていません。origin update を実行するか、変数をエクスポートしてください。

auth フェーズでクローンがフォールバックする

clone-kit-result: status=fallback phase=auth と Not authenticated。origin を実行する process に CURSOR_AUTH_TOKEN がエクスポートされていません。origin コマンドの前に、同じ shell でエクスポートしてください。

mint が 401 Issuer is not authorized を返す

トークン endpoint から 401 {"code":16,"message":"Issuer is not authorized"} が返される場合、iss claim が登録済みの App ID でないか、その app に署名キーが登録されていません。ORIGIN_APP_ID が app と一致しているか、また app に署名キーが登録されているかを確認してください。

origin auth status はトークンが有効と報告するがクローンが失敗する

origin auth status は、CURSOR_AUTH_TOKEN 内の有効期限のclaimから Token: valid または Token: expired を判定します。Origin にトークンを受け入れるかどうかを問い合わせているわけではないため、valid はトークンが失効していないことを示すにすぎません。CLI は、有効期限のclaimの 5 分前からトークンを失効扱いにします。origin コマンドは、失効したトークンの場合はリクエストを送信する前に処理を拒否し、clone-fast は The injected CURSOR_AUTH_TOKEN session has expired とともに clone-kit-result: status=fallback phase=auth をログに記録します。新しいトークンをmintして再試行してください。

キットのパスでも失敗する場合は、clone-kit-result の行を含む ジョブ のログ、リポジトリ、origin --version の出力を Cherri Code アカウントチームに送ってください。