# UseMy App Publishing Skill

Use this skill when you are an AI coding agent that has built or modified a local web app and the user wants to add it to UseMy Workbench, publish it through UseMy Cloud, or hand the setup details to the app owner.

UseMy lets a creator run an app on their own computer, Mac mini, home server, NAS, or VPS, then publish a clean public app URL without exposing the local host address, port, device ID, or device token.

## Default Service

- UseMy Cloud URL: `https://usemy.assetcommons.com`
- Workbench local API: `http://127.0.0.1:4178`
- UseMy Agent CLI: `usemy-agent` or `node bin/usemy-agent.mjs`
- Workbench download page: `https://usemy.assetcommons.com/download`
- Windows installer: `https://usemy.assetcommons.com/downloads/usemy-workbench-setup-latest.exe`
- macOS installer: `https://usemy.assetcommons.com/downloads/usemy-workbench-macos-latest.dmg`

## Product Boundary

Ordinary users install Workbench. They should not be asked to download Agent as a separate product.

Remote Agent installation should be started by Workbench or by a short-lived command generated by Workbench. If you are helping the owner directly over SSH, treat `usemy-agent` commands as implementation details and report the final app fields back to the owner.

An Agent belongs to one UseMy account/Workbench owner. Do not take over a host that already has a UseMy Agent unless the owner explicitly asks you to release or reset the existing installation.

## Preferred App Server Flow

Use this when the owner has a dedicated Linux/Mac mini/app server and wants you to deploy apps there from another computer over SSH.

1. SSH into the app server.
2. Put the app in a dedicated directory, not inside the UseMy Agent data directory.
3. Start the app with a stable service manager such as `systemd`, `launchd`, `pm2`, or a project-specific supervisor.
4. Verify the app from the app server itself:

```bash
curl -I http://127.0.0.1:3000/
```

5. Verify UseMy Agent is running:

```bash
usemy-agent status --json
```

If `usemy-agent` is not on PATH, use:

```bash
node /path/to/usemy/bin/usemy-agent.mjs status --json
```

6. Connect UseMy Cloud if not configured:

```bash
usemy-agent connect --name "Owner app server"
```

7. Add the app privately first unless the owner explicitly asked to publish:

```bash
usemy-agent add-app \
  --name "My App" \
  --url http://127.0.0.1:3000/ \
  --group "Apps" \
  --description "A local app built with an AI agent."
```

8. If the owner explicitly asked to publish, add it with `--public` and a stable slug:

```bash
usemy-agent add-app \
  --name "My Public App" \
  --url http://127.0.0.1:3000/ \
  --public \
  --slug my-public-app \
  --description "A public app hosted from the owner app server."
usemy-agent sync
usemy-agent shares
```

Report the public URL only after it appears in `usemy-agent shares`.

## Dedicated App Server Safety

When the owner uses an idle PC, Linux box, or Mac mini as an app server:

- Prefer Linux for old PCs and macOS for Mac mini hosts.
- Prefer a separate router, guest network, VLAN, or firewall rules so the app server cannot reach the owner's main home LAN.
- Keep UseMy Agent bound to `127.0.0.1` unless the owner explicitly asks for LAN API access.
- Manage the app server over SSH instead of exposing UseMy Agent directly to the LAN.
- Never publish router admin pages, NAS pages, camera pages, dashboards, SSH/RDP/database ports, or broad internal network URLs.
- Publish only the specific local app URL the owner approved.

## What You Should Produce After Building An App

After you finish building the user's app, make it UseMy-ready before reporting the app fields.

Create a deterministic local start path for the project. Do not rely on the user's global shell state, a previously activated virtualenv, globally installed packages, or hardcoded development ports.

For every AI-built web app:

- Include a project-local start command that honors `PORT`, `USEMY_PORT`, or `APP_PORT`.
- Bind the app server to `127.0.0.1` for private local use or `0.0.0.0` only when Workbench/remote access needs it.
- Add a short smoke test command, usually `curl -I http://127.0.0.1:<port>/`.
- Keep generated caches, virtualenvs, node modules, exports, uploads, and large user data out of the packaged app unless the owner explicitly wants them bundled.
- Prefer an `apphub.manifest.json` when the app is meant to be dragged into Workbench as a folder.

