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

# Storage SDK

> The simplest way to work with Code Storage. Generate authenticated URLs, create commits without git, stream file contents, and manage repositories—all from your application code.

> [!WARNING]
>
> This page documents the earlier Code Storage SDKs: `@pierre/storage`, `pierre-storage`, and
> `code-storage-go`. New code uses the [Pierre SDK](https://code.storage/docs/sdks.md). To move code to the new SDK, use the
> [`pierre-migrate`
> skill](https://github.com/pierrecomputer/skills/tree/main/skills/pierre-migrate).

## Installation & Setup

```bash TypeScript theme={null} theme={"theme":{"light":"github-light","dark":"min-dark"}}
pnpm i @pierre/storage
```

```bash Python theme={null} theme={"theme":{"light":"github-light","dark":"min-dark"}}
# Using uv (recommended)
uv add pierre-storage

# Or using pip
pip install pierre-storage
```

```bash Go theme={null} theme={"theme":{"light":"github-light","dark":"min-dark"}}
go get github.com/pierrecomputer/sdk/packages/code-storage-go@latest
```

Set `PIERRE_ORG` and `PIERRE_PRIVATE_KEY` as shown in the
[Quick Start](https://code.storage/docs/getting-started/quick-start.md#1-sign-up-and-create-a-private-key). Pass them to the
client:

```typescript TypeScript theme={null} theme={"theme":{"light":"github-light","dark":"min-dark"}}
import { GitStorage } from '@pierre/storage';

const store = new GitStorage({
  name: process.env.PIERRE_ORG!,
  key: process.env.PIERRE_PRIVATE_KEY!,
});
```

```python Python theme={null} theme={"theme":{"light":"github-light","dark":"min-dark"}}
import os

from pierre_storage import GitStorage

storage = GitStorage({
    "name": os.environ["PIERRE_ORG"],
    "key": os.environ["PIERRE_PRIVATE_KEY"],
})
```

```go Go theme={null} theme={"theme":{"light":"github-light","dark":"min-dark"}}
// Initialize the client
client, err := storage.NewClient(storage.Options{
  Name: os.Getenv("PIERRE_ORG"),
  Key:  os.Getenv("PIERRE_PRIVATE_KEY"),
})
```

Await `store.createRepo()` or `store.findOne()` to get a `repo` object. `store.findOne()` returns
`null` if the repository does not exist.

In Go, import `os` to read the environment variables. SDK calls take a `context.Context`, and TTL
values are `time.Duration` (for example `time.Hour`).

> Need to create a JWT without an SDK client? See
> [Authentication → How to sign a JWT](https://code.storage/docs/platform/authentication.md#how-to-sign-a-jwt).

## Token signing

The Python package exports `generate_jwt` for code that needs a token without a `GitStorage` client.
The helper selects ES256 or RS256 from the key type.

```python Python theme={null} theme={"theme":{"light":"github-light","dark":"min-dark"}}
import os

from pierre_storage import generate_jwt

private_key = os.environ["PIERRE_PRIVATE_KEY"]
org = os.environ["PIERRE_ORG"]

token = generate_jwt(
    key_pem=private_key,  # Required. This key signs the JWT.
    issuer=org,  # Required. This parameter maps to iss.
    repo_id="team/project-alpha",  # Required. This parameter maps to repo.
    scopes=["git:read", "git:write"],  # Optional. This list maps to scopes and is the default.
    ttl=3600,  # Optional. This value sets exp from iat. The default is 31536000 seconds.
)

git_url = f"https://t:{token}@{org}.code.storage/team/project-alpha.git"
print(f"git clone {git_url}")
```

See [Storage Access & Permissions](https://code.storage/docs/repos/access.md) for repository claims and scopes.

## Error Handling

The SDK surfaces API failures as `ApiError` and ref update failures as `RefUpdateError`.

```typescript TypeScript theme={null} theme={"theme":{"light":"github-light","dark":"min-dark"}}
import { ApiError, RefUpdateError, GitStorage } from '@pierre/storage';

const store = new GitStorage({
  name: process.env.PIERRE_ORG!,
  key: process.env.PIERRE_PRIVATE_KEY!,
});

try {
  const repo = await store.createRepo({ id: 'existing' });
  console.log(repo.id);
} catch (err) {
  if (err instanceof ApiError) {
    console.error('API error:', err.message);
    console.error('Status code:', err.statusCode);
  } else {
    throw err;
  }
}

const repo = await store.findOne({ id: 'repo-id' });
const builder = repo?.createCommit({
  targetBranch: 'main',
  commitMessage: 'Update docs',
  author: { name: 'Docs Bot', email: 'docs@example.com' },
});

try {
  const result = await builder
    ?.addFileFromString('docs/changelog.md', '# v2.0.1\n- add streaming SDK\n')
    .send();
  console.log(result?.commitSha);
} catch (err) {
  if (err instanceof RefUpdateError) {
    console.error('Ref update failed:', err.message);
    console.error('Status:', err.status);
    console.error('Reason:', err.reason);
    console.error('Ref update:', err.refUpdate);
  } else {
    throw err;
  }
}
```

```python Python theme={null} theme={"theme":{"light":"github-light","dark":"min-dark"}}
from pierre_storage import ApiError, RefUpdateError

try:
    repo = await storage.create_repo(id="existing")
except ApiError as e:
    print(f"API error: {e.message}")
    print(f"Status code: {e.status_code}")

try:
    result = await builder.send()
except RefUpdateError as e:
    print(f"Ref update failed: {e.message}")
    print(f"Status: {e.status}")
    print(f"Reason: {e.reason}")
    print(f"Ref update: {e.ref_update}")
```

```go Go theme={null} theme={"theme":{"light":"github-light","dark":"min-dark"}}
// Initialize the client
client, err := storage.NewClient(storage.Options{
  Name: os.Getenv("PIERRE_ORG"),
  Key:  os.Getenv("PIERRE_PRIVATE_KEY"),
})

// Create a repository and handle API errors
_, err = client.CreateRepo(context.Background(), storage.CreateRepoOptions{ID: "existing"})
if err != nil {
  var apiErr *storage.APIError
  if errors.As(err, &apiErr) {
    fmt.Printf("API error: %s (status=%d)\n", apiErr.Message, apiErr.Status)
  } else {
    fmt.Printf("Unexpected error: %v\n", err)
  }
}

// Build a commit and handle ref update errors
repo, err := client.FindOne(context.Background(), storage.FindOneOptions{ID: "repo-id"})
builder, err := repo.CreateCommit(storage.CommitOptions{
  TargetBranch:  "main",
  CommitMessage: "Update docs",
  Author:        storage.CommitSignature{Name: "Docs Bot", Email: "docs@example.com"},
})

_, err = builder.AddFileFromString("docs/changelog.md", "# v2.0.1\n- add streaming SDK\n", nil).
  Send(context.Background())
if err != nil {
  var refErr *storage.RefUpdateError
  if errors.As(err, &refErr) {
    fmt.Printf("Ref update failed: %s (status=%s, reason=%s)\n", refErr.Message, refErr.Status, refErr.Reason)
  } else {
    fmt.Printf("Unexpected error: %v\n", err)
  }
}
```

## Methods

Each method of the earlier SDK has its own page.

### Client methods

* [`store.createGitCredential()`](https://code.storage/docs/sdk/repos/git-credential-create)
* [`store.createRepo()`](https://code.storage/docs/sdk/repos/repo-create)
* [`store.deleteGitCredential()`](https://code.storage/docs/sdk/repos/git-credential-delete)
* [`store.deleteRepo()`](https://code.storage/docs/sdk/repos/repo-delete)
* [`store.findOne()`](https://code.storage/docs/sdk/repos/repo-get)
* [`store.listRepos()`](https://code.storage/docs/sdk/repos/repos-list)
* [`store.updateGitCredential()`](https://code.storage/docs/sdk/repos/git-credential-update)

### Repository methods

* [`repo.appendNote()`](https://code.storage/docs/sdk/repos/note-append)
* [`repo.createBranch()`](https://code.storage/docs/sdk/repos/branch-create)
* [`repo.createCommit()`](https://code.storage/docs/sdk/repos/commit-pack)
* [`repo.createCommitFromDiff()`](https://code.storage/docs/sdk/repos/commit-create-from-diff)
* [`repo.createNote()`](https://code.storage/docs/sdk/repos/note-create)
* [`repo.createTag()`](https://code.storage/docs/sdk/repos/tag-create)
* [`repo.deleteBranch()`](https://code.storage/docs/sdk/repos/branch-delete)
* [`repo.deleteNote()`](https://code.storage/docs/sdk/repos/note-delete)
* [`repo.deleteTag()`](https://code.storage/docs/sdk/repos/tag-delete)
* [`repo.getArchiveStream()`](https://code.storage/docs/sdk/repos/archive)
* [`repo.getBlame()`](https://code.storage/docs/sdk/repos/blame)
* [`repo.getBranchDiff()`](https://code.storage/docs/sdk/repos/branches-diff)
* [`repo.getCommit()`](https://code.storage/docs/sdk/repos/commit-get)
* [`repo.getCommitDiff()`](https://code.storage/docs/sdk/repos/diff-get)
* [`repo.getEphemeralRemoteURL()`](https://code.storage/docs/sdk/repos/ephemeral-remote-url-get)
* [`repo.getFileStream()`](https://code.storage/docs/sdk/repos/file-get)
* [`repo.getImportRemoteURL()`](https://code.storage/docs/sdk/repos/import-remote-url-get)
* [`repo.getNote()`](https://code.storage/docs/sdk/repos/note-get)
* [`repo.getRemoteURL()`](https://code.storage/docs/sdk/repos/remote-url-get)
* [`repo.grep()`](https://code.storage/docs/sdk/repos/grep)
* [`repo.headFile()`](https://code.storage/docs/sdk/repos/file-head)
* [`repo.listBranches()`](https://code.storage/docs/sdk/repos/branches-list)
* [`repo.listCommits()`](https://code.storage/docs/sdk/repos/commits-list)
* [`repo.listFiles()`](https://code.storage/docs/sdk/repos/files-list)
* [`repo.listFilesWithMetadata()`](https://code.storage/docs/sdk/repos/files-metadata-list)
* [`repo.listTags()`](https://code.storage/docs/sdk/repos/tags-list)
* [`repo.merge()`](https://code.storage/docs/sdk/repos/merge)
* [`repo.previewMerge()`](https://code.storage/docs/sdk/repos/merge-preview)
* [`repo.pullUpstream()`](https://code.storage/docs/sdk/repos/upstream-pull)
* [`repo.restoreCommit()`](https://code.storage/docs/sdk/repos/commit-restore)


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