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

# Custom Skills

> Create org-scoped skills with embeddings that work alongside the curated library

Build your own legal AI skills and make them available to your organization's agents. Custom skills are stored with vector embeddings and automatically appear in unified search alongside the 870+ curated skills.

<Info>
  **Requires authentication.** All custom skills endpoints require a Case.dev API key with `skills`
  permission scope.
</Info>

## How It Works

Custom skills live in your organization and are the canonical way to manage private skills. When your agents search for skills via `/skills/resolve`, results from your custom skills are merged with curated skills in a single ranked list. If a custom skill has the same slug as a curated skill, the custom skill takes priority for your organization.

Use the `/skills` API for the full lifecycle:

| Endpoint                   | Purpose                                                    |
| -------------------------- | ---------------------------------------------------------- |
| `POST /skills`             | Create a custom skill, optionally with bundled files       |
| `GET /skills/custom`       | List your organization's custom skills                     |
| `GET /skills/:slug`        | Read a custom or curated skill by slug                     |
| `PUT /skills/:slug`        | Update a custom skill and optionally replace bundled files |
| `DELETE /skills/:slug`     | Delete a custom skill                                      |
| `GET /skills/:slug/export` | Inspect the installable file tree for an agent runtime     |
| `GET /skills/resolve`      | Search custom and curated skills together                  |

Each custom skill includes:

* **Content** in markdown, up to 64KB
* **Vector embedding** (generated automatically) for semantic search
* **Tags** for categorization and search boosting
* **Metadata** for arbitrary key-value data
* **Optional companion files** for Skills.sh-style `SKILL.md` bundles, scripts, templates, and references
* **Version tracking** with automatic increment on updates
* **Soft-delete** so deleted skills can be recreated

## Create a Skill

<CodeGroup>
  ```bash title="cURL" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  curl -X POST https://api.case.dev/skills \
    -H "Authorization: Bearer $CASE_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "Deposition Prep Checklist",
      "summary": "Comprehensive checklist for deposition preparation.",
      "content": "# Deposition Prep Checklist\n\n## Pre-Deposition\n...",
      "tags": ["litigation", "deposition", "checklist"],
      "metadata": { "author": "Jane Smith", "practice_area": "litigation" }
    }'
  ```

  ```typescript title="Typescript" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  import Casedev from 'casedev'

  const client = new Casedev({ apiKey: process.env.CASEDEV_API_KEY })

  const skill = await client.skills.create({
    name: 'Deposition Prep Checklist',
    summary: 'Comprehensive checklist for deposition preparation in federal litigation.',
    content:
      '# Deposition Prep Checklist\n\n## Pre-Deposition\n- Review all relevant documents\n- Prepare witness outline',
    tags: ['litigation', 'deposition', 'checklist'],
    metadata: { author: 'Jane Smith', practice_area: 'litigation' },
  })

  console.log(skill.slug) // "deposition-prep-checklist"
  ```

  ```python title="Python" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  import os
  import casedev

  client = casedev.Casedev(api_key=os.environ['CASEDEV_API_KEY'])

  skill = client.skills.create(
      name='Deposition Prep Checklist',
      summary='Comprehensive checklist for deposition preparation in federal litigation.',
      content='# Deposition Prep Checklist\n\n## Pre-Deposition\n- Review all relevant documents',
      tags=['litigation', 'deposition', 'checklist'],
      metadata={'author': 'Jane Smith', 'practice_area': 'litigation'},
  )

  print(skill.slug)  # "deposition-prep-checklist"
  ```

  ```go title="Go" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  package main

  import (
      "context"
      "fmt"

      "github.com/CaseMark/casedev-go"
  )

  func main() {
      client := casedev.NewClient()

      skill, _ := client.Skills.New(context.TODO(), casedev.SkillNewParams{
          Name:    casedev.F("Deposition Prep Checklist"),
          Summary: casedev.F("Comprehensive checklist for deposition preparation."),
          Content: casedev.F("# Deposition Prep Checklist\n\n## Pre-Deposition\n..."),
          Tags:    casedev.F([]string{"litigation", "deposition", "checklist"}),
      })

      fmt.Println(skill.Slug)
  }
  ```
</CodeGroup>

**Request body:**

| Field      | Type      | Required | Description                                                            |
| ---------- | --------- | -------- | ---------------------------------------------------------------------- |
| `name`     | string    | Yes      | Skill name (max 256 chars)                                             |
| `content`  | string    | Yes      | Full skill content in markdown (max 64KB)                              |
| `slug`     | string    | No       | URL-safe identifier. Auto-generated from name if omitted               |
| `summary`  | string    | No       | Brief description (max 1000 chars)                                     |
| `tags`     | string\[] | No       | Tags for categorization and search boosting                            |
| `metadata` | object    | No       | Arbitrary key-value metadata                                           |
| `files`    | object\[] | No       | Companion files installed under the skill directory in agent sandboxes |