For Python apps:

- Include `requirements.txt`.
- Include a `start.sh` that creates or reuses a project-local `.venv`, installs requirements into that venv, and runs the web server.
- Never ask UseMy or the owner to install Python packages into the system Python. Homebrew and distro-managed Python may reject global `pip install` with an externally managed environment error.
- For Streamlit, run `python -m streamlit run app.py --server.address=0.0.0.0 --server.port="${PORT:-8080}" --server.headless=true`.

Recommended `start.sh` pattern for Python apps:

```sh
#!/usr/bin/env sh
set -eu

APP_PORT="${PORT:-${USEMY_PORT:-${APP_PORT:-8080}}}"
PYTHON_BIN="${PYTHON_BIN:-python3}"

if [ ! -x ".venv/bin/python" ]; then
  "$PYTHON_BIN" -m venv .venv
fi

PYTHON_BIN=".venv/bin/python"

if ! "$PYTHON_BIN" -c "import streamlit" >/dev/null 2>&1; then
  "$PYTHON_BIN" -m pip install -r requirements.txt
fi

exec "$PYTHON_BIN" -m streamlit run app.py \
  --server.address=0.0.0.0 \
  --server.port="${APP_PORT}" \
  --server.headless=true
```

Recommended `apphub.manifest.json` fields:

```json
{
  "manifestVersion": 1,
  "id": "my-ai-app",
  "name": "My AI App",
  "description": "A local web app built with an AI coding agent.",
  "type": "web",
  "runtime": {
    "kind": "python",
    "startCommand": "sh start.sh",
    "port": 8080,
    "healthPath": "/"
  },
  "entry": {
    "localUrl": "http://127.0.0.1:8080/",
    "publicPath": "/"
  },
  "sharing": {
    "defaultAudience": "private",
    "allowPublic": true,
    "visibility": "unlisted",
    "pricing": "free",
    "requiresLogin": false
  },
  "permissions": {
    "filesystem": "app-data-only",
    "network": {
      "inbound": ["127.0.0.1:8080"],
      "outbound": []
    }
  }
}
```

After the app is UseMy-ready, report these fields clearly:

```json
{
  "name": "Human friendly app name",
  "localUrl": "http://127.0.0.1:3000/",
  "healthUrl": "http://127.0.0.1:3000/health",
  "iconText": "APP",
  "color": "#0f766e",
  "description": "One short sentence explaining what this app does.",
  "recommendedVisibility": "private | unlisted | public",
  "pricing": "free | paid | subscription",
  "requiresLogin": false,
  "safeToPublish": true,
  "notesForOwner": "Anything the owner must start, keep running, or review before publishing."
}
```

If you know the app should be published, also give the owner this instruction:

> Open UseMy Workbench, add this app as a local web app, test it locally, move it to the public sharing area, connect UseMy Cloud, then sync publishing status.

## Manual Workbench Setup For The Owner

Use this when you cannot call the Workbench local API directly.

1. Make sure the app is running locally.
2. Open `UseMy Workbench`.
3. Click `Add`.
4. Choose `Local service` if the app runs on `localhost` or `127.0.0.1`.
5. Fill in:
   - Name
   - Port
   - Path
   - Icon text
   - Color
   - Description
   - Visibility
   - Pricing
   - Whether login is required
6. Save the app.
7. Keep it in the private area if only the owner should use it.
8. Move it to the public sharing area only if the owner explicitly wants others to use it.
9. Open Settings and click `Connect UseMy Cloud`.
10. Sync publishing status and copy the public app URL.

## Direct Workbench API Setup

Use this only when:

- You are running on the same host as UseMy Workbench.
- The user asked you to add or publish the app directly, or it is clearly part of the task.
- You have verified the app is running locally.

Never call the cloud owner APIs directly from the user's app code. Use the local Workbench API.

### 1. Check Workbench Is Running

```bash
curl http://127.0.0.1:4178/api/state
```

