Living UI Importer
Bring existing apps into this CraftBot: marketplace installs (pre-built
apps from the catalogue), Living UI project imports from a ZIP, a local folder
path, or a git URL, and conversions of foreign (non-Living-UI) apps —
which are REBUILDS: the original code becomes reference material and the
behavior is re-implemented on this platform. Be honest about that cost
before converting: nothing of the original code runs here.
Which path?
| The user has… |
Do this |
| An app name / "what's in the marketplace?" |
living_ui_marketplace_list → match by name → living_ui_marketplace_install(app_id=...) |
A .zip, a project folder path, or a git URL of a Living UI |
living_ui_import(source=...) — one door for all three |
| A foreign (non-Living-UI) codebase |
living_ui_convert(source=...) — a full REBUILD; tell the user first |
Conversion (foreign apps)
living_ui_convert(source=..., name?, description?) scaffolds a fresh Living UI
project, ships the original source read-only at reference/source/,
synthesizes requirements.md FROM that source, and dispatches the normal
supervised build to the project's session — you are done after this call;
progress streams to the project tab and the system announces the result.
Pass description when the user said what matters ("keep the board, skip
the admin panel"). If the source turns out to BE a Living UI project the
action errors and points you to living_ui_import.
Marketplace install
living_ui_marketplace_list — resolve the exact app_id (never guess
ids; match the user's words against names/descriptions).
living_ui_marketplace_install(app_id="...", name="...") — downloads,
registers, and launches the app in one step.
- On success, tell the user the app name and URL. Marketplace apps are
pre-built and pre-verified upstream — no walk-verify needed.
NOTE: apps still in the legacy V1 format are rejected with a clear
error — the platform only runs current-format Living UIs. Tell the user that app hasn't been
re-published for this version of CraftBot yet; do not improvise a
workaround.
- On a launch error, treat it like any build failure: read ALL errors,
fix (the project is a normal Living UI project under the ownership rules),
living_ui_notify_ready again.
Project import (ZIP / folder / git URL)
living_ui_import(source="...") — accepts an absolute .zip path, a
local project folder path, or a git URL (GitHub is downloaded directly;
other hosts are cloned). Registers a NEW delivered project (fresh id +
port, shipped credentials stripped, kit re-vendored) and queues a
launch-and-verify run in the project's own session — normally you are
DONE after this call; the system announces the result.
Only native Living UI projects are accepted; anything else errors.
- Only if the action says the verify run could not be queued, drive it
yourself:
living_ui_notify_ready(project_id="<ID>") then
living_ui_walk_verify(project_id="<ID>") — the app is delivered, so
these run in staging mode and the walk's clean verdict deploys and
announces it. Fix any gate errors under the usual ownership rules.
HONESTY RULE: the import is done ONLY when the verify succeeds.
(living_ui_import_zip still exists as the ZIP-only legacy door.)
Adopting an EXTERNAL app (foreign source — runs AS-IS)
When living_ui_import receives a foreign (non-Living-UI) source it
registers it as an EXTERNAL project and dispatches an ADOPTION run with
these steps. The app runs UNCHANGED in its own runtime — never rebuild it,
never edit its code except configuration needed to bind the assigned port.
- Inspect the source at the project path: README, dependency manifests
(package.json / pyproject.toml / go.mod / Cargo.toml), how it starts,
which port/env it expects, whether it has a build step.
- Write the pipeline verbs into
<project>/craftbot.json (NOT
manifest.json — that may be the app's own file). Use {{PORT}} where
the port belongs; the app must bind 127.0.0.1:{{PORT}}:
- node: install
npm install --ignore-scripts; start e.g.
npm run dev -- --port {{PORT}} --host 127.0.0.1 or
PORT={{PORT}} node server.js — whatever THIS app's scripts support.
- python: install
pip install -r requirements.txt; start e.g.
python3 -m uvicorn main:app --port {{PORT}} / the app's own runner.
- static: no install; start
python3 -m http.server {{PORT}} from the
directory holding index.html.
- go / rust: build
go build -o app . / cargo build --release; start
the binary with its port flag/env.
- health: default
{"strategy": "http_get", "url": "http://127.0.0.1:{{PORT}}/"} — switch to tcp or process_alive
for servers that 404 on /.
- Map the app's controllable surface into
<project>/operations.json
(CraftBot's file — a stub exists) so agents can DRIVE the app over the
A2App protocol. At launch the system substitutes a hidden internal port
into your {{PORT}} verbs and serves the A2App adapter (identity,
describe, /api/_ops, guarded /api/ops/*, passthrough for everything
else) on the ASSIGNED port in front of the app. Probe in order:
OpenAPI/Swagger spec shipped in the repo → route definitions in the
code → the README. Declare the app's PUBLIC verbs with typed params;
each op maps executor.path (/api/ops/<name with dots as slashes>)
onto executor.upstream — the app's OWN endpoint:{ "name": "todos.create", "description": "Add a todo",
"params": { "title": { "type": "string", "required": true } },
"executor": { "type": "http", "method": "POST",
"path": "/api/ops/todos/create",
"upstream": { "method": "POST", "path": "/api/todos",
"body": { "title": "{{title}}" } } } }
(body template only when the app's field names differ from your param
names.) Mark anything that deletes/overwrites "destructive": true.
If the app has NO server API (static site, pure client-side SPA), leave
operations empty and say so in LIVING_UI.md — never invent verbs,
never map direct DB writes.
- Note what the app is in
LIVING_UI.md (one short section — the
user's reference). Do NOT rewrite reference/requirements.md: it is
pre-written with the adoption scope — verification covers the app
launches and its main screen renders, never the foreign app's internal
features (you can't fix those and must not try; the app ships as-is,
quirks included).
living_ui_notify_ready(project_id="<ID>") — launches via your pipeline
verbs. Errors come back with logs/app.log excerpts; fix the VERBS (or
port binding config), not the app's features, and retry.
living_ui_ops_verify(project_id="<ID>") — invokes every
non-destructive op FOR REAL through the adapter (destructive ops are
shape-checked, never fired). Fix executor.upstream mappings — or
remove ops that cannot work — and re-run until clean: a mapping that
does not work must not ship.
living_ui_walk_verify(project_id="<ID>") — verifies the launch and
announces. HONESTY RULE: adopted ONLY when this succeeds. If the app
fundamentally cannot run here (needs a database server, private APIs,
system deps), STOP and tell the user exactly what is missing — do not
fake a start command that serves an error page.
Changes to a running external app apply LIVE (no staging): edit →
living_ui_notify_ready relaunches it.
Notes
- Imported/installed projects are ordinary Living UI projects afterwards:
operate them via the lui CLI (
ops / run / data), modify them via
the living-ui-modify workflow. External apps speak the same ops surface
through their adapter — lui ops / lui run (and raw HTTP with the
project's .agent-token) work against them too; only the data verbs
don't apply (external apps expose operations only, no protocol
entities — the app's own API passes
through instead).
- Never edit
frontend/src/kit/, manifest.json, or other system files
of a Living UI project — the validation gate hashes them.
1---2name: living-ui-importer3description: Install Living UI apps from the marketplace or import Living UI projects from a ZIP, a local folder, or a git URL. Registers, launches, and verifies imported projects.4---56# Living UI Importer78Bring existing apps into this CraftBot: **marketplace installs** (pre-built9apps from the catalogue), **Living UI project imports** from a ZIP, a local folder10path, or a git URL, and **conversions** of foreign (non-Living-UI) apps —11which are REBUILDS: the original code becomes reference material and the12behavior is re-implemented on this platform. Be honest about that cost13before converting: nothing of the original code runs here.1415## Which path?1617| The user has… | Do this |18|---|---|19| An app name / "what's in the marketplace?" | `living_ui_marketplace_list` → match by name → `living_ui_marketplace_install(app_id=...)` |20| A `.zip`, a project folder path, or a git URL of a Living UI | `living_ui_import(source=...)` — one door for all three |21| A foreign (non-Living-UI) codebase | `living_ui_convert(source=...)` — a full REBUILD; tell the user first |2223## Conversion (foreign apps)2425`living_ui_convert(source=..., name?, description?)` scaffolds a fresh Living UI26project, ships the original source read-only at `reference/source/`,27synthesizes `requirements.md` FROM that source, and dispatches the normal28supervised build to the project's session — you are done after this call;29progress streams to the project tab and the system announces the result.30Pass `description` when the user said what matters ("keep the board, skip31the admin panel"). If the source turns out to BE a Living UI project the32action errors and points you to `living_ui_import`.3334## Marketplace install35361. `living_ui_marketplace_list` — resolve the exact `app_id` (never guess37 ids; match the user's words against names/descriptions).382. `living_ui_marketplace_install(app_id="...", name="...")` — downloads,39 registers, and **launches** the app in one step.403. On success, tell the user the app name and URL. Marketplace apps are41 pre-built and pre-verified upstream — no walk-verify needed.42 NOTE: apps still in the legacy V1 format are rejected with a clear43 error — the platform only runs current-format Living UIs. Tell the user that app hasn't been44 re-published for this version of CraftBot yet; do not improvise a45 workaround.464. On a launch error, treat it like any build failure: read ALL errors,47 fix (the project is a normal Living UI project under the ownership rules),48 `living_ui_notify_ready` again.4950## Project import (ZIP / folder / git URL)51521. `living_ui_import(source="...")` — accepts an absolute `.zip` path, a53 local project folder path, or a git URL (GitHub is downloaded directly;54 other hosts are cloned). Registers a NEW delivered project (fresh id +55 port, shipped credentials stripped, kit re-vendored) and **queues a56 launch-and-verify run in the project's own session** — normally you are57 DONE after this call; the system announces the result.58 Only native Living UI projects are accepted; anything else errors.592. Only if the action says the verify run could not be queued, drive it60 yourself: `living_ui_notify_ready(project_id="<ID>")` then61 `living_ui_walk_verify(project_id="<ID>")` — the app is delivered, so62 these run in staging mode and the walk's clean verdict deploys and63 announces it. Fix any gate errors under the usual ownership rules.64 HONESTY RULE: the import is done ONLY when the verify succeeds.65 (`living_ui_import_zip` still exists as the ZIP-only legacy door.)6667## Adopting an EXTERNAL app (foreign source — runs AS-IS)6869When `living_ui_import` receives a foreign (non-Living-UI) source it70registers it as an EXTERNAL project and dispatches an ADOPTION run with71these steps. The app runs UNCHANGED in its own runtime — never rebuild it,72never edit its code except configuration needed to bind the assigned port.73741. **Inspect** the source at the project path: README, dependency manifests75 (package.json / pyproject.toml / go.mod / Cargo.toml), how it starts,76 which port/env it expects, whether it has a build step.772. **Write the pipeline verbs** into `<project>/craftbot.json` (NOT78 manifest.json — that may be the app's own file). Use `{{PORT}}` where79 the port belongs; the app must bind `127.0.0.1:{{PORT}}`:80 - node: install `npm install --ignore-scripts`; start e.g.81 `npm run dev -- --port {{PORT}} --host 127.0.0.1` or82 `PORT={{PORT}} node server.js` — whatever THIS app's scripts support.83 - python: install `pip install -r requirements.txt`; start e.g.84 `python3 -m uvicorn main:app --port {{PORT}}` / the app's own runner.85 - static: no install; start `python3 -m http.server {{PORT}}` from the86 directory holding index.html.87 - go / rust: build `go build -o app .` / `cargo build --release`; start88 the binary with its port flag/env.89 - health: default `{"strategy": "http_get", "url":90 "http://127.0.0.1:{{PORT}}/"}` — switch to `tcp` or `process_alive`91 for servers that 404 on `/`.923. **Map the app's controllable surface** into `<project>/operations.json`93 (CraftBot's file — a stub exists) so agents can DRIVE the app over the94 A2App protocol. At launch the system substitutes a hidden internal port95 into your `{{PORT}}` verbs and serves the A2App adapter (identity,96 describe, `/api/_ops`, guarded `/api/ops/*`, passthrough for everything97 else) on the ASSIGNED port in front of the app. Probe in order:98 OpenAPI/Swagger spec shipped in the repo → route definitions in the99 code → the README. Declare the app's PUBLIC verbs with typed params;100 each op maps `executor.path` (`/api/ops/<name with dots as slashes>`)101 onto `executor.upstream` — the app's OWN endpoint:102 ```json103 { "name": "todos.create", "description": "Add a todo",104 "params": { "title": { "type": "string", "required": true } },105 "executor": { "type": "http", "method": "POST",106 "path": "/api/ops/todos/create",107 "upstream": { "method": "POST", "path": "/api/todos",108 "body": { "title": "{{title}}" } } } }109 ```110 (`body` template only when the app's field names differ from your param111 names.) Mark anything that deletes/overwrites `"destructive": true`.112 If the app has NO server API (static site, pure client-side SPA), leave113 `operations` empty and say so in `LIVING_UI.md` — never invent verbs,114 never map direct DB writes.1154. **Note what the app is** in `LIVING_UI.md` (one short section — the116 user's reference). Do NOT rewrite `reference/requirements.md`: it is117 pre-written with the adoption scope — verification covers *the app118 launches and its main screen renders*, never the foreign app's internal119 features (you can't fix those and must not try; the app ships as-is,120 quirks included).1215. `living_ui_notify_ready(project_id="<ID>")` — launches via your pipeline122 verbs. Errors come back with `logs/app.log` excerpts; fix the VERBS (or123 port binding config), not the app's features, and retry.1246. `living_ui_ops_verify(project_id="<ID>")` — invokes every125 non-destructive op FOR REAL through the adapter (destructive ops are126 shape-checked, never fired). Fix `executor.upstream` mappings — or127 remove ops that cannot work — and re-run until clean: a mapping that128 does not work must not ship.1297. `living_ui_walk_verify(project_id="<ID>")` — verifies the launch and130 announces. HONESTY RULE: adopted ONLY when this succeeds. If the app131 fundamentally cannot run here (needs a database server, private APIs,132 system deps), STOP and tell the user exactly what is missing — do not133 fake a start command that serves an error page.134135Changes to a running external app apply LIVE (no staging): edit → 136`living_ui_notify_ready` relaunches it.137138## Notes139140- Imported/installed projects are ordinary Living UI projects afterwards:141 operate them via the lui CLI (`ops` / `run` / `data`), modify them via142 the living-ui-modify workflow. External apps speak the same ops surface143 through their adapter — `lui ops` / `lui run` (and raw HTTP with the144 project's `.agent-token`) work against them too; only the `data` verbs145 don't apply (external apps expose operations only, no protocol146 entities — the app's own API passes147 through instead).148- Never edit `frontend/src/kit/`, `manifest.json`, or other system files149 of a Living UI project — the validation gate hashes them.