---
title: "Spec patches"
description: "Fix a spec you cannot edit upstream. Patches apply before every generation, and a patch that stops matching is reported, never silently dropped."
url: https://typeship.dev/docs/projects/spec-patches
markdown: https://typeship.dev/docs/projects/spec-patches.md
section: "Get started"
---
> ## Documentation index
> Fetch the complete documentation index at https://typeship.dev/llms.txt (every page, one line each) or the full text at https://typeship.dev/llms-full.txt.
> Append .md to any docs URL, or send Accept: text/markdown, for the markdown twin of that page.

# Spec patches

Fix a spec you cannot edit upstream. Patches apply before every generation, and a patch that stops matching is reported, never silently dropped.

Some specs have a wrong type, a name that reads badly in code, or a field that should not be there, and the fix upstream is weeks away. Spec patches let a project carry small fixes that apply to the spec before every generation. The source stays untouched. The generated packages get the corrected document.

## Shape

> **For AI agents:** `typeship projects update <project_id> --spec-patches '[{"op":"set","path":"/paths/~1accounts/get/operationId","value":"listAccounts","reason":"stable name"}]'`
> 
>  replaces the whole list; read the current one first with 
> 
> `typeship projects get <project_id>`
> 
> . Then 
> 
> `typeship projects generate <project_id>`
> 
>  and diff the warnings.

A patch is a JSON object with an operation and a JSON Pointer path. Add them under **spec patches** in project settings, or through `spec_patches` on the [typeship API](https://typeship.dev/docs/typeship-api/api). Up to 50 per project.

```json
[
  { "op": "set", "path": "/components/schemas/Account/properties/id/type", "value": "string", "reason": "ids are strings" },
  { "op": "rename", "path": "/components/schemas/Acct", "to": "Account" },
  { "op": "remove", "path": "/paths/~1internal~1debug" },
  { "op": "append", "path": "/servers", "value": { "url": "https://sandbox.acme.example.com/v1", "description": "Sandbox" } }
]
```

| Op       | Does                                                                                                        | Requires |
| -------- | ----------------------------------------------------------------------------------------------------------- | -------- |
| `set`    | Replaces the value at the path. Creates a missing final key when the parent exists and the path is literal. | `value`  |
| `append` | Pushes onto the array at the path.                                                                          | `value`  |
| `remove` | Deletes the key or array element at the path.                                                               |          |
| `rename` | Renames an object key. Refuses if the destination exists.                                                   | `to`     |

`reason` is optional and shows up in the console and in warnings, so future you knows why the patch exists.

## Path patterns

Paths are JSON Pointers with three additions for bulk fixes:

* `*` matches any child.
* `**` matches any depth, including zero.
* `[name=account_id]` matches children that are objects whose `name` property is `account_id`.

```json
{ "op": "set", "path": "/paths/**/parameters/[name=account_id]/schema/type", "value": "string" }
```

That one patch retypes every `account_id` parameter in the document.

Renaming a schema under `/components/schemas` (or `/definitions` in Swagger 2.0) rewrites every `$ref` to it, so nothing dangles.

## Where patches apply

Everywhere a project's spec is read:

* Every generation, whatever the trigger.
* Both sides of [preview builds](https://typeship.dev/docs/projects/preview-builds), so PR diffs reflect the spec change rather than the patches.
* The [hosted MCP endpoint](https://typeship.dev/docs/platforms/mcp#hosted-endpoint).

Project settings link to **the patched spec**: the live source with your patches applied, exactly as generation sees it, with a count of applications and any diagnostics.

## When a patch misses

A patch whose target no longer exists is skipped and reported as a warning on the generation:

```text
Spec patch matched nothing: not applied: set /components/schemas/Acct/properties/id/type (ids are strings)
```

Nothing drifts silently. If the upstream spec fixes the problem, the warning tells you the patch can go.

## Limits

* Patches address OpenAPI documents. GraphQL schemas generate unpatched, with a warning when patches are configured.
* Patches are not a transform language. There is no templating and no conditional logic, on purpose. When a fix needs more than set, append, remove, and rename, fix the spec.

## Sitemap

[Every page of these docs](https://typeship.dev/llms.txt)
