# Charming remix — fork an app or open it up for visitors to fork

There are two ways a Charming app gets "remixed," and they answer different questions:

- **Read its source so you can re-author it.** Use this when I want a copy of an app I (or my agent) already own and you need the actual `module` / `ui` / `styles` to edit. The fork is a new `create_app` call seeded by that source.
- **Let any visitor fork it by opening the URL.** Use this when I want to share an app on Reddit, in a group chat, or with a friend, and I want each of them to get their own editable copy that doesn't change mine. The original stays untouched; existing remixes are independent.

Pick the one that matches what I asked for. Don't flip the public flag on an app just because you want to read the source — `get_app_source` already does that for the owner.

## 1. Export source to re-author (`get_app_source` / `GET /app/<id>/source`)

Use this to inspect, debug, or fork-by-edit an app the caller owns. It returns the exact bytes Charming has stored for that app, plus a monotonic `version` number you'll pass back on any later edit.

### MCP

```
get_app_source({ app_id: "<uuid>" })
```

Returns a JSON payload (pretty-printed as `content[0].text`) with the shape:

```
{
  id, url, manifestId, sourceManifestId, displayName, version,
  capabilities, claimed, expiresAt,
  source: { module: "...", ui: "..." | null, styles: "..." | null }
}
```

Owner-only — the call fails with `not_found` if the MCP user does not own the app. `get_app` _renders_ the app; `get_app_source` _exports the code_. Don't confuse them.

### HTTP

```
curl -sS https://charm.ing/app/<id>/source \
    -H "Authorization: Bearer $TOKEN"
```

Auth is stricter than rendered access: the original `bld_app_*` edit token works for unclaimed apps, and a signed-in owner's `bld_user_*` works for claimed apps. Render tokens and claim cookies are rejected. The response body matches the MCP payload above and the response carries `ETag: "v<N>"`; keep it for any subsequent `PUT /app/<id>` or `PATCH /app/<id>/source` (pass it as `If-Match`).

### From source to a fresh remix

To author a sibling app that starts from the same code, pass the returned `source.module` (and `ui`, `styles`) into a fresh `create_app` / `POST /app` call. Bump `manifest.id` if the original was a routes-based app and you want the remix to live as a distinct app row rather than re-replacing the source. Storage does NOT carry over — the new app starts with empty storage by design.

## 2. Share the URL so visitors auto-fork (`set_remixable`)

When the user says "send this to friends", "post this on Reddit", or "make a share link", flip the remixable flag instead of handing them the raw `/app/<id>` URL. Anyone who opens the resulting URL gets their own fresh editable copy seeded from the template's source at that instant; their edits do not change mine. Each visitor's copy is independent and they can claim it by signing up later.

Confirm with the user before flipping the flag and surface the consequence ("anyone with this URL can interact with your app as their own remix") so they are not surprised. To revoke sharing, call `unset_remixable`; existing remixes survive untouched.

**Anonymous apps cannot be made remixable.** If the app is still unclaimed, `set_remixable` refuses with `not_found`. Tell the user to claim it first (open the URL, sign up to save it), then call `set_remixable`.

### MCP

```
set_remixable({ app_id: "<uuid>" })   // returns { public_url, message }
unset_remixable({ app_id: "<uuid>" })
```

Both calls are idempotent. `set_remixable` has `destructiveHint: false`; `unset_remixable` has `destructiveHint: true` because it revokes new visitors' ability to create remixes. Existing remixes remain available, and the owner can allow new remixes again later.

### HTTP

```
curl -sS -X PUT https://charm.ing/app/<id>/remixable \
    -H "Authorization: Bearer $USER_TOKEN" \
    -H 'Content-Type: application/json' \
    -d '{"remixable": true}'
```

User-scoped auth required (a `bld_user_*` token from device-code pairing or a PAT — see the device-code pairing flow in https://usecharming.com/llms-full.txt). The same route with `{"remixable": false}` revokes sharing.

Response:

```
{ "remixable": true, "public_url": "https://charm.ing/..." }
```

Hand `public_url` back to the user — that's the link they share.

## Starter prompt — what visitors see in "Open in Claude / ChatGPT"

Every rendered Charming app shows a control-panel pill with **Open in Claude**, **Open in ChatGPT**, and **Copy prompt** actions. The default prompt is generic ("I'm using a Charming app at <url>, help me use it"). For a shared/remixable app you can author a custom prompt that better steers the visiting assistant — see https://usecharming.com/profile.md for `set_starter_prompt`. Remixes snapshot the template's starter prompt at fork time; remixers can re-author with their own `set_starter_prompt` call later.

## When to use which

| User says                                  | Do this                                      |
| ------------------------------------------ | -------------------------------------------- |
| "Copy this so I can change it"             | `get_app_source` → new `create_app`          |
| "Show me the code for this app"            | `get_app_source` (no fork yet)               |
| "Share this so my friends can use a copy"  | `set_remixable`, share the returned URL      |
| "Stop letting people remix this"           | `unset_remixable` (existing remixes survive) |
| "What will visitors see when they open it" | `set_starter_prompt` (see profile.md)        |

For the full machine-readable contract — every route, error `kind`, and limit — fetch https://charm.ing/.well-known/openapi.json. For sandbox/UI rules when authoring the remix, read https://usecharming.com/design.md before writing the UI.
