Build with Claude Code.

Claude Code registers and builds your Hello Purple app, on demo accounts only. It never reads your keys.

For now, an app works only for the person who registered it. No one else can use it, not even with their own account.

You need Node 20 or newer, macOS, Linux or WSL, and a staging account with a supported broker (create one at Axiory).

TL;DR · Already know Claude Code plugins?

claude plugin marketplace add https://portal-plt-1455.murban.personal.purple-lab.dev/marketplace.json
claude plugin install hello-purple@hello-purple

Then start Claude Code in an empty folder for your app, type /mcp, choose plugin:hello-purple:apps, pick Authenticate and sign in, and tell it: “Register a Hello Purple app that reads my demo trading accounts, sign it in, and build me a local app that shows them.”

Or let Claude Code take every step. Say this to it:

Read https://portal-plt-1455.murban.personal.purple-lab.dev/start/agent.md and follow it to set me up with Hello Purple and build me a small app that shows my trading accounts.

Not using Claude Code locally? Go back or use My Apps.

Only you can:

  • Say yes to the plugin install, and type /reload-plugins when asked.
  • Type /mcp, choose Authenticate and accept the terms.
  • Approve the one register_app call, with the per-call prompt kept on.
  • Let the sign-in script run outside the sandbox, then sign in again with the same account.

You're done when you see check: status=200 accounts=N, or check: skipped for an app that reads no accounts.

For agents: this page as Markdown.

For your agent

The brief it follows, with the values for this environment

The person wants their own Hello Purple app, built with you, in the test environment plt-1455.

You are done when the app is registered in their name, its key and sign-in are in their store, the sign-in script has printed its check: line, and the app runs from a folder they own without you.

Before you act. Claude Code on the person's own computer: follow this page. Any other host is not officially supported yet: send the person to https://portal-plt-1455.murban.personal.purple-lab.dev/apps.

  • Never read, print or ask for a key or token.
  • Never accept terms for the person.
  • Ask the person before any risky permission.
  • Keep the host's per-call approval on.
  • Driving a browser? Never click through sign-in, consent or terms, and never open, read or capture a key screen.

Values for this environment

Procedure

  1. Ask the person before installing anything. With their yes, run claude plugin marketplace add https://portal-plt-1455.murban.personal.purple-lab.dev/marketplace.json, then claude plugin install hello-purple@hello-purple. If you installed it in this session, ask them to type /reload-plugins.
  2. Ask the person to type /mcp, choose plugin:hello-purple:apps and pick Authenticate. They sign in and accept the terms on the consent page themselves.
  3. For trading or market data, load the plugin's build-on-yourbourse skill first.
  4. Load and follow the app-access and safe-secret-handling skills. They choose the permissions, ask about the risky ones, register the app through the redeemer script, and store ENGINE_API_KEY and ENGINE_WEBHOOK_SECRET in the person's .env or 1Password.
  5. Sign the app in. An app with a page gets the skill's sign-in button. An app without one uses the authorize script, which ends with check: status=200 accounts=N, or with check: skipped when the app does not read accounts.
  6. Build the app as a standalone local server, in a folder the person owns, from copies of the skill's templates. At runtime it reads ENGINE_API_KEY and ENGINE_REFRESH_TOKEN from .env, saves the new refresh token after every refresh, and calls the API with Authorization: Bearer plus X-API-Key.

Also

  • Rotating the key or the webhook secret, and revoking the app, need the person's yes in the chat first.
  • A permission the app lacks is added to the same app, never by registering a new one. After an addition or a removal, sign the app in again.
  • Every trading-account permission is a demo one. Live accounts are out of reach.

Do it by hand

Install, update and remove the plugin, store the key in 1Password, manage your apps

Install the plugin

Run these in a terminal. Then start Claude Code in an empty folder for your app: that folder gets the .env.

claude plugin marketplace add https://portal-plt-1455.murban.personal.purple-lab.dev/marketplace.json
claude plugin install hello-purple@hello-purple

If Claude Code is already running, type /reload-plugins in it.

Update to the latest deploy

claude plugin marketplace update hello-purple
claude plugin update hello-purple@hello-purple

Then type /reload-plugins in Claude Code.

Remove the plugin and its marketplace

claude plugin marketplace remove hello-purple

Store the key in 1Password

Ask for it when you register:

Register my-first-app with trading account read access and store the key in 1Password, vault Private, item my-first-app, field ENGINE_API_KEY. Then sign it in and store the token in the same item.
  • Use a private vault, never a shared one.
  • Approve the 1Password prompt when each script starts. One approval covers that run.
  • Signed in to more than one 1Password account? Start Claude Code with OP_ACCOUNT=<account> claude; op account list shows the names.

Manage your apps

