> ## 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.

# 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.

## Installation & Setup

<CodeGroup>
  ```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
  ```
</CodeGroup>

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

<CodeGroup>
  ```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"),
  })
  ```
</CodeGroup>

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](/docs/platform/authentication#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](/docs/repos/access) for repository claims and scopes.

## Error Handling

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

<CodeGroup>
  ```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)
    }
  }
  ```
</CodeGroup>