### Bundled Skill Files

Use `files[]` when a skill needs scripts, references, examples, or templates in addition to its root `SKILL.md` instructions. The root `content` becomes `<slug>/SKILL.md`; each companion file is installed at `<slug>/<path>`.

```bash title="cURL" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
curl -X POST https://api.case.dev/skills \
  -H "Authorization: Bearer $CASE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Contract Redline Review",
    "slug": "contract-redline-review",
    "summary": "Review contract redlines with a firm-specific checklist.",
    "content": "# Contract Redline Review\n\nUse the checklist and script before drafting comments.",
    "tags": ["transactional", "contracts"],
    "files": [
      {
        "path": "references/checklist.md",
        "content": "# Checklist\n\n- Confirm governing law\n- Flag assignment restrictions"
      },
      {
        "path": "scripts/clauses.ts",
        "content": "export const riskyClauses = [\"assignment\", \"indemnity\"];",
        "contentType": "text/typescript"
      }
    ]
  }'
```

Bundled paths must be relative, cannot contain `.` or `..` segments, and cannot be `SKILL.md`. Send `files[]` again on `PUT /skills/:slug` to replace the companion tree; omit `files` to leave companion files unchanged.

**Response** (201):

```json theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
{
  "slug": "deposition-prep-checklist",
  "name": "Deposition Prep Checklist",
  "summary": "Comprehensive checklist for deposition preparation.",
  "content": "# Deposition Prep Checklist\n\n...",
  "tags": ["litigation", "deposition", "checklist"],
  "metadata": { "author": "Jane Smith", "practice_area": "litigation" },
  "bundle": null,
  "version": 1,
  "created_at": "2026-03-16T20:09:59.333Z"
}
```

<Info>
  **Slugs** are unique per organization. Reserved slugs (`resolve`, `custom`) cannot be used. If you
  omit `slug`, one is auto-generated from the skill name.
</Info>

## Read a Skill

Retrieve a skill by slug. For authenticated users, custom skills are checked first, then curated skills.

<CodeGroup>
  ```bash title="cURL" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  curl https://api.case.dev/skills/deposition-prep-checklist \
    -H "Authorization: Bearer $CASE_API_KEY"
  ```

  ```typescript title="Typescript" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  const skill = await client.skills.read('deposition-prep-checklist')
  console.log(skill.source) // "custom" or "curated"
  ```

  ```python title="Python" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  skill = client.skills.read('deposition-prep-checklist')
  print(skill.source)  # "custom" or "curated"
  ```

  ```go title="Go" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  skill, _ := client.Skills.Read(context.TODO(), "deposition-prep-checklist")
  fmt.Println(skill.Source)
  ```
</CodeGroup>