Ask Claude Code in plain words, or use My Apps.

  • “List my apps”: each app's id, client id, permissions and whether it is active.
  • “Let my-first-app place demo trades”: adds the permission to the same app. A risky one waits for your yes, and the app signs in again.
  • “Remove the trades permission from my-first-app”: removes it and the app's calls that use it, and the app signs in again.
  • “Rotate the key for my-first-app”: issues a new key and stores it. The old key stops working at once, so the agent asks you first. Up to ten rotations per app in 24 hours.
  • “Rotate the webhook secret for my-first-app”: issues a new signing secret and stores it as ENGINE_WEBHOOK_SECRET. The old one keeps working for 24 hours.
  • “Show the redirect URLs”: where sign-ins may return. Keep http://127.0.0.1:8401/callback while you use the sign-in script.
  • “Revoke my-first-app”: switches the app off for good and deletes its key. The agent asks you first.

If something goes wrong

Fixes, by what you see

Never paste a key or token into the chat. If one ends up there, ask the agent to rotate it.

Installing the plugin

Node is too old (NODE_TOO_OLD) “Node 20 or newer is required”
  • Run node --version in a terminal. The scripts need Node 20 or newer.
  • Install a current Node, then ask the agent to run the script again.
The plugin will not install (MARKETPLACE_ADD_FAILED) claude plugin marketplace add fails
  • Open the marketplace file in a browser. If it does not load, this environment is being redeployed or is down: try again in a few minutes.
  • Update Claude Code to a current version, then run the command again.
Claude Code does not know the plugin's skills (PLUGIN_NOT_LOADED)
  • Type /reload-plugins in Claude Code.
  • Still missing? Run claude plugin install hello-purple@hello-purple in a terminal, then type /reload-plugins again.
The connector is missing (CONNECTOR_MISSING) /mcp does not list plugin:hello-purple:apps
  • Type /reload-plugins, then /mcp again.
  • Still missing? Run claude plugin marketplace update hello-purple and claude plugin update hello-purple@hello-purple in a terminal, then type /reload-plugins.

Signing in

The terms are not accepted TERMS_ACCEPTANCE_REQUIRED
  • New terms are in force, and only you can accept them.
  • Type /mcp, choose plugin:hello-purple:apps, pick Authenticate and accept the terms on the consent page. Or accept them in My Apps.
  • Then ask the agent to try again.
The sign-in script cannot listen EPERM or “bind refused”
  • The script ran inside the agent's sandbox, where it cannot listen for your sign-in.
  • Allow it when the agent asks to run the script outside the sandbox, then sign in again.
A port is already in use (EADDRINUSE) “Another process is listening on 127.0.0.1”
  • Another program holds the port the script needs, often an earlier run of the same script.
  • Find it with lsof -i :8400 or lsof -i :8401, and stop it.
  • Then ask the agent to run the script again.
The sign-in never comes back (SIGN_IN_TIMEOUT)
  • The app lacks the redirect URL http://127.0.0.1:8401/callback.
  • Ask the agent to add it to the app's redirect URLs, then to sign the app in again.
You signed in with another account APP_NOT_FOUND
  • You signed in with a different account than the one Claude Code is connected with.
  • Ask the agent to run it again, and sign in with the account you used in /mcp.
  • If the message says its one-time pickup is bound to this run, also ask the agent to rotate what the message names, the key or the webhook secret, and confirm when it asks.

Keys and secrets

The one-time pickup expired RETRIEVAL_TOKEN_EXPIRED or RETRIEVAL_TOKEN_NOT_REDEEMABLE
  • The one-time pickup of the key or the webhook secret expired after five minutes or was already used.
  • Ask the agent to rotate what the message names, the key or the webhook secret, and confirm when it asks.
The key was rotated too often ROTATION_WINDOW_CAP
  • The key was rotated ten times in 24 hours.
  • Wait until the time the message names. If the key is exposed, ask the agent to revoke the app instead, and confirm.

Permissions and calls

A call lacks a permission SCOPE_INSUFFICIENT from your app or the check
  • The app lacks that permission, or its sign-in is older than the permission.
  • Tell the agent which call failed. It adds the permission to the same app, or signs the app in again.
An operation is turned off ROUTE_NOT_CONFIGURED from your app or the check
  • The app holds the permission, but that operation is turned off for it. A new permission does not fix this.
  • Turn the operation on in the app's Advanced view in My Apps.
The check was skipped (CHECK_SKIPPED) check: skipped (the app does not hold the account list)
  • Nothing is wrong. The app does not read your account list, so the script made no test call.
  • Check the app by what it shows.

1Password

1Password did not get an answer (OP_AUTHORIZATION_TIMEOUT) 1Password “authorization timeout”
  • The 1Password approval prompt was not answered in time.
  • Ask the agent to run the script again, and approve the prompt when it appears.
You have more than one 1Password account (OP_MULTIPLE_ACCOUNTS) 1Password “more than one account”
  • Run op account list to see your account names.
  • Quit Claude Code, start it again with OP_ACCOUNT=<account> claude, and ask the agent to run the script again.