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

# Create a Shape and try it on a File

> A new Shape is published with a message, the project lists it, and one extraction from one File shows what it finds.

Guide · shapes

> **Use when**
>
> A person wants a Shape for a domain, and no Shape in the project or in the public library fits.

> **Looking for something else?**
>
> A change to a Shape the project has (recipe [change-a-shape](https://docs.pnbr.io/guides/change-a-shape.md)). A public Shape you adopt as it is (card [Shape](https://docs.pnbr.io/concepts/shape.md)). Extracting with a Shape that exists (recipe [extract-files](https://docs.pnbr.io/guides/extract-files.md)).

## Outcome

The project has a new Shape that the person's question shaped. Its first
version has a message. One extraction from one File ran with it, so the person
and you can see which types the Shape finds in real text. Nothing is in the
Graph yet.

## Before you start

1. Look before you write. Run `penumbra shapes` for the Shapes of the project
   and `penumbra shapes library "<words>"` for the public ones. If a public
   Shape fits, adopt it (card rule [shape.7](https://docs.pnbr.io/concepts/shape.md#rule-shape-7)). If a Shape of the project nearly
   fits, change it (recipe [change-a-shape](https://docs.pnbr.io/guides/change-a-shape.md)). Create a new Shape only when
   neither fits.

2. Know your credential: `penumbra whoami`. An editor writes drafts. An owner or
   an admin publishes. A project API key needs the scope
   `shapes.draft.publish`. Its publish waits for approval only if the
   project's policy holds `shape_change` (card rule [shape-draft.7](https://docs.pnbr.io/concepts/shape-draft.md#rule-shape-draft-7)).

3. Ask what the Shape is for. A Shape is an expert's lens on the person's
   Files. It names the kinds of things that the expert looks for, what each one
   means, and how they connect. Write down the question that the expert asks of
   these Files, in one sentence. Each type must serve that question. Penumbra does
   not choose the types for you (card [shape](https://docs.pnbr.io/concepts/shape.md)).

4. Choose how to start. Use one of these three.

   | Start from | Choose it when | Cost |
   | - | - | - |
   | A brief: `penumbra shapes new --brief "<text>"` | You can describe the domain in a few sentences. | Spends the project's credits. A key or a connected agent waits for approval. |
   | A blank draft: `penumbra shapes new --blank --name "<name>"` | You already know the types you want. | None. |
   | A fork: `penumbra shapes fork <shape> --name "<name>"` | An existing Shape is close, and yours differs. | None. A public Shape is `<publisher>/<shape>`. |

   Prefer a brief when you can describe the domain. You then edit a draft, and
   you do not write one from nothing. To change a Shape the project has,
   use `penumbra shapes edit <shape>` (recipe [change-a-shape](https://docs.pnbr.io/guides/change-a-shape.md)).

5. For a brief, choose what else the draft reads. The brief always says what
   the Shape is for. It holds at most 4,096 characters. To read a longer brief
   from a file, use `--brief-from <path>`, or `--brief-from -` for stdin.

   | Add | Choose it when | What changes |
   | - | - | - |
   | `--from <file>`, repeat for more | The project has Files of the kind that the Shape will read. | The draft fits the vocabulary and the things in those Files. Their text adds to the cost of the run. |
   | `--from-collection <collection>` | The Files are in one collection. | The same as `--from` for each File in the collection. |
   | `--like <shape>`, repeat for more | A published Shape has the style or the parts that you want. | The draft takes that Shape as a model. A name or an id means the Shape's latest version. |

   A `<file>` is a Workspace path, a File id or a name. Together the Files can
   be 64 at most, with at most 2 MiB of text. The draft fits the Files that
   you give, so state the general purpose in the brief when the Shape must
   serve more than these Files.

## Steps

1. Start the draft with the command that you chose in step 4. MCP, in `execute`:
   `penumbra.shapes.open({ name })` with a name that no Shape has starts a new
   Shape. `penumbra.shapes.generate({ brief, name })` starts from a brief; add
   `sources` (File ids) and `reference_shapes` (Shape names or ids) for step 5.
   `penumbra.shapes.copy({ from, name })` starts from a Shape in use.
   * Expect, for a blank draft or a fork: `Draft <id> is open at revision 1`.
     Keep the draft id.
   * Expect, for a brief: `Draft <id> started: generating (queued)`. A key or a
     connected agent gets exit code 4 and `pending` first (problem
     [change-waits-for-approval](https://docs.pnbr.io/troubleshooting/change-waits-for-approval.md)).

2. For a brief, wait until the draft is open. Run `penumbra shapes show <draft-id>` until it prints `Draft <id>: open` and an outline, instead of
   `generating`. It takes one to ten minutes, depending on the brief. MCP:
   `shape.read()` shows the progress.
   * `pull`, `check`, `diff` and `publish` on a generating draft stop with
     `draft_generating` and exit code 4. This is not an approval. Wait, then try
     again.
   * `Generation stopped; nothing was authored` means the run failed. Discard the
     draft with `penumbra shapes drop <draft-id>` and start again with a clearer
     brief or a blank draft.

3. Pull the definition file: `penumbra shapes pull <draft-id>`. MCP:
   `shape.read({ part: "model" })`.
   * Expect: `Wrote <path> from draft <id> at revision <n>.` The default file is
     `<name>.shape.json` in the current directory.
   * Edit this file. Do not edit a saved published artifact or the output of
     `penumbra shapes library show`. Both carry IDs and digests, and a push
     refuses them with `file_invalid`.

4. Edit the `definition` in the file. Write it from the question of step 3.
   Use recipe [write-better-descriptions](https://docs.pnbr.io/guides/write-better-descriptions.md) to clarify the meanings and keep them consistent across the Shape.

   * `description` and `telos.purpose`: the question, and who asks it.
   * Each type: a `description` that tells it apart from similar things, and the
     properties that the answer needs.
   * Each property: a `schema` whose `description` says what the value holds.
     Reading a File relies on it, and on the type's
     `semantics.extraction_guidance`.
   * Each relationship: `from_type_ref`, `to_type_ref` and a `cardinality`.
   * Keep the [source](https://docs.pnbr.io/concepts/source.md) field and every `*_ref`. The [source](https://docs.pnbr.io/concepts/source.md) field makes the
     next push go to the same draft (card rule [shape-draft.3](https://docs.pnbr.io/concepts/shape-draft.md#rule-shape-draft-3)).

   ```json theme={null}
   {
     "type_ref": "service_line",
     "name": "Service line",
     "description": "A service that the firm sells to clients, as the firm describes it.",
     "properties": [
       {
         "property_ref": "summary",
         "name": "summary",
         "schema": {
           "type": "string",
           "description": "What the service does for a client, in one sentence."
         },
         "required": false
       }
     ]
   }
   ```

   MCP: `shape.define({ name, description, telos, types, relationships })` sets
   the whole model. It saves each part that it can, and returns what to fix for
   each part that it cannot.

5. Push the file: `penumbra shapes push <name>.shape.json`. MCP: `shape.define`
   or `shape.modify`.
   * Expect: `Synced draft <id> to <file>: revision <n>` and `<file> now follows
     draft <id> at revision <n>.` Exit code 0.
   * If the push prints `Some of <file> could not be saved`, read each line `- <declaration>: not saved.` and its message. Fix those parts and push again.
     What was saved stays.

6. Check the draft: `penumbra shapes check <draft-id>`. MCP: `shape.validate()`.
   * Expect: `Draft <id> is valid at revision <n>` and exit code 0. Otherwise it
     exits with code 3 and lists diagnostics. Fix them, push and check again
     (card rule [shape-draft.4](https://docs.pnbr.io/concepts/shape-draft.md#rule-shape-draft-4)).
   * A valid draft can still print `Worth improving (N gaps; advice only…)`.
     Each line names a target (the Shape, a type, `type.property` or a
     relationship) and what is missing. The CLI prints the first five, and
     `penumbra shapes check <draft-id> --json` holds all of them.

7. Fix the gaps that the person's question needs, such as a type without a
   `description`. Push and check again. Say which gaps you left, and why. Advice
   never blocks a save.

8. Publish with a message: `penumbra shapes publish <draft-id> -m "<what the
   Shape is for>"`. MCP: `shape.submit({ note })`.
   * Expect, for a person's own session: `Published version <n> of Shape <id>.`
     and exit code 0.
   * If the policy holds `shape_change`, a key or a connected agent gets exit
     code 4 and `pending`. Give the person the approval URL and follow the
     handle (problem
     [change-waits-for-approval](https://docs.pnbr.io/troubleshooting/change-waits-for-approval.md)). Nothing is published until it is approved.
   * A publish adds the Shape to the project. Do not run `penumbra shapes add`:
     it adopts public Shapes only.

9. Try the Shape on one File. Pick a File that states what the question asks
   about. Check its text (recipe [check-file-text](https://docs.pnbr.io/guides/check-file-text.md)). Then follow recipe
   [extract-files](https://docs.pnbr.io/guides/extract-files.md) with that one File and the new Shape. The plan is free. The
   run is paid, so give the person the cost range and wait for a clear yes.

10. Read the items in the workspace that the run opened:
    `penumbra graph workspace show "<workspace>"`. Compare them with the
    question of step 3. Name the types that found items and the types that
    found none.
    * If a type is missing, a property is empty or the items miss the point,
      change the Shape (recipe [change-a-shape](https://docs.pnbr.io/guides/change-a-shape.md)). Then run again on the same File.
    * Submit the review only if the person wants these entities in the Graph
      (recipe [review-and-submit](https://docs.pnbr.io/guides/review-and-submit.md)).

## Check

1. `penumbra shapes log <name>` shows the new version first, with your message.
2. `penumbra shapes show <name>` outlines the types that you meant. Each one
   serves the question, and nothing that the question needs is missing.
3. The run from step 9 names its Shape, and its items use types of this Shape.
   You can say which types found items.
4. You told the person that nothing is in the Graph until a submit is approved
   (card rule [workspace.2](https://docs.pnbr.io/concepts/workspace.md#rule-workspace-2)).

## If it goes wrong

| You see | Go to |
| - | - |
| `file_invalid` and `is not a Shape definition file` (exit code 2) | You pushed JSON that is not a definition file. Pull the draft with step 3 and edit that file. |
| `draft_generating` (exit code 4) | The brief is still being drafted. Run `penumbra shapes show <draft-id>` until it is open (step 2). |
| `invalid_option` and `Choose one way to start` | Use `--blank` or `--brief`, not both. A blank draft also needs `--name`. To copy a Shape, use `penumbra shapes fork`. |
| `request_too_large` and `The reference Files hold` | The Files have more text than the limit. Leave out the largest Files that the message names, and start again. |
| `invalid_request` and `No published Shape matches` | A `--like` value names no published Shape. List the Shapes with `penumbra shapes` and use a name or an id from it. |
| A push exits with code 3 and `revision_conflict` | card rule [shape-draft.2](https://docs.pnbr.io/concepts/shape-draft.md#rule-shape-draft-2). Pull the draft again and reapply your edits. |
| A push says that someone else changed a part since you pulled | Pull the draft again to see the change, then reapply your edit. |
| A check exits with code 3 | Step 6. Fix the diagnostics, push and check again. |
| The brief or the publish exits with code 4 and prints `pending` | problem [change-waits-for-approval](https://docs.pnbr.io/troubleshooting/change-waits-for-approval.md) |
| `forbidden` on the publish | card rule [shape.10](https://docs.pnbr.io/concepts/shape.md#rule-shape-10) |
| `draft_locked` on a push | card rule [shape-draft.8](https://docs.pnbr.io/concepts/shape-draft.md#rule-shape-draft-8) |
| The plan for the extraction does not find the Shape | The publish may still wait for approval. List the Shapes with `penumbra shapes` and use the exact name. |

## Worth offering

* Offer to extract the rest of the Files, or a collection, when the first run
  reads well (recipe [extract-files](https://docs.pnbr.io/guides/extract-files.md)).
* Offer to change the Shape when the first run shows a missing type or an empty
  property (recipe [change-a-shape](https://docs.pnbr.io/guides/change-a-shape.md)).

## Report

Tell the person:

* The name of the Shape, its version and your message.
* How you started it (brief, blank or fork). For a brief, say that it spent
  credits, and name the Files and Shapes that it read.
* The question that the Shape answers, in the person's words.
* The gaps in `Worth improving` that you left, and why.
* The File you tried, the cost of the run, and which types found items.
* That nothing is in the Graph until a submit is approved, and who must approve
  it.

## Keep going

[Shape](https://docs.pnbr.io/concepts/shape.md) · [Shape draft](https://docs.pnbr.io/concepts/shape-draft.md) · [Approval](https://docs.pnbr.io/concepts/approval.md) · [Extraction](https://docs.pnbr.io/concepts/extraction.md) · [File](https://docs.pnbr.io/concepts/file.md) · [Change a Shape and publish it](https://docs.pnbr.io/guides/change-a-shape.md) · [Check that a File's text arrived intact](https://docs.pnbr.io/guides/check-file-text.md) · [Extract entities from Files](https://docs.pnbr.io/guides/extract-files.md) · [Review a workspace and submit it](https://docs.pnbr.io/guides/review-and-submit.md) · [A change returned pending](https://docs.pnbr.io/troubleshooting/change-waits-for-approval.md) · [Write better descriptions](https://docs.pnbr.io/guides/write-better-descriptions.md)

Penumbra Grammar 0.6.26


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