Skip to main content

code-storage

Agent skill for interacting with code.storage, a managed Git infrastructure layer. Provides repository creation, branching, commits, file access, diffs, search, notes, GitHub sync, ephemeral branches, and forking through a RESTful HTTP API authenticated with customer-signed JWTs. Every repo operation scoped per-JWT.

소스 정보

저장소
pierrecomputer/sdk
최근 소스 활동
2026년 9월 17일 19:23
감지된 SKILL.md 언어
영어
스타
38
포크
7

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
code-storage
description
Agent skill for interacting with code.storage, a managed Git infrastructure layer. Provides repository creation, branching, commits, file access, diffs, search, notes, GitHub sync, ephemeral branches, and forking through a RESTful HTTP API authenticated with customer-signed JWTs. Every repo operation scoped per-JWT.
MCP server: https://code.storage/docs/mcp Docs index: https://code.storage/docs/llms.txt Official SDKs (in this repository): - TypeScript / JavaScript: `@pierre/storage` (npm) - Python: `pierre-storage` (PyPI; import `pierre_storage`) - Go: `github.com/pierrecomputer/sdk/packages/code-storage-go` ## TypeScript custom HTTP transport `new GitStorage({ name, key, fetch })` (also `CodeStorage` and `createClient`) accepts an optional `fetch: typeof globalThis.fetch`. It applies to all SDK HTTP calls, including repository handles, downloads, and streaming commit uploads. The default is global fetch; the SDK adds no automatic retries. Callers own retry limits, backoff, cancellation, and safe body replay. Do not blindly retry writes or reuse consumed streaming request bodies. This option does not affect Git CLI traffic. See `packages/code-storage-typescript/README.md` for a read-only retry example. Python and Go do not use this TypeScript option. # ENVIRONMENT SETUP ## Required Environment Variables | Variable | Description | Example | |-------------------------|----------------------------------------------------------------|--------------------------------------------------| | `ORG_NAME` | Your organization identifier (subdomain slug) | `acme` | | `PIERRE_PRIVATE_KEY` | PEM-encoded EC (ES256) or RSA (RS256) private key | `-----BEGIN PRIVATE KEY-----\n...` | | `CODE_STORAGE_BASE_URL` | Derived base URL for HTTP API | `https://api.acme.code.storage/api/v1` | | `CODE_STORAGE_TOKEN` | JWT minted for current operation (per-repo or org-wide) | `eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9...` | Export for curl sessions: ```bash export ORG_NAME="your-org" export CODE_STORAGE_BASE_URL="https://api.${ORG_NAME}.code.storage/api/v1" export CODE_STORAGE_TOKEN="YOUR_JWT_TOKEN" ``` ## JWT Token Structure Every request requires a JWT signed with your private key. Tokens are per-repository (except `org:read` which is org-wide). ```json { "iss": "your-org", // Organization identifier "sub": "@pierre/storage", // Subject (the SDKs set this to the package name) "repo": "team/project", // Repository the token grants access to "scopes": ["git:read", "git:write"], "refs": [ // Optional per-ref policy rules (first match wins) ["refs/heads/main", ["no-push"]], ["refs/heads/feature/*", ["no-force-push"]] ], "iat": 1723453189, "exp": 1723456789 } ``` JWT header: `{ "alg": "ES256", "typ": "JWT" }` (RS256 and EdDSA also supported) ### Policy Operations | Op string | SDK constant | Effect | |------------------|------------------------------------------------------------------------------|-------------------------------------------------------| | `no-force-push` | TS `OP_NO_FORCE_PUSH` / Py `OP_NO_FORCE_PUSH` / Go `storage.OpNoForcePush` | Rejects force pushes / non-fast-forward ref updates. | | `no-push` | TS `OP_NO_PUSH` / Py `OP_NO_PUSH` / Go `storage.OpNoPush` | Rejects any push to matching refs. | | `verify-sig` | TS `OP_VERIFY_SIG` / Py `OP_VERIFY_SIG` / Go `storage.OpVerifySig` | Rejects pushes introducing commits without a valid signature from a registered signing key. | #### Per-ref policies (preferred, use this for new code) The `refs` claim is an **ordered** array of `[pattern, [ops...]]` tuples. Rules are evaluated in declaration order. The first pattern that matches the ref wins. Patterns may be fully-qualified refs (`refs/heads/main`), prefix globs (`refs/heads/feature/*`, `refs/tags/*`), or `*` for every ref. Short branch names like `main` are normalized to `refs/heads/main` on verify. The policies are accepted by every URL-minting method and every ref-mutating REST method via the SDK option `refPolicies` (TS), `ref_policies` (Py), `RefPolicies` (Go). #### Repo-wide `ops` (legacy, do not use in new code) The optional top-level `ops` claim applies to every ref. On verify it is folded into the catch-all `*` rule. It is merged into an existing `*` entry in the ref policies when one is present, or appended as a new trailing `*` rule otherwise. Only available on the URL-minting methods (`getRemoteURL` / `getEphemeralRemoteURL` / `getImportRemoteURL`). Use `refPolicies: [{ pattern: '*', ops: [...] }]` instead. ```typescript await repo.getRemoteURL({ refPolicies: [ { pattern: 'refs/heads/main', ops: [OP_NO_PUSH] }, { pattern: '*', ops: [OP_NO_FORCE_PUSH] }, ], }); ``` ```python await repo.get_remote_url( ref_policies=[ {"pattern": "refs/heads/main", "ops": [OP_NO_PUSH]}, {"pattern": "*", "ops": [OP_NO_FORCE_PUSH]}, ], ) ``` ```go repo.RemoteURL(ctx, storage.RemoteURLOptions{ RefPolicies: storage.RefPolicyList{ {Pattern: "refs/heads/main", Ops: storage.Ops{storage.OpNoPush}}, {Pattern: "*", Ops: storage.Ops{storage.OpNoForcePush}}, }, }) ``` ### Permission Scopes | Scope | Grants | Required By | |--------------|---------------------------------|------------------------------------------------| | `git:read` | clone, fetch, pull, read API | GET file/branch/commit/diff/grep endpoints | | `git:write` | push, write API (includes read) | POST/DELETE commit/branch/note endpoints | | `repo:write` | create/delete repositories | POST /repos, DELETE /repos/delete | | `org:read` | list all repos in org | GET /repos (list) | ### Git Remote URL Format ``` https://t:{JWT}@{ORG_NAME}.code.storage/{REPO_ID}.git ``` Username is always `t`. Password is the JWT. # QUICK-REFERENCE ENDPOINT TABLE | Goal | Method | Endpoint | Scope Required | |-------------------------------|----------|-----------------------------------|-----------------| | **REPOSITORIES** | | | | | Create repository | POST | `/repos` | `repo:write` | | List all repositories | GET | `/repos` | `org:read` | | Get repository metadata | GET | `/repo` | (repo in JWT) | | Delete repository | DELETE | `/repos/delete` | `repo:write` | | **BRANCHES** | | | | | Create branch | POST | `/repos/branches/create` | `git:write` | | List branches | GET | `/repos/branches` | `git:read` | | Get branch diff | GET | `/repos/branches/diff` | `git:read` | | Preview merge | GET | `/repos/merge/preview` | `git:read` | | Merge branches | POST | `/repos/merge` | `git:write` | | Delete branch | DELETE | `/repos/branches` | `git:write` | | **COMMITS** | | | | | Create commit (file blobs) | POST | `/repos/commit-pack` | `git:write` | | Create commit from diff/patch | POST | `/repos/diff-commit` | `git:write` | | List commits | GET | `/repos/commits` | `git:read` | | Get commit | GET | `/repos/commit` | `git:read` | | Get commit diff | GET | `/repos/diff` | `git:read` | | Restore branch to commit | POST | `/repos/restore-commit` | `git:write` | | **FILES** | | | | | List files at ref | GET | `/repos/files` | `git:read` | | List files with metadata | GET | `/repos/files/metadata` | `git:read` | | Get file content (stream) | GET/HEAD | `/repos/file` | `git:read` | | Blame file at ref | GET | `/repos/blame` | `git:read` | | Search content (grep) | POST | `/repos/grep` | `git:read` | | Download archive (tar.gz) | POST | `/repos/archive` | `git:read` | | **TAGS** | | | | | Create tag | POST | `/repos/tags` | `git:write` | | List tags | GET | `/repos/tags` | `git:read` | | Delete tag | DELETE | `/repos/tags` | `git:read`+`git:write` | | **NOTES** | | | | | Create note on commit | POST | `/repos/notes` (action:"add") | `git:write` | | Append to note | POST | `/repos/notes` (action:"append") | `git:write` | | Get note for commit | GET | `/repos/notes?sha=SHA` | `git:read` | | Delete note | DELETE | `/repos/notes` | `git:write` | | List notes refs | GET | `/repos/notes/refs` | `git:read` | | **GIT SYNC** | | | | | Pull from upstream | POST | `/repos/pull-upstream` | `git:write` | | Detach upstream | DELETE | `/repos/base` | `git:write` | | **GENERIC GIT SYNC** | | | | | Create Git credential | POST | `/repos/git-credentials` | `repo:write` | | Update Git credential | PUT | `/repos/git-credentials` | `repo:write` | | Delete Git credential | DELETE | `/repos/git-credentials` | `repo:write` | All endpoints: `BASE_URL = https://api.{org}.code.storage/api/v1`
GitHub에서 보기
이 SKILL.md는 매우 커서 SkillsMP가 여기에는 첫 섹션만 미리 보여줍니다. GitHub에서 보기