@wix/himalaya-cli 0.1136.0 → 0.1138.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,222 @@
1
+ # Base44 app context — `himi base44 analyze`
2
+
3
+ `himi base44 analyze` turns a [Base44](https://base44.com) app into an **app book**: one folder
4
+ holding a machine-readable `book.json`, an agent-readable `BOOK.md`, the app's project source and
5
+ screenshots. It is the Base44 counterpart of `himi site analyze` (see `himi docs wix-business-context`),
6
+ and it exists so the coding agent building a Himi app from a Base44 app reads the app's real
7
+ entities, schemas, backend functions and routes instead of guessing them from the rendered site.
8
+
9
+ It is **read-only**. Every call it makes is a GET, and it never writes to the Base44 app.
10
+
11
+ ## Quick start
12
+
13
+ ```bash
14
+ # Visitor pass — no sign-in. What any browser sees at the published URL.
15
+ himi base44 analyze --url https://<tenant>.base44.app --out .himi/base44-book
16
+
17
+ # Owner pass — you are signed in as the app's owner or an editor.
18
+ himi base44 login
19
+ himi base44 whoami
20
+ himi base44 analyze --app-id <24-hex app id> --url https://<tenant>.base44.app --out .himi/base44-book
21
+
22
+ # Print the book itself on stdout (for a script or an agent)
23
+ himi base44 analyze --url https://<tenant>.base44.app --json
24
+ ```
25
+
26
+ Read `BOOK.md` first, then `book.json` for detail. The default folder is `.himi/base44-book/`.
27
+ It sits inside `.himi/`, so `himi push` never archives it as app source.
28
+
29
+ ## The two passes
30
+
31
+ | | Visitor pass | Owner pass |
32
+ |---|---|---|
33
+ | Needs | `--url` | `--app-id` **and** a Base44 session |
34
+ | Identity | app id, name, description, favicon, theme colour, language from the published page | plus the app's name and description from its app record |
35
+ | Routes | router paths found in a self-hosted bundle (a Base44-hosted app loads its pages at run time, so usually none) | path → page component → entities it reads, from the source router |
36
+ | Look | screenshots + colours from the Playwright crawl (the same crawl `site analyze` uses) | same, when `--url` is also given |
37
+ | Entities | — | every entity: JSON schema, field types, required fields, row- and field-level access rules, up to `--sample` redacted rows |
38
+ | Functions | — | every backend function: name, entry file, `http` (it serves requests itself) or `invoke`, HTTP methods it branches on, scheduled automations |
39
+ | Agents, connectors | — | agent names, descriptions and tools; connector **types, scopes and status only** |
40
+ | Secrets | — | secret **names** only |
41
+ | Auth | — | visibility (public / private / workspace) and enabled sign-in providers |
42
+ | Source | — | the project files under `<out>/source/`, filtered (below) |
43
+
44
+ **The owner pass is never inferred.** A URL-only run stays a visitor pass even when you are signed
45
+ in and the published page names its app id. Only an explicit `--app-id` asks for the owner pass,
46
+ and without a session that is refused with exit code 2 before anything is read.
47
+
48
+ **Nothing is fatal.** When a chapter cannot be read, the run still writes the book and lists the
49
+ chapter in `gaps[]` with the reason. Common reasons: a refused read (your role can view the app but
50
+ not edit it), no browser for the crawl, or an app id the published page does not carry. This is how
51
+ a viewer's run looks: the visitor pass plus whatever the role could read, with every refused chapter
52
+ listed in `gaps[]`.
53
+
54
+ ## Signing in
55
+
56
+ | Mode | How | Stored where |
57
+ |---|---|---|
58
+ | Interactive | `himi base44 login` runs Base44's device sign-in. You approve a code in the browser, and only read access (`apps:read`) is asked for | `~/.himi/base44/session.json`, mode 0600 |
59
+ | Reuse the Base44 CLI's session | `himi base44 login --from-base44-cli` imports what `npx base44 login` stored | the same file |
60
+ | CI | `BASE44_ACCESS_TOKEN=<token>` in the environment | nowhere, it is read from the environment |
61
+
62
+ `BASE44_ACCESS_TOKEN` wins over a stored session. `himi base44 whoami` says which one is in effect
63
+ (`source: "env" | "session"`), who it belongs to and when it expires. It never prints the token.
64
+ `himi base44 logout` deletes the stored session. A stored session that has expired is refreshed
65
+ once, automatically, with its refresh token. The environment token is used exactly as given.
66
+ `BASE44_API_URL` points every call at another Base44 API host (the default is
67
+ `https://app.base44.com`).
68
+
69
+ The session is a user credential. It never goes into the repo or the book.
70
+
71
+ ## Options
72
+
73
+ | Flag | Meaning |
74
+ |---|---|
75
+ | `--url <https://…>` | The published app. Runs the visitor pass. |
76
+ | `--app-id <id>` | The app id (24 hex characters, as in `app.base44.com/apps/<id>`). Runs the owner pass. |
77
+ | `--out <dir>` | Book folder. Default `.himi/base44-book`. It must be new, a previous app book (whose `source/` and `screenshots/` are replaced), or free of `book.json`, `BOOK.md`, `source/` and `screenshots/`. Anything else is refused rather than overwritten. |
78
+ | `--sample <n>` | Sample rows per entity, 0–100. Default 5. `--sample 0` reads no rows. |
79
+ | `--json` | Print the book on stdout instead of the summary. |
80
+ | `--no-browser` | Skip the Playwright crawl (recorded as a `look` gap). |
81
+
82
+ The MCP server (`himi mcp`) exposes the same collector as the tool `himi_base44_analyze`
83
+ (`url`, `appId`, `out`, `sample`). It returns the book as `structuredContent`. Toward Base44 it is
84
+ read-only, but it writes the book folder, so it is not annotated read-only to the host.
85
+
86
+ ## The book (`book.json`, schema v1)
87
+
88
+ ```jsonc
89
+ {
90
+ "schemaVersion": 1,
91
+ "kind": "base44-app-book",
92
+ "generatedAt": "2026-09-30T12:00:00.000Z",
93
+ "mode": "owner", // or "visitor"
94
+ "input": { "url": "https://fixit.base44.app/", "appId": "68c0…cdef", "sample": 5 },
95
+ "identity": { "appId": "68c0…cdef", "appIdSource": "input", "name": "FixIt Tracker",
96
+ "faviconUrl": "…/favicon.png", "colors": { "theme-color": "#4f46e5" }, "lang": "en" },
97
+ "routes": [
98
+ { "path": "/", "component": "Dashboard", "file": "src/pages/Dashboard.jsx",
99
+ "entities": ["Job"], "source": "project-files" }
100
+ ],
101
+ "entities": [
102
+ { "name": "Job", "fields": [{ "name": "status", "type": "string", "required": true,
103
+ "enum": ["open", "done"] }],
104
+ "required": ["title", "status"], "schema": { /* the JSON Schema, verbatim */ },
105
+ "rls": { "read": { "created_by": "{{user.email}}" }, "delete": false },
106
+ "sampleRows": [{ "title": "Fix phone", "created_by": "[redacted-email]" }],
107
+ "file": "base44/entities/Job.jsonc", "source": "project-files" }
108
+ ],
109
+ "functions": [
110
+ { "name": "sendReport", "sourcePath": "base44/functions/sendReport/entry.ts", "kind": "http",
111
+ "methods": ["POST"], "invoke": "base44.functions.invoke(\"sendReport\", payload)",
112
+ "automations": [{ "name": "weekly", "type": "scheduled", "schedule": "0 9 * * 1" }] }
113
+ ],
114
+ "agents": [{ "name": "job_helper", "tools": [{ "entity": "Job", "operations": ["read"] }] }],
115
+ "connectors": [{ "type": "gmail", "scopes": ["…/gmail.send"], "status": "active" }],
116
+ "secrets": { "names": ["STRIPE_KEY"] },
117
+ "auth": { "visibility": "private", "requiresLogin": true, "providers": ["email-password", "google"] },
118
+ "look": { "pages": [ /* the crawl's pages + screenshots */ ], "theme": { "colors": {}, "fonts": {} } },
119
+ "source": { "root": "source", "files": 42, "denied": [".env.local"],
120
+ "secretFlagged": [{ "path": "src/api/keys.js", "reason": "a GitHub token" }] },
121
+ "gaps": [{ "chapter": "look", "reason": "playwright_not_installed: …" }]
122
+ }
123
+ ```
124
+
125
+ Every fact carries a `source`: `published-spa` (any visitor could see it), `project-files` (the
126
+ app's own project files) or `rest` (the owner-authenticated API). Treat an operation with no rule as
127
+ **open**: the Base44 CLI's own local server allows an operation whose rule is missing, `null` or
128
+ empty.
129
+
130
+ `BOOK.md` is the same content, summarised for an agent. For each entity it lists the worker calls
131
+ the Himi app would make through the `@himalaya/base44` capability: `base44.entities.<Name>.list()`,
132
+ `.filter({…})`, `.get(id)`, and the writes (`create`, `update`, `delete`) that the entity's rules do
133
+ not forbid outright.
134
+
135
+ ## What is deliberately never collected
136
+
137
+ - **Secret values.** Only secret names are read. The secrets listing returns a map, and its values
138
+ are dropped the moment it arrives.
139
+ - **Connector tokens and account details.** A connector is its type, scopes and status. The
140
+ connected account's email and any other key are dropped field by field, not filtered afterwards.
141
+ - **Your session.** It stays in `~/.himi/base44/` or the environment and appears in no output.
142
+ - **People's contact details in sample rows.** Emails and phone numbers are replaced with
143
+ `[redacted-email]` / `[redacted-phone]`. A column whose name says credential (`password`,
144
+ `token`, `api_key`, `secret`, `session`, …) loses its value outright, and every token-shaped
145
+ string (JWTs, Base44 workspace keys, GitHub/Slack/AWS/Stripe/Google keys, bearer headers, private
146
+ keys) becomes `[redacted-token]`.
147
+ - **Credential files in the source.** The project files pass through the same deny-list and secret
148
+ scan `himi push` uses for its source archive, and the scan is widened by every token shape listed
149
+ above. Dotenv files, key material, `.git`, `node_modules` and build output are dropped (listed in
150
+ `source.denied`). A file whose *content* looks like a credential (a hardcoded `sk_live_…` in a
151
+ function, say) is named in `source.secretFlagged` with the reason, and its bytes are never
152
+ written.
153
+ - **A copy of the app.** See below.
154
+
155
+ As a last check, the writer scans the serialized book and `BOOK.md` again, and refuses to write
156
+ either if anything token-shaped survived redaction.
157
+
158
+ ## What Base44 exposes
159
+
160
+ This section records what the collector relies on. It was read from the source of the official
161
+ Base44 CLI (`base44` on npm, v0.1.24, MIT), not guessed.
162
+
163
+ **Project layout.** An app is a Vite + React SPA plus a `base44/` folder. `base44/config.jsonc`
164
+ names the resource directories, each relative to `base44/`. Their defaults are `entities/`,
165
+ `functions/`, `agents/`, `connectors/` and `auth/`, and each holds `.json` or `.jsonc` files:
166
+
167
+ | Path | Holds |
168
+ |---|---|
169
+ | `base44/entities/<Name>.jsonc` | a JSON Schema object with `name`, `properties`, `required`, `rls` (`read`, `create`, `update`, `delete`, `write`). Each rule is `true`, `false` or a condition such as `{ "created_by": "{{user.email}}" }`. Fields may carry their own `rls`. |
170
+ | `base44/functions/<name>/function.jsonc` | `name`, `entry` (relative to that folder), `automations` (scheduled or entity-triggered). A zero-config function is just `functions/<name>/entry.{js,ts}`. Functions run on Deno. |
171
+ | `base44/agents/<name>.jsonc` | `name`, `description`, `instructions`, `tool_configs` (`entity_name` + `allowed_operations`, or `function_name`) |
172
+ | `base44/connectors/<type>.jsonc` | `type` (`gmail`, `slack`, …) and `scopes` |
173
+ | `base44/auth/*.jsonc` | `enableUsernamePassword`, `enableGoogleLogin`, `enableMicrosoftLogin`, `enableFacebookLogin`, `enableAppleLogin`, `enableSSOLogin`, … |
174
+
175
+ Apps built in the Base44 editor before that layout keep entities at the project root
176
+ (`entities/*.json`) and one file per function (`functions/<name>.js`). The collector reads both
177
+ places. Pages are routed either by a React Router tree (`<Route path=… element={<Page/>}>`) or by
178
+ Base44's page registry (`PAGES = { Name: Component }`, routed at `/<Name>`, with the `mainPage` at
179
+ `/`).
180
+
181
+ **API.** Everything is under `https://app.base44.com` (or `BASE44_API_URL`) and authenticated with
182
+ `Authorization: Bearer <access token>`:
183
+
184
+ | Request | Returns | Used for |
185
+ |---|---|---|
186
+ | `GET /api/apps/<id>` | `name`, `user_description`, `public_settings` (`public_without_login`, `private_with_login`, `workspace_with_login`), `auth_config` | identity, auth |
187
+ | `GET /api/apps/<id>/eject` | the project as a tarball | source, entities, functions, agents, connectors, routes |
188
+ | `GET /api/apps/<id>/backend-functions` | `{ functions: [{ name, entry, files, automations }] }` | functions the download lacks (their `files` are not copied) |
189
+ | `GET /api/apps/<id>/agent-configs` | `{ items: [agent config], total }` | agents the download lacks |
190
+ | `GET /api/apps/<id>/external-auth/list` | `{ integrations: [{ integration_type, status, scopes, user_email }] }` | connectors (`user_email` dropped) |
191
+ | `GET /api/apps/<id>/secrets` | a name → value map | secret **names** |
192
+ | `GET /api/apps/<id>/entities/<Name>?limit=<n>` | rows | sample rows |
193
+
194
+ There is no read endpoint for entity schemas (the CLI only pushes them), so schemas come from the
195
+ downloaded project alone. When the download is refused, the entities chapter is a gap.
196
+
197
+ **Why the collector does not run `base44 eject`.** `eject` downloads the code with
198
+ `GET /api/apps/<id>/eject`. It then creates a **new app** named "<name> Copy" (`POST /api/apps`),
199
+ writes that new app's id into the download, and offers to deploy it. That is a write to your Base44
200
+ account. The collector makes the same download request and stops there.
201
+
202
+ **Sign-in.** Base44 uses the OAuth 2.0 device flow for its CLI. `POST /oauth/device/code` with
203
+ `client_id: base44_cli` returns a user code and a verification URL. `POST /oauth/token`
204
+ (`grant_type=urn:ietf:params:oauth:grant-type:device_code`) is polled until the user approves.
205
+ `POST /oauth/token` with `grant_type=refresh_token` renews a session, and `GET /oauth/userinfo`
206
+ names the user. The Base44 CLI keeps its own session in `~/.base44/auth/auth.json`. himi keeps its
207
+ own, and reads the Base44 CLI's only on `--from-base44-cli`.
208
+
209
+ **Published apps.** An app published on `<tenant>.base44.app` is served by Base44's platform shell.
210
+ Its HTML carries the app's identity: `og:site_name`, description, favicon, `theme-color`, and the
211
+ app id on the Base44 badge tag (`<script data-app-id="<id>" …>`). The app's own page code loads at
212
+ run time, so the visitor pass usually finds **no routes** there and says so in `gaps[]`. The owner
213
+ pass reads them from the source router instead. A self-hosted build of an ejected app is a plain
214
+ Vite bundle: the app id is baked in (`VITE_BASE44_APP_ID`) and the router's `path` strings survive
215
+ minification, so the visitor pass finds both. The visitor pass reads the HTML and up to four of its
216
+ same-origin scripts, through the same SSRF- and DNS-rebinding-guarded fetch `himi site analyze`
217
+ uses. A third-party script tag is never followed.
218
+
219
+ ## Not in scope
220
+
221
+ - Generating the Himi app from the book. That is the agent's job.
222
+ - Writing anything back to the Base44 app.
@@ -77,6 +77,7 @@ runs a session with it.
77
77
  | `himi_login` | Open a browser window where the user signs in to Wix, so publishing works with no terminal. It returns the sign-in link at once; call it again to see whether the sign-in finished. |
78
78
  | `himi_push` | Publish a **draft**: private to the owner, viewable by preview link and in Himi Player, not live. |
79
79
  | `himi_share`, `himi_preview_links` | Share links for a published release. |
80
+ | `himi_base44_analyze` | Read a Base44 app into an app book (read-only) and return it as structured content — `himi docs base44-app-context`. |
80
81
 
81
82
  Each tool acts on the agent's workspace folder unless it is given a `dir`.
82
83
 
package/guides/index.json CHANGED
@@ -208,6 +208,12 @@
208
208
  "category": "Wix SDK",
209
209
  "file": "wix-business-context.md"
210
210
  },
211
+ {
212
+ "id": "base44-app-context",
213
+ "title": "Base44 app context (himi base44 analyze)",
214
+ "category": "CLI & Loop",
215
+ "file": "base44-app-context.md"
216
+ },
211
217
  {
212
218
  "id": "headless-business-to-himi-app",
213
219
  "title": "From Wix Headless / Back Office → a native Himi app",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wix/himalaya-cli",
3
- "version": "0.1136.0",
3
+ "version": "0.1138.0",
4
4
  "type": "module",
5
5
  "description": "himi — the Himalaya authoring CLI. Build a Tier-5 content package on your own machine, push it to the production serve as a draft, preview it on web + Himi Player, and read worker logs back — the remote dev loop. Wraps @himalaya/serve-cli for transport.",
6
6
  "keywords": [
@@ -67,5 +67,5 @@
67
67
  "artifactId": "himalaya-cli"
68
68
  }
69
69
  },
70
- "falconPackageHash": "0c3678539afa365f0de04b4c967184453cab4af35a8dffde750e6583"
70
+ "falconPackageHash": "654aea685a4320550fc30f32aaa3e23bd890f63b8e281ce00aeb794b"
71
71
  }