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

# SDK API Reference

> All GitMorph SDK methods and types

Complete reference for the `@morphllm/morph-git-sdk` TypeScript SDK.

## GitMorph (Client)

The main client. Handles authentication and provides access to repositories.

```typescript theme={null}
import { GitMorph } from "@morphllm/morph-git-sdk";

const gm = new GitMorph({ token: "your-token" });
```

### Constructor Options

| Option  | Type     | Description                                                              |
| ------- | -------- | ------------------------------------------------------------------------ |
| `token` | `string` | API token. Falls back to `GM_TOKEN` env, then `~/.config/gm/config.json` |
| `host`  | `string` | Server hostname. Falls back to `GM_HOST` env, then `gitmorph.com`        |

### `repo(slug)`

Returns a `GitMorphRepo` handle for the given repository.

```typescript theme={null}
const repo = gm.repo("owner/repo-name");
```

### `getRepositoryInfo(slug)`

Fetch metadata for a repository.

```typescript theme={null}
const info = await gm.getRepositoryInfo("owner/repo-name");
console.log(info.default_branch, info.stars_count, info.language);
```

Returns a [`Repository`](#repository) object.

### `mirror(source, options?)`

Mirror a repository from GitHub, GitLab, or another Gitea instance.

```typescript theme={null}
const { repository, repo } = await gm.mirror(
  "https://github.com/org/project",
  {
    source: "github",
    private: true,
    issues: true,
    pullRequests: true,
    releases: true,
    labels: true,
    milestones: true,
    lfs: true,
    wiki: true,
    repoName: "custom-name",  // optional override
  }
);
```

**MirrorOptions:**

| Option         | Type                              | Default       | Description                        |
| -------------- | --------------------------------- | ------------- | ---------------------------------- |
| `source`       | `"github" \| "gitlab" \| "gitea"` | auto-detect   | Source platform                    |
| `repoName`     | `string`                          | original name | Override the destination repo name |
| `private`      | `boolean`                         | `false`       | Make the mirrored repo private     |
| `wiki`         | `boolean`                         | `false`       | Mirror wiki                        |
| `issues`       | `boolean`                         | `false`       | Mirror issues                      |
| `pullRequests` | `boolean`                         | `false`       | Mirror pull requests               |
| `releases`     | `boolean`                         | `false`       | Mirror releases                    |
| `labels`       | `boolean`                         | `false`       | Mirror labels                      |
| `milestones`   | `boolean`                         | `false`       | Mirror milestones                  |
| `lfs`          | `boolean`                         | `false`       | Mirror LFS objects                 |

Returns `{ repository: Repository, repo: GitMorphRepo }`.

### `grepAll(options)`

Search code across all accessible repositories.

```typescript theme={null}
const results = await gm.grepAll({
  pattern: "handleAuth",
  language: "typescript",
  limit: 20,
  page: 1,
  sortByStars: true,
});
```

**GrepAllOptions:**

| Option        | Type      | Description                     |
| ------------- | --------- | ------------------------------- |
| `pattern`     | `string`  | Search pattern (required)       |
| `language`    | `string`  | Filter by programming language  |
| `page`        | `number`  | Page number for pagination      |
| `limit`       | `number`  | Max results per page (max 50)   |
| `sortByStars` | `boolean` | Sort repositories by star count |

Returns `{ matches: GrepAllMatch[], total: number }`.

***

## GitMorphRepo

Per-repository operations. Obtained via `gm.repo("owner/name")`.

### `readFile(path, options?)`

Read a file from the repository. Optionally read only specific line ranges.

```typescript theme={null}
// Full file
const file = await repo.readFile("src/index.ts");
console.log(file.content);
console.log(`Total lines: ${file.totalLines}`);

// Specific lines (1-indexed, inclusive)
const snippet = await repo.readFile("src/auth.ts", {
  ref: "main",
  lines: [
    { start: 1, end: 10 },
    { start: 50, end: 60 },
  ],
});
```

**ReadFileOptions:**

| Option  | Type          | Description                                                       |
| ------- | ------------- | ----------------------------------------------------------------- |
| `ref`   | `string`      | Branch, tag, or commit SHA. Defaults to the repo's default branch |
| `lines` | `LineRange[]` | Array of `{ start, end }` ranges (1-indexed, inclusive)           |

Returns `{ path, content, totalLines, lines? }`.

### `grep(options)`

Search code within the repository using server-side search.

```typescript theme={null}
const results = await repo.grep({
  pattern: "TODO|FIXME",
  language: "typescript",
  caseSensitive: false,
  maxMatches: 25,
});

for (const match of results.matches) {
  console.log(`${match.path}:${match.lineNumber}`);
  console.log(`  ${match.lineContent}`);
  for (const sub of match.submatches) {
    console.log(`  match: "${sub.match}" at ${sub.startOffset}-${sub.endOffset}`);
  }
}
```

**GrepOptions:**

| Option          | Type      | Description                               |
| --------------- | --------- | ----------------------------------------- |
| `pattern`       | `string`  | Search pattern (required)                 |
| `language`      | `string`  | Filter by programming language            |
| `caseSensitive` | `boolean` | Case-sensitive matching (default `false`) |
| `maxMatches`    | `number`  | Max results (max 50)                      |
| `page`          | `number`  | Page number for pagination                |

Returns `{ matches: GrepMatch[], total: number }`.

Each `GrepMatch` contains:

* `path` - file path
* `lineNumber` - line number
* `lineContent` - the matching line (plain text)
* `submatches` - array of `{ match, startOffset, endOffset }` within the line

### `getFileContents(paths, options?)`

Batch-read multiple files in a single request.

```typescript theme={null}
const files = await repo.getFileContents(
  ["README.md", "package.json", "src/index.ts"],
  { ref: "main" }
);

for (const file of files) {
  if (file) {
    console.log(`${file.path} (${file.size} bytes)`);
    console.log(file.content);
  }
}
```

Returns an array of `FileContentEntry | null` (null for files that don't exist). Content is automatically decoded from base64.

### `glob(options)`

Find files matching glob patterns.

```typescript theme={null}
const result = await repo.glob({
  patterns: ["**/*.ts", "**/*.tsx"],
  prefix: "src/",
  ref: "main",
  sizes: true,
  limit: 500,
});

for (const entry of result.entries) {
  console.log(`${entry.path} (${entry.size} bytes)`);
}
```

**GlobOptions:**

| Option     | Type       | Description                                                           |
| ---------- | ---------- | --------------------------------------------------------------------- |
| `patterns` | `string[]` | Doublestar glob patterns (required)                                   |
| `ref`      | `string`   | Branch, tag, or commit SHA                                            |
| `prefix`   | `string`   | Directory prefix to narrow the search                                 |
| `sizes`    | `boolean`  | Include file sizes (default `true`). Set `false` for faster responses |
| `limit`    | `number`   | Max results (default 1000)                                            |

Returns `{ entries: TreeEntry[], truncated: boolean }`.

### `listDir(options?)`

List directory contents.

```typescript theme={null}
// Top-level files
const root = await repo.listDir();

// Specific directory, recursive
const src = await repo.listDir({
  path: "src/",
  ref: "main",
  recursive: true,
});

for (const entry of src.entries) {
  console.log(`${entry.type === "dir" ? "d" : "f"} ${entry.path}`);
}
```

**ListDirOptions:**

| Option      | Type      | Description                        |
| ----------- | --------- | ---------------------------------- |
| `path`      | `string`  | Directory path                     |
| `ref`       | `string`  | Branch, tag, or commit SHA         |
| `recursive` | `boolean` | Include subdirectories recursively |

Returns `{ entries: ListDirEntry[], truncated: boolean }`.

### `listBranches(options?)`

List repository branches.

```typescript theme={null}
const branches = await repo.listBranches({ limit: 50 });

for (const branch of branches) {
  console.log(`${branch.name} ${branch.protected ? "(protected)" : ""}`);
  console.log(`  latest: ${branch.commit.message}`);
}
```

Returns `Branch[]` with `name`, `commit`, and `protected` fields.

### `listCommits(options?)`

List commits with optional filters.

```typescript theme={null}
const commits = await repo.listCommits({
  sha: "main",
  path: "src/",
  since: "2025-01-01T00:00:00Z",
  limit: 20,
});

for (const commit of commits) {
  console.log(`${commit.sha.slice(0, 7)} ${commit.message}`);
  console.log(`  by ${commit.author.name} on ${commit.author.date}`);
}
```

**ListCommitsOptions:**

| Option  | Type     | Description                                |
| ------- | -------- | ------------------------------------------ |
| `sha`   | `string` | Branch name or SHA to list from            |
| `path`  | `string` | Only commits affecting this file/directory |
| `since` | `string` | ISO 8601 date, commits after this date     |
| `until` | `string` | ISO 8601 date, commits before this date    |
| `page`  | `number` | Page number                                |
| `limit` | `number` | Results per page                           |

***

## Error Handling

The SDK throws typed errors for different failure modes:

```typescript theme={null}
import {
  GitMorphError,
  AuthenticationError,
  ApiError,
  MirrorError,
  GrepError,
} from "@morphllm/morph-git-sdk";

try {
  await repo.readFile("nonexistent.ts");
} catch (err) {
  if (err instanceof ApiError) {
    console.log(`API error ${err.status}: ${err.message}`);
    console.log(`URL: ${err.url}`);
  } else if (err instanceof AuthenticationError) {
    console.log("Not authenticated. Run: gm auth login");
  }
}
```

| Error Class           | When                                                             |
| --------------------- | ---------------------------------------------------------------- |
| `AuthenticationError` | No token found in constructor, env, or config                    |
| `ApiError`            | Server returned a non-2xx response (includes `status` and `url`) |
| `MirrorError`         | Mirror operation failed                                          |
| `GrepError`           | Code search failed or invalid pattern                            |
| `GitMorphError`       | Base class for all SDK errors                                    |

***

## Types

### Repository

```typescript theme={null}
interface Repository {
  id: number;
  name: string;
  full_name: string;
  description: string;
  private: boolean;
  fork: boolean;
  mirror: boolean;
  archived: boolean;
  size: number;
  stars_count: number;
  forks_count: number;
  open_issues_count: number;
  default_branch: string;
  language: string;
  html_url: string;
  ssh_url: string;
  clone_url: string;
  owner: User;
  created_at: string;
  updated_at: string;
}
```

### User

```typescript theme={null}
interface User {
  id: number;
  login: string;
  full_name: string;
  email: string;
  avatar_url: string;
  is_admin: boolean;
}
```

***

## CLI Reference

The `gm` CLI covers repositories, issues, PRs, releases, workflows, secrets, and more. It follows the same patterns as GitHub's `gh` CLI.

### Repositories

```bash theme={null}
gm repo list                              # list your repos
gm repo view [OWNER/REPO]                 # view repo details
gm repo create my-project [--private]     # create repo
gm repo clone OWNER/REPO                  # clone repo
gm repo fork OWNER/REPO                   # fork repo
gm repo edit -R OWNER/REPO -d "new desc"  # edit metadata
gm repo delete OWNER/REPO --yes           # delete repo
gm repo deploy-key list -R OWNER/REPO     # manage deploy keys
```

### Issues

```bash theme={null}
gm issue list [-s closed] [-l bug]         # list issues
gm issue view 42 [-c]                      # view issue (with comments)
gm issue create -t "Title" -b "Body"       # create issue
gm issue close 42 -c "Fixed"              # close with comment
gm issue edit 42 --add-label bug           # edit issue
```

### Pull Requests

```bash theme={null}
gm pr list [-s closed] [-B main]           # list PRs
gm pr view 10 [-c]                         # view PR
gm pr create -t "Title" -B main [-d]       # create PR (draft with -d)
gm pr merge 10 -s                          # squash merge
gm pr checkout 10                          # checkout locally
gm pr diff 10                              # view diff
gm pr review 10 --approve -b "LGTM"        # approve
```

### Code Search

```bash theme={null}
gm search code OWNER/REPO "query"          # search a repo
gm search code "query"                     # interactive repo picker
gm search code OWNER/REPO "q" -b develop   # search specific branch
```

### Workflows & Runs

```bash theme={null}
gm workflow list                           # list workflows
gm workflow run 3 [-r develop]             # trigger workflow
gm run list [-w 3]                         # list runs
gm run view 100 --log                      # view logs
gm run watch 100                           # watch until done
```

### Releases

```bash theme={null}
gm release list                            # list releases
gm release create v1.0.0 -t "v1.0.0"      # create release
gm release create v1.0.0 binary.tar.gz     # create with asset
gm release download v1.0.0 -D ./out        # download assets
```

### Secrets & Variables

```bash theme={null}
gm secret list                             # list secrets
gm secret set MY_SECRET -b "value"         # set secret
gm variable list                           # list variables
gm variable set MY_VAR -b "value"          # set variable
```

### Raw API

```bash theme={null}
gm api /repos/OWNER/REPO                   # GET
gm api /repos/OWNER/REPO/issues -X POST -f title="Bug"  # POST
gm api /repos/OWNER/REPO --jq ".full_name" # filter response
```

### Configuration

Config is stored at `~/.config/gm/config.json` (or `$GM_CONFIG_DIR/config.json`).

```bash theme={null}
gm config list
gm config get host
gm config set host gitmorph.com
```
