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

# Bundle Reusable Harnesses with ChappiePluginManifest

> Bundle a harness, tools, and plugins into a ChappiePluginManifest you can share across clients, serialize to JSON, and resolve at runtime.

A `ChappiePluginManifest` is a packaging type for a reusable harness bundle. It wraps a base `ChappieHarness` together with additional tool descriptors, plugin descriptors, and arbitrary setup metadata — all in a single `Codable` value you can store, share, or load from JSON. When you're ready to create a client, call `manifest.resolvedHarness` to merge everything into a single `ChappieHarness` with duplicates removed.

## Create and use a plugin manifest

```swift theme={null}
let manifest = ChappiePluginManifest(
    identifier: "com.example.inventory",
    displayName: "Inventory Assistant",
    summary: "Inventory lookup and replenishment helpers.",
    version: "0.1.0",
    harness: ChappieHarnessSamples.inventory
)

let client = Chappie.client(harness: manifest.resolvedHarness)
let reply = try await client.send("How much stock is left for SKU-456?")
```

`resolvedHarness` merges the manifest's `tools` and `plugins` arrays into the base harness, deduplicating tools by name (first occurrence wins). The returned `ChappieHarness` is a plain value with no reference back to the manifest, so you can mutate or extend it further before passing it to the client.

## Manifest fields

<ParamField path="identifier" type="String" required>
  A reverse-DNS bundle identifier that uniquely names this manifest, for example `"com.example.inventory"`. Use it as a stable key when storing or referencing manifests across builds.
</ParamField>

<ParamField path="displayName" type="String" required>
  A human-readable name shown in debug surfaces and logs, for example `"Inventory Assistant"`.
</ParamField>

<ParamField path="summary" type="String" required>
  A short description of what the manifest's harness covers. This text is not sent to the model directly — it lives in the manifest layer for documentation and tooling purposes.
</ParamField>

<ParamField path="version" type="String?">
  A semver string such as `"0.1.0"`. Optional, but useful when you distribute manifests as versioned packages or store them in a registry.
</ParamField>

<ParamField path="harness" type="ChappieHarness" required>
  The base harness. All tools and plugins from `tools` and `plugins` arrays are merged into this harness when you call `resolvedHarness`.
</ParamField>

<ParamField path="tools" type="[ChappieHarnessTool]">
  Additional tool descriptors merged into the harness at resolution. Any tool whose `name` already exists in `harness.tools` is silently dropped — the harness definition takes precedence.
</ParamField>

<ParamField path="plugins" type="[ChappieHarnessPlugin]">
  Additional plugin descriptors appended to the harness at resolution. Unlike tools, plugins are not deduplicated by name.
</ParamField>

<ParamField path="setupMetadata" type="[String: ChappieJSONValue]">
  A free-form dictionary for arbitrary metadata your app needs at setup time — API endpoints, feature flags, configuration values, and so on. The model never sees this directly; it's available to your own code after you decode the manifest.
</ParamField>

## Add extra tools and plugins at manifest creation

Pass `tools` and `plugins` to the manifest initializer to augment the base harness without modifying it:

```swift theme={null}
let manifest = ChappiePluginManifest(
    identifier: "com.example.fulfillment",
    displayName: "Fulfillment Suite",
    summary: "Order creation, tracking, and cancellation flows.",
    version: "1.2.0",
    harness: ChappieHarnessSamples.inventory,
    tools: [
        ChappieHarnessTool(
            name: "create_order",
            description: "Creates a new purchase order for a given SKU and quantity.",
            inputSchema: .object([
                "type": .string("object"),
                "properties": .object([
                    "sku": .object(["type": .string("string")]),
                    "quantity": .object(["type": .string("number")])
                ]),
                "required": .array([.string("sku"), .string("quantity")]),
                "additionalProperties": .bool(false)
            ])
        )
    ],
    plugins: [
        ChappieHarnessPlugin(
            name: "fulfillment-workflows",
            description: "Multi-step order creation and cancellation workflows.",
            version: "1.0.0"
        )
    ],
    setupMetadata: [
        "api_base_url": .string("https://api.example.com/v2"),
        "max_order_qty": .number(500)
    ]
)

let client = Chappie.client(harness: manifest.resolvedHarness)
```

## ChappieHarnessPlugin fields

Plugin descriptors give the model awareness of named workflow plugins available in the harness. They are purely declarative — the model can reference them in reasoning, but runtime plugin execution APIs are coming in a future release.

<ParamField path="name" type="String" required>
  A unique, machine-readable plugin identifier, for example `"fulfillment-workflows"`.
</ParamField>

<ParamField path="description" type="String" required>
  A short, human-readable description of what the plugin does. The model sees this in the harness manifest.
</ParamField>

<ParamField path="version" type="String?">
  An optional semver string for the plugin, for example `"1.0.0"`.
</ParamField>

## Built-in sample harnesses

`ChappieHarnessSamples` provides ready-made harnesses for common app surfaces. Use them as the `harness` base in a manifest or pass them directly to `Chappie.client(harness:)`:

<CardGroup cols={2}>
  <Card title=".currentScreen" icon="display">
    Declares a `read_current_screen` tool. Use it in assistants that need to answer questions about the currently visible UI state.
  </Card>

  <Card title=".documents" icon="doc.text">
    Declares a `read_selected_document_text` tool. Use it for summarization, rewriting, and structured extraction flows.
  </Card>

  <Card title=".photos" icon="photo">
    Declares a `describe_selected_photo` tool. Use it when the assistant should reason about user-selected photo metadata.
  </Card>

  <Card title=".inventory" icon="shippingbox">
    Declares a `lookup_item` tool. Use it as the starting point for inventory lookup and replenishment conversations.
  </Card>
</CardGroup>

## Serialize and deserialize manifests

<Note>
  `ChappiePluginManifest` conforms to `Codable`, so you can round-trip it through JSON. Store manifests in your app bundle, fetch them from a server, or cache them to disk — then decode and resolve them at runtime.
</Note>

```swift theme={null}
// Encode to JSON
let encoder = JSONEncoder()
encoder.outputFormatting = [.prettyPrinted, .sortedKeys]
let data = try encoder.encode(manifest)

// Decode from JSON
let decoded = try JSONDecoder().decode(ChappiePluginManifest.self, from: data)
let client = Chappie.client(harness: decoded.resolvedHarness)
```

This makes manifests a natural interchange format: ship a `manifest.json` in your app bundle for default configurations, or serve environment-specific manifests from your backend without recompiling your app.