The response includes a `source` field indicating whether the skill is `"custom"` (your organization's) or `"curated"` (from the open-source library).

For bundled root skills, `GET /skills/:slug` also includes a `bundle` object:

```json theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
{
  "bundle": {
    "role": "root",
    "files": [
      {
        "slug": "contract-redline-review--file--references-checklist-md-a1b2c3d4e5f6",
        "path": "references/checklist.md",
        "content_type": "text/plain; charset=utf-8"
      }
    ]
  }
}
```

## Export a Skill Tree

Use `GET /skills/:slug/export` to inspect the exact files that will be installed into an agent runtime sandbox. Custom skills in your organization are resolved first; curated skills are used as a fallback.

```bash title="cURL" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
curl "https://api.case.dev/skills/contract-redline-review/export?target=agents" \
  -H "Authorization: Bearer $CASE_API_KEY"
```

Response:

```json theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
{
  "slug": "contract-redline-review",
  "target": "agents",
  "root": "<runtime-skill-directory>/contract-redline-review",
  "source": "custom",
  "files": [
    {
      "path": "contract-redline-review/SKILL.md",
      "content": "# Contract Redline Review\n\n...",
      "content_type": "text/markdown; charset=utf-8",
      "sha256": "d3b07384d113edec49eaa6238ad5ff00",
      "size_bytes": 128
    },
    {
      "path": "contract-redline-review/references/checklist.md",
      "content": "# Checklist\n\n...",
      "content_type": "text/plain; charset=utf-8",
      "sha256": "98f13708210194c475687be6106a3b84",
      "size_bytes": 64
    }
  ]
}
```

Most applications do not need to call export directly. Pass `skillSlugs` when creating an agent runtime and Case.dev installs the right tree for that sandbox.

## Install Skills in Agent Runtimes

When creating an agent runtime through a Case.dev integration that supports skills, pass
`skillSlugs` to install custom or curated skills into the sandbox before the runtime starts.

Case.dev installs the root `SKILL.md` and any companion files into the sandbox's skill directory before the runtime process starts.

Use the same `skillSlugs` field for any Case.dev runtime that supports skill installation. Case.dev selects the correct sandbox paths for that runtime.

## Search Skills

Use `/skills/resolve` to search across both curated and custom skills. Results are ranked by relevance using semantic search, BM25 text matching, and tag boosting.

<CodeGroup>
  ```bash title="cURL" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  curl "https://api.case.dev/skills/resolve?q=deposition+preparation&limit=5" \
    -H "Authorization: Bearer $CASE_API_KEY"
  ```

  ```typescript title="Typescript" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  const results = await client.skills.resolve({
    q: 'deposition preparation',
    limit: 5,
  })

  for (const skill of results.results) {
    console.log(skill.source + ': ' + skill.name + ' (' + skill.score + ')')
  }
  ```

  ```python title="Python" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  results = client.skills.resolve(q='deposition preparation', limit=5)

  for skill in results.results:
      print(f"{skill.source}: {skill.name} ({skill.score})")
  ```

  ```go title="Go" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  results, _ := client.Skills.Resolve(context.TODO(), casedev.SkillResolveParams{
      Q:     casedev.F("deposition preparation"),
      Limit: casedev.Int(5),
  })

  for _, skill := range results.Results {
      fmt.Printf("%s: %s (%f)\n", skill.Source, skill.Name, skill.Score)
  }
  ```
</CodeGroup>

Each result includes:

| Field     | Description               |
| --------- | ------------------------- |
| `slug`    | Skill identifier          |
| `name`    | Skill name                |
| `summary` | Brief description         |
| `tags`    | Practice area tags        |
| `score`   | Relevance score (0-1)     |
| `source`  | `"curated"` or `"custom"` |

<Tip>
  Custom skills with the same slug as a curated skill take priority in your organization's results.
  This lets you override curated skills with org-specific versions.
</Tip>

## List Custom Skills

List all custom skills in your organization, with optional filtering.

<CodeGroup>
  ```bash title="cURL" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  # List all
  curl "https://api.case.dev/skills/custom" \
    -H "Authorization: Bearer $CASE_API_KEY"

  # Filter by tag
  curl "https://api.case.dev/skills/custom?tag=litigation" \
    -H "Authorization: Bearer $CASE_API_KEY"

  # Paginate
  curl "https://api.case.dev/skills/custom?limit=10&cursor=csk_abc123" \
    -H "Authorization: Bearer $CASE_API_KEY"
  ```

  ```typescript title="Typescript" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  // List all
  const list = await client.skills.custom.list()

  // Filter by tag
  const filtered = await client.skills.custom.list({ tag: 'litigation' })

  // Paginate
  const page2 = await client.skills.custom.list({
    limit: 10,
    cursor: list.next_cursor,
  })
  ```

  ```python title="Python" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  # List all
  skills_list = client.skills.custom.list()

  # Filter by tag
  filtered = client.skills.custom.list(tag='litigation')

  # Paginate
  page2 = client.skills.custom.list(limit=10, cursor=skills_list.next_cursor)
  ```

  ```go title="Go" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  // List all
  list, _ := client.Skills.Custom.List(context.TODO(), casedev.SkillCustomListParams{})

  // Filter by tag
  filtered, _ := client.Skills.Custom.List(context.TODO(), casedev.SkillCustomListParams{
      Tag: casedev.String("litigation"),
  })

  // Paginate
  page2, _ := client.Skills.Custom.List(context.TODO(), casedev.SkillCustomListParams{
      Limit:  casedev.Int(10),
      Cursor: list.NextCursor,
  })
  ```
</CodeGroup>

**Query parameters:**

| Parameter | Type    | Description                                  |
| --------- | ------- | -------------------------------------------- |
| `limit`   | integer | Results per page (1-100, default 50)         |
| `cursor`  | string  | Cursor from previous response for pagination |
| `tag`     | string  | Filter by tag                                |

**Response:**

```json theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
{
  "skills": [
    {
      "slug": "deposition-prep-checklist",
      "name": "Deposition Prep Checklist",
      "summary": "...",
      "tags": ["litigation", "deposition"],
      "metadata": {},
      "version": 1,
      "created_at": "2026-03-16T20:09:59.333Z",
      "updated_at": "2026-03-16T20:09:59.333Z"
    }
  ],
  "next_cursor": "csk_abc123",
  "has_more": true
}
```

## Update a Skill

Update one or more fields. The version is automatically incremented. If you change content-related fields (name, summary, or content), the embedding is regenerated.

<CodeGroup>
  ```bash title="cURL" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  curl -X PUT https://api.case.dev/skills/deposition-prep-checklist \
    -H "Authorization: Bearer $CASE_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "Updated Deposition Prep Checklist",
      "tags": ["litigation", "deposition", "checklist", "federal"],
      "content": "# Updated content..."
    }'
  ```

  ```typescript title="Typescript" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  const updated = await client.skills.update('deposition-prep-checklist', {
    name: 'Updated Deposition Prep Checklist',
    tags: ['litigation', 'deposition', 'checklist', 'federal'],
    content: '# Updated content...',
  })

  console.log(updated.version) // 2
  ```

  ```python title="Python" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  updated = client.skills.update(
      'deposition-prep-checklist',
      name='Updated Deposition Prep Checklist',
      tags=['litigation', 'deposition', 'checklist', 'federal'],
      content='# Updated content...',
  )

  print(updated.version)  # 2
  ```

  ```go title="Go" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  updated, _ := client.Skills.Update(context.TODO(), "deposition-prep-checklist", casedev.SkillUpdateParams{
      Name:    casedev.String("Updated Deposition Prep Checklist"),
      Tags:    casedev.F([]string{"litigation", "deposition", "checklist", "federal"}),
      Content: casedev.String("# Updated content..."),
  })

  fmt.Println(updated.Version)
  ```
</CodeGroup>

You can also rename a skill's slug:

```bash title="cURL" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
curl -X PUT https://api.case.dev/skills/deposition-prep-checklist \
  -H "Authorization: Bearer $CASE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "slug": "depo-prep-v2" }'
```

After renaming, the old slug returns 404 and the new slug is active.

## Delete a Skill

Soft-deletes a skill. It will no longer appear in search results or be accessible by slug.

<CodeGroup>
  ```bash title="cURL" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  curl -X DELETE https://api.case.dev/skills/deposition-prep-checklist \
    -H "Authorization: Bearer $CASE_API_KEY"
  ```

  ```typescript title="Typescript" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  await client.skills.delete('deposition-prep-checklist')
  ```

  ```python title="Python" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  client.skills.delete('deposition-prep-checklist')
  ```

  ```go title="Go" theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  client.Skills.Delete(context.TODO(), "deposition-prep-checklist")
  ```
</CodeGroup>

**Response** (200):

```json theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
{
  "slug": "deposition-prep-checklist",
  "deleted": true
}
```

<Info>Deletion frees the slug. You can create a new skill with the same slug after deleting.</Info>

## Permissions

Custom skills require the `skills` permission scope on your API key.

| Endpoint                   | Permission       |
| -------------------------- | ---------------- |
| `GET /skills/resolve`      | `skills` (read)  |
| `GET /skills/:slug`        | `skills` (read)  |
| `GET /skills/custom`       | `skills` (read)  |
| `POST /skills`             | `skills` (write) |
| `PUT /skills/:slug`        | `skills` (write) |
| `DELETE /skills/:slug`     | `skills` (write) |
| `GET /skills/:slug/export` | `skills` (read)  |

Configure permissions when creating API keys in the [Console](https://console.case.dev).

## Limits

| Limit               | Value                  |
| ------------------- | ---------------------- |
| Content size        | 64KB per skill         |
| Companion files     | 100 per skill          |
| Companion file size | 64KB per file          |
| Name length         | 256 characters         |
| Summary length      | 1,000 characters       |
| Tag length          | 100 characters per tag |
| Slug length         | 128 characters         |
| Slugs per org       | Unlimited              |

## What's Next?

<CardGroup cols={2}>
  <Card title="Browse Curated Skills" icon="search" href="https://agentskills.legal/skills">
    Explore 870+ open-source legal skills
  </Card>

  <Card title="API Reference" icon="code" href="/api-reference">
    Full endpoint documentation
  </Card>

  <Card title="Skills Overview" icon="book" href="/skills/index">
    Learn about the curated skills library and MCP setup
  </Card>

  <Card title="Rate Limits" icon="gauge" href="/rate-limits">
    Understand request limits and pricing
  </Card>
</CardGroup>