If this fails, ask the user to open UseMy Workbench or start it yourself if you have permission.

### 2. Let Workbench Discover Local Candidates

Use this when the user wants help finding apps/tools that can be added. It only reports candidates; the owner or agent must still choose what to add.

```bash
curl http://127.0.0.1:4178/api/discover-apps
```

The response includes `candidates[]` with `alreadyAdded`, `reason`, and an `app` object. Only add candidates that are clearly intended by the owner. Do not publish command-line tools, terminals, Workbench settings, or private dashboards.

### 3. Add A Private App

Use private mode first unless the user explicitly asked to publish.

```bash
curl -X POST http://127.0.0.1:4178/api/apps \
  -H "Content-Type: application/json" \
  -d '{
    "name": "My App",
    "type": "web",
    "url": "http://127.0.0.1:3000/",
    "iconText": "MY",
    "color": "#0f766e",
    "group": "My apps",
    "description": "A local app built with an AI agent.",
    "trustLevel": "owned",
    "audience": "private",
    "visibility": "public",
    "pricing": "free",
    "requiresLogin": false,
    "enabled": true,
    "requiresApproval": false
  }'
```

### 4. Add And Publish A Public App

Use this only with explicit owner intent.

```bash
curl -X POST http://127.0.0.1:4178/api/apps \
  -H "Content-Type: application/json" \
  -d '{
    "name": "My Public App",
    "type": "web",
    "url": "http://127.0.0.1:3000/",
    "iconText": "MY",
    "color": "#0f766e",
    "group": "Published apps",
    "description": "A public app hosted from the owner machine.",
    "trustLevel": "owned",
    "audience": "shared",
    "publicSlug": "my-public-app",
    "visibility": "public",
    "pricing": "free",
    "requiresLogin": false,
    "enabled": true,
    "requiresApproval": false
  }'
```

Then connect/sync UseMy Cloud:

```bash
curl -X POST http://127.0.0.1:4178/api/relay-center/connect \
  -H "Content-Type: application/json" \
  -d '{
    "centerUrl": "https://usemy.assetcommons.com",
    "deviceName": "Owner host"
  }'
```

Workbench provisions and stores the device token automatically. Do not ask the user for an owner token or device token.

### 5. Read Published Shares

```bash
curl http://127.0.0.1:4178/api/relay-center/shares
```

Report the `publicUrl` to the owner only after it appears in the response.

## Local App Requirements Before Publishing

Before adding the app to Workbench, verify:

- The app is reachable at a stable local URL, preferably `http://127.0.0.1:<port>/`.
- The app does not require access to Workbench settings, local APIs, terminals, or private files.
- The app does not expose stack traces, environment variables, tokens, local filesystem paths, internal IP addresses, or admin panels.
- If the app needs authentication, set `requiresLogin: true`.
- If the app is experimental, use `visibility: "unlisted"` first.
- If the app is only for the owner, keep `audience: "private"`.

## Security Rules

- Never publish UseMy Workbench itself.
- Never publish Codex, Claude Code, terminal sessions, settings, logs, pairing pages, or internal APIs.
- Never expose local LAN IPs, private ports, owner tokens, device tokens, relay tokens, or cloud API secrets to visitors.
- Never store UseMy device tokens inside the user's app repository.
- Never change an app from private to shared unless the user explicitly asked.
- Prefer a narrow app URL over a broad dashboard URL.
- Tell the owner what is being published in plain language.

## Recommended Owner-Facing Summary

When finished, send the owner something like:

```text
I built the app and prepared it for UseMy.

Local URL:
http://127.0.0.1:3000/

Workbench fields:
Name: My App
Type: Local web app
Icon: MY
Color: #0f766e
Visibility: Unlisted first
Login required: No

Safety note:
This publishes only the app URL above. It should not expose your files, terminal, Workbench settings, or local network details.

Next step:
Open UseMy Workbench, add the app with these fields, test it locally, then move it to the public sharing area if you want others to use it.
```

If you added and synced it directly, include:

```text
Public URL:
https://usemy.assetcommons.com/apps/...
```
