@zoahhq/cli 0.1.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.
- package/LICENSE +190 -0
- package/README.md +348 -0
- package/dist/cli.mjs +101429 -0
- package/package.json +56 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
6
|
+
|
|
7
|
+
1. Definitions.
|
|
8
|
+
|
|
9
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
10
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
11
|
+
|
|
12
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
13
|
+
the copyright owner that is granting the License.
|
|
14
|
+
|
|
15
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
16
|
+
other entities that control, are controlled by, or are under common
|
|
17
|
+
control with that entity. For the purposes of this definition,
|
|
18
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
19
|
+
direction or management of such entity, whether by contract or
|
|
20
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
21
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
22
|
+
|
|
23
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
24
|
+
exercising permissions granted by this License.
|
|
25
|
+
|
|
26
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
27
|
+
including but not limited to software source code, documentation
|
|
28
|
+
source, and configuration files.
|
|
29
|
+
|
|
30
|
+
"Object" form shall mean any form resulting from mechanical
|
|
31
|
+
transformation or translation of a Source form, including but
|
|
32
|
+
not limited to compiled object code, generated documentation,
|
|
33
|
+
and conversions to other media types.
|
|
34
|
+
|
|
35
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
36
|
+
Object form, made available under the License, as indicated by a
|
|
37
|
+
copyright notice that is included in or attached to the work
|
|
38
|
+
(an example is provided in the Appendix below).
|
|
39
|
+
|
|
40
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
41
|
+
form, that is based on (or derived from) the Work and for which the
|
|
42
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
43
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
44
|
+
of this License, Derivative Works shall not include works that remain
|
|
45
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
46
|
+
the Work and Derivative Works thereof.
|
|
47
|
+
|
|
48
|
+
"Contribution" shall mean any work of authorship, including
|
|
49
|
+
the original version of the Work and any modifications or additions
|
|
50
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
51
|
+
submitted to the Licensor for inclusion in the Work by the copyright owner
|
|
52
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
53
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
54
|
+
means any form of electronic, verbal, or written communication sent
|
|
55
|
+
to the Licensor or its representatives, including but not limited to
|
|
56
|
+
communication on electronic mailing lists, source code control systems,
|
|
57
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
58
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
59
|
+
excluding communication that is conspicuously marked or otherwise
|
|
60
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
61
|
+
|
|
62
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
63
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
64
|
+
subsequently incorporated within the Work.
|
|
65
|
+
|
|
66
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
67
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
68
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
69
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
70
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
71
|
+
Work and such Derivative Works in Source or Object form.
|
|
72
|
+
|
|
73
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
74
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
75
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
76
|
+
(except as stated in this section) patent license to make, have made,
|
|
77
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
78
|
+
where such license applies only to those patent claims licensable
|
|
79
|
+
by such Contributor that are necessarily infringed by their
|
|
80
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
81
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
82
|
+
institute patent litigation against any entity (including a
|
|
83
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
84
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
85
|
+
or contributory patent infringement, then any patent licenses
|
|
86
|
+
granted to You under this License for that Work shall terminate
|
|
87
|
+
as of the date such litigation is filed.
|
|
88
|
+
|
|
89
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
90
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
91
|
+
modifications, and in Source or Object form, provided that You
|
|
92
|
+
meet the following conditions:
|
|
93
|
+
|
|
94
|
+
(a) You must give any other recipients of the Work or
|
|
95
|
+
Derivative Works a copy of this License; and
|
|
96
|
+
|
|
97
|
+
(b) You must cause any modified files to carry prominent notices
|
|
98
|
+
stating that You changed the files; and
|
|
99
|
+
|
|
100
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
101
|
+
that You distribute, all copyright, patent, trademark, and
|
|
102
|
+
attribution notices from the Source form of the Work,
|
|
103
|
+
excluding those notices that do not pertain to any part of
|
|
104
|
+
the Derivative Works; and
|
|
105
|
+
|
|
106
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
107
|
+
distribution, then any Derivative Works that You distribute must
|
|
108
|
+
include a readable copy of the attribution notices contained
|
|
109
|
+
within such NOTICE file, excluding those notices that do not
|
|
110
|
+
pertain to any part of the Derivative Works, in at least one
|
|
111
|
+
of the following places: within a NOTICE text file distributed
|
|
112
|
+
as part of the Derivative Works; within the Source form or
|
|
113
|
+
documentation, if provided along with the Derivative Works; or,
|
|
114
|
+
within a display generated by the Derivative Works, if and
|
|
115
|
+
wherever such third-party notices normally appear. The contents
|
|
116
|
+
of the NOTICE file are for informational purposes only and
|
|
117
|
+
do not modify the License. You may add Your own attribution
|
|
118
|
+
notices within Derivative Works that You distribute, alongside
|
|
119
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
120
|
+
that such additional attribution notices cannot be construed
|
|
121
|
+
as modifying the License.
|
|
122
|
+
|
|
123
|
+
You may add Your own copyright statement to Your modifications and
|
|
124
|
+
may provide additional or different license terms and conditions
|
|
125
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
126
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
127
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
128
|
+
the conditions stated in this License.
|
|
129
|
+
|
|
130
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
131
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
132
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
133
|
+
this License, without any additional terms or conditions.
|
|
134
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
135
|
+
the terms of any separate license agreement you may have executed
|
|
136
|
+
with Licensor regarding such Contributions.
|
|
137
|
+
|
|
138
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
139
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
140
|
+
except as required for reasonable and customary use in describing the
|
|
141
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
142
|
+
|
|
143
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
144
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
145
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
146
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
147
|
+
implied, including, without limitation, any warranties or conditions
|
|
148
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
149
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
150
|
+
appropriateness of using or redistributing the Work and assume any
|
|
151
|
+
risks associated with Your exercise of permissions under this License.
|
|
152
|
+
|
|
153
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
154
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
155
|
+
unless required by applicable law (such as deliberate and grossly
|
|
156
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
157
|
+
liable to You for damages, including any direct, indirect, special,
|
|
158
|
+
incidental, or consequential damages of any character arising as a
|
|
159
|
+
result of this License or out of the use or inability to use the
|
|
160
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
161
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
162
|
+
other commercial damages or losses), even if such Contributor
|
|
163
|
+
has been advised of the possibility of such damages.
|
|
164
|
+
|
|
165
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
166
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
167
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
168
|
+
or other liability obligations and/or rights consistent with this
|
|
169
|
+
License. However, in accepting such obligations, You may act only
|
|
170
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
171
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
172
|
+
defend, and hold each Contributor harmless for any liability
|
|
173
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
174
|
+
of your accepting any such warranty or additional liability.
|
|
175
|
+
|
|
176
|
+
END OF TERMS AND CONDITIONS
|
|
177
|
+
|
|
178
|
+
Copyright 2026 Zoah Inc.
|
|
179
|
+
|
|
180
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
181
|
+
you may not use this file except in compliance with the License.
|
|
182
|
+
You may obtain a copy of the License at
|
|
183
|
+
|
|
184
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
185
|
+
|
|
186
|
+
Unless required by applicable law or agreed to in writing, software
|
|
187
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
188
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
189
|
+
See the License for the specific language governing permissions and
|
|
190
|
+
limitations under the License.
|
package/README.md
ADDED
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="https://zoah.com/assets/images/opacity-mark.svg" alt="Zoah" width="84" />
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
# @zoahhq/cli
|
|
6
|
+
|
|
7
|
+
The Zoah CLI. Sign in from your terminal, import first-party React components into Zoah, and optionally rewrite local imports.
|
|
8
|
+
|
|
9
|
+
Published to npm as [`@zoahhq/cli`](https://www.npmjs.com/package/@zoahhq/cli). The package installs the `zoah` command.
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install -g @zoahhq/cli
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Verify the installation with `zoah --version`. The package also provides `opacity` as a temporary compatibility alias.
|
|
18
|
+
|
|
19
|
+
## Quick start
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
zoah login # sign in via your browser
|
|
23
|
+
zoah import # scan ./src, import and publish your components
|
|
24
|
+
zoah import --swap # also rewrite local imports to the published package
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Commands
|
|
28
|
+
|
|
29
|
+
### `zoah login`
|
|
30
|
+
|
|
31
|
+
Opens your browser to the Zoah sign-in flow. It saves the credential with `chmod 600`. Other commands reuse its token and base URL.
|
|
32
|
+
|
|
33
|
+
Credentials are layered (same precedence as `git config local > global`):
|
|
34
|
+
|
|
35
|
+
- **Default, global:** writes `~/.zoah/credentials.json`. One sign-in covers every Zoah project on this machine.
|
|
36
|
+
- **`--local`:** writes `<cwd>/.zoah/credentials.json`. Use this for a project-specific account or instance. The CLI also writes `<cwd>/.zoah/.gitignore`.
|
|
37
|
+
|
|
38
|
+
Reads always check local first; falls back to global.
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
zoah login # global default
|
|
42
|
+
zoah login --local # project-specific override
|
|
43
|
+
zoah login --base-url https://zoah.example.com
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
The CLI uses `ZOAH_BASE_URL` when it is set. Otherwise, it uses `https://zoah.com`. `OPACITY_BASE_URL` remains a compatibility fallback.
|
|
47
|
+
|
|
48
|
+
### `zoah logout`
|
|
49
|
+
|
|
50
|
+
By default, this removes the **active** credentials. It removes project-local credentials when they exist, and otherwise removes global credentials.
|
|
51
|
+
|
|
52
|
+
- `zoah logout`: clear the active layer only.
|
|
53
|
+
- `zoah logout --global`: remove `~/.zoah/credentials.json` even when a project-local override is also present.
|
|
54
|
+
|
|
55
|
+
To clear both, run logout twice.
|
|
56
|
+
|
|
57
|
+
### `zoah whoami`
|
|
58
|
+
|
|
59
|
+
Prints the active user, the source credentials file, and the base URL. Use this when project credentials hide the global token.
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
zoah whoami
|
|
63
|
+
# Signed in as you@example.com (global).
|
|
64
|
+
# Source: ~/.zoah/credentials.json
|
|
65
|
+
# Base URL: https://zoah.com
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### `zoah mcp`
|
|
69
|
+
|
|
70
|
+
Serves the Zoah Action API over MCP (stdio) so a coding agent (Claude Code,
|
|
71
|
+
Codex, Cursor, or any MCP-capable harness) can read and edit a Zoah project
|
|
72
|
+
from your terminal session. The agent gets the same verbs the designer uses:
|
|
73
|
+
nodes, pages, components, slots, variants, variables, themes, breakpoints and
|
|
74
|
+
events, plus branch and pull-request tools.
|
|
75
|
+
|
|
76
|
+
#### Set it up
|
|
77
|
+
|
|
78
|
+
**1. Sign in once.** The MCP server reuses the credential `zoah login`
|
|
79
|
+
writes. It never asks the agent for one.
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
npm i -g @zoahhq/cli
|
|
83
|
+
zoah login
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
**2. Add the server to your harness.** The guided installer is the fast path:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
zoah mcp init
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
It asks four things:
|
|
93
|
+
|
|
94
|
+
| Question | Options | Pick this when |
|
|
95
|
+
| ------------------ | ----------------------------------------------------------- | ------------------------------------------------------------- |
|
|
96
|
+
| Which harness | Claude Code, Cursor, VS Code, Codex, or print the snippet | Pick the harness that will use Zoah |
|
|
97
|
+
| How to launch | `npx -y @zoahhq/cli@latest`, or the global `zoah` binary | `npx` for a config you check in, so teammates need no install |
|
|
98
|
+
| What agents may do | full access, or `--read-only` | read-only serves the query verbs alone |
|
|
99
|
+
| Default project | the repo's linked project from `.zoah/config.json`, or none | baking it in means `connect` needs no ids |
|
|
100
|
+
|
|
101
|
+
It merges into an existing config without disturbing other servers. Every answer
|
|
102
|
+
is also a flag (`--harness`, `--global-command`, `--read-only`, `--project`,
|
|
103
|
+
`--print`) for scripted setup.
|
|
104
|
+
|
|
105
|
+
To write the entry by hand instead:
|
|
106
|
+
|
|
107
|
+
```json
|
|
108
|
+
{
|
|
109
|
+
"mcpServers": {
|
|
110
|
+
"zoah": {
|
|
111
|
+
"command": "npx",
|
|
112
|
+
"args": ["-y", "@zoahhq/cli@latest", "mcp"]
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
**3. Point the agent at a project.** In the agent session:
|
|
119
|
+
|
|
120
|
+
```
|
|
121
|
+
connect(project: "my-project")
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
`connect` signs in when the credential is missing or expired. It returns a URL
|
|
125
|
+
for you to approve in a browser, then resolves the project by slug, name or id
|
|
126
|
+
and opens the session. Give it `branch` to pick one. With no branch it creates a
|
|
127
|
+
fresh `agent/<timestamp>` branch off main, so an agent's edits stay reviewable
|
|
128
|
+
rather than landing on main.
|
|
129
|
+
|
|
130
|
+
**4. Check it worked.** `status` reports the connected project, the branch, and
|
|
131
|
+
workspace role. It also reports credential health. `whoami` reports the
|
|
132
|
+
identity, role, and instance.
|
|
133
|
+
|
|
134
|
+
#### What the agent gets
|
|
135
|
+
|
|
136
|
+
The server exposes each Action API verb that can run in a headless project
|
|
137
|
+
session without direct human confirmation. Confirmation actions stay in the
|
|
138
|
+
Zoah app. The server replaces renderer-only and workspace-agent verbs with
|
|
139
|
+
the session tools below.
|
|
140
|
+
|
|
141
|
+
| Group | Tools |
|
|
142
|
+
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
|
|
143
|
+
| Session | `connect`, `status`, `pullEvents`, `disconnect`, `whoami`, `logout`, `describeProperties` |
|
|
144
|
+
| Workspaces and projects | `listWorkspaces`, `createWorkspace`, `listProjects`, `createProject`, `updateProject` |
|
|
145
|
+
| Branches | `listBranches`, `createBranch` |
|
|
146
|
+
| Pull requests | `createPullRequest`, `getPullRequest`, `updatePullRequest`, `commentOnPullRequest` |
|
|
147
|
+
| Canvas | one per applicable Action API verb for nodes, pages, components, slots, variants, variables, themes, breakpoints, events, and queries |
|
|
148
|
+
|
|
149
|
+
Two properties are worth knowing. Mutation tools return only after the sync
|
|
150
|
+
gateway acks the write, so a returned success means persisted, not queued. And
|
|
151
|
+
the server does not provide branch, project, or workspace deletion.
|
|
152
|
+
`pullEvents` returns structured rejection and collaborator action details. It
|
|
153
|
+
also returns merge summaries. Sync and cache signals mean the agent should
|
|
154
|
+
re-query after reconnect catch-up.
|
|
155
|
+
For a read role, the server hides mutation tools and connects to an existing
|
|
156
|
+
branch. It does not create an agent branch.
|
|
157
|
+
Deleting one is irreversible from here, and it is easy for an agent to reach for
|
|
158
|
+
while recovering from its own mistake. That stays in the web UI, where a person
|
|
159
|
+
can see what they are about to destroy.
|
|
160
|
+
|
|
161
|
+
#### Working against local dev
|
|
162
|
+
|
|
163
|
+
The published bundle targets `https://zoah.com`. For a local instance, link
|
|
164
|
+
the checkout instead of installing from npm, then sign in against it:
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
zoah login --base-url http://localhost:5070
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
`connect` accepts a `baseUrl` parameter, and it wins over the saved
|
|
171
|
+
credential. It exists for the clean-workspace case: with no credential file
|
|
172
|
+
yet, the built-in default is a guess, and on a multi-instance dev machine it
|
|
173
|
+
is usually the wrong port. The choice is saved, so later calls agree - a
|
|
174
|
+
session cannot silently straddle two instances, and `status` reports a
|
|
175
|
+
mismatch between the open session and the credential on disk
|
|
176
|
+
(`baseUrlMismatch`) rather than letting one develop unnoticed. Build and link
|
|
177
|
+
steps are in [DEVELOPMENT.md](./DEVELOPMENT.md).
|
|
178
|
+
|
|
179
|
+
Design and details: [docs/action-api-mcp.md](docs/action-api-mcp.md).
|
|
180
|
+
|
|
181
|
+
### `zoah import [path]`
|
|
182
|
+
|
|
183
|
+
Scans first-party React components and sends an import payload to Zoah. It publishes a package and writes project state under `.zoah/`. The default path is `src`.
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
zoah import # scans ./src
|
|
187
|
+
zoah import src/components # scope to a subdirectory
|
|
188
|
+
zoah import --swap # also rewrite local imports after publish
|
|
189
|
+
zoah import --project-name my-ui # override the first project name
|
|
190
|
+
zoah import --branch main # target a specific branch
|
|
191
|
+
zoah import --debug # also write .zoah/debug/payload.json
|
|
192
|
+
zoah import --print-issues warn # print issue details at or above this level
|
|
193
|
+
zoah import --dry-run # preview locally without an API call
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
The first import creates a project and saves its IDs to `.zoah/config.json`. Later imports use the same project.
|
|
197
|
+
|
|
198
|
+
Notable flags:
|
|
199
|
+
|
|
200
|
+
- `--swap`: runs `zoah swap` after a successful import.
|
|
201
|
+
- `--project-name <name>`: sets the first project name. Later imports use the project ID in `.zoah/config.json`.
|
|
202
|
+
- `--branch <name>`: defaults to the project's saved branch (usually `main`).
|
|
203
|
+
- `--base-url <url>`: overrides the URL saved at login.
|
|
204
|
+
- `--print-issues <level>`: also prints full details for every issue at or above `info | warn | error`.
|
|
205
|
+
- `--dry-run`: runs the local pipeline without publishing. It still writes `.zoah/debug/issues.json`.
|
|
206
|
+
|
|
207
|
+
The CLI skips components imported directly by an entry file (`src/main.tsx`, `src/index.tsx`, etc.). Translating them would blank the running app.
|
|
208
|
+
|
|
209
|
+
### `zoah preflight [path]`
|
|
210
|
+
|
|
211
|
+
Runs the import pipeline locally without publishing. It writes `.zoah/debug/issues.json` but does not call the API or change project state.
|
|
212
|
+
|
|
213
|
+
- preview what a real `zoah import` would do on a checkout you have not published,
|
|
214
|
+
- audit which codes a codebase trips before deciding whether to upgrade the CLI,
|
|
215
|
+
- regenerate the issues snapshot after a source change without re-publishing.
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
zoah preflight # scans ./src
|
|
219
|
+
zoah preflight src/components # scope to a subdirectory
|
|
220
|
+
zoah preflight --print-issues warn # also print issue details
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
The full code list, grouped by what the swap actually does (cleanly / visibly degrades / refuses), is documented in `docs/supported-shapes.md` in the repo.
|
|
224
|
+
|
|
225
|
+
### `zoah swap [path]`
|
|
226
|
+
|
|
227
|
+
Installs the published Zoah package and wraps your local components. It reads `.zoah/components.json` and `.zoah/manifest.json` from `zoah import`.
|
|
228
|
+
|
|
229
|
+
```bash
|
|
230
|
+
zoah swap # install the package and rewrite imports
|
|
231
|
+
zoah swap --dry-run # print diffs only
|
|
232
|
+
zoah swap --print-issues warn # print issue details
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
The dry-run mode is the safe way to preview what swap will do before letting it touch your source tree.
|
|
236
|
+
|
|
237
|
+
#### Authenticated installs (`.npmrc` management)
|
|
238
|
+
|
|
239
|
+
Published packages carry the project's privacy. CLI imports are private by
|
|
240
|
+
default, so the install needs credentials. When the repo's `.npmrc` (and your
|
|
241
|
+
`~/.npmrc`) has no token for the Zoah registry host, swap mints a registry
|
|
242
|
+
API key for the project's organization and manages the file for you:
|
|
243
|
+
|
|
244
|
+
- The key is requested through the authenticated import API, requires write
|
|
245
|
+
access in the project's organization, and is **reused** on repeat runs (one
|
|
246
|
+
key per project + user, not one per invocation). It appears in Project
|
|
247
|
+
Settings → Package as `CLI import · <project>` and is revocable there.
|
|
248
|
+
- The token line (`//<host>/:_authToken=…`) is written to `<repo>/.npmrc`
|
|
249
|
+
with owner-only permissions (0600), and `.npmrc` is added to `.gitignore`.
|
|
250
|
+
- **If `.npmrc` is already tracked by git**, `.gitignore` cannot protect it.
|
|
251
|
+
swap prints a loud warning telling you to `git rm --cached .npmrc` before
|
|
252
|
+
your next commit.
|
|
253
|
+
- When signed out, the install continues without authentication. Public
|
|
254
|
+
packages still work. A private package install returns the registry's 401.
|
|
255
|
+
|
|
256
|
+
## Reading the import output
|
|
257
|
+
|
|
258
|
+
After each `zoah import` run, the CLI prints a status table for each component:
|
|
259
|
+
|
|
260
|
+
```
|
|
261
|
+
Component Import Swap
|
|
262
|
+
──────────────────── ────── ────
|
|
263
|
+
Avatar █ █
|
|
264
|
+
Button █ █ 1 error
|
|
265
|
+
Card █ ░ █ 2 warnings, 1 info
|
|
266
|
+
ToastProvider █ █
|
|
267
|
+
|
|
268
|
+
File-level:
|
|
269
|
+
src/utils.ts █ 1 warning
|
|
270
|
+
src/App.tsx ░ 1 info
|
|
271
|
+
|
|
272
|
+
1 error, 2 warnings, 1 info. See .zoah/debug/issues.json
|
|
273
|
+
|
|
274
|
+
View in Zoah: https://zoah.com/projects/<id>/design
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
Each cell is two glyphs: the **severity slot** on the left summarises the worst outcome for that (row, phase) pair, and the **info-note slot** on the right lights up when any info-level notes accrued.
|
|
278
|
+
|
|
279
|
+
| Cell | Meaning |
|
|
280
|
+
| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
281
|
+
| `█` green | Phase ran cleanly (component imported successfully, no issues). |
|
|
282
|
+
| `█` yellow | Phase ran with at least one warning. |
|
|
283
|
+
| `█` red | Phase ran with at least one error. |
|
|
284
|
+
| `░` dim | On a component row, phase didn't reach this row (e.g. swap blocked by an import error). On a File-level row, phase ran with only info-level notes (e.g. an entry file that was intentionally skipped). |
|
|
285
|
+
| blank | On a File-level row, the phase did not touch this file. Sparse rows leave unused phases empty. |
|
|
286
|
+
| trailing `░` | The cell has at least one info-level note beside a colored severity block. See the JSON for details. |
|
|
287
|
+
|
|
288
|
+
The trailing summary line counts errors, warnings, and info notes (zero-counts are omitted, so a clean run with only info notes still shows e.g. `3 info`). Full per-issue detail is in the JSON snapshot.
|
|
289
|
+
|
|
290
|
+
### `.zoah/debug/issues.json`
|
|
291
|
+
|
|
292
|
+
Every run writes all issues to `.zoah/debug/issues.json`, grouped by phase and severity. Shape:
|
|
293
|
+
|
|
294
|
+
```jsonc
|
|
295
|
+
{
|
|
296
|
+
"schemaVersion": 1,
|
|
297
|
+
"generatedAt": "2026-05-04T18:00:00.000Z",
|
|
298
|
+
"commitSha": "abc1234+dirty",
|
|
299
|
+
"summary": { "total": 12 },
|
|
300
|
+
"phases": {
|
|
301
|
+
"import": { "total": 11, "issues": { "error": [...], "warn": [...], "info": [...] } },
|
|
302
|
+
"package": { "total": 0, "issues": { "error": [], "warn": [], "info": [] } },
|
|
303
|
+
"swap": { "total": 1, "issues": { "error": [], "warn": [...], "info": [] } }
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
Each issue carries a stable `code` (e.g. `DYNAMIC_CLASSNAME_UNRESOLVED`, `CODEMOD_FILE_REFUSED`), a `target` describing what it applies to (`node` / `component` / `file` / `project`), an optional `location` with a 3-line source snippet, and a `commitSha` stamp. The full code list with severity and phase mappings, grouped by outcome, is documented in `docs/supported-shapes.md` in the repo.
|
|
309
|
+
|
|
310
|
+
When the import fails (e.g. the server returns 400 because no components were extractable), the CLI still writes this file and prints the table so you can see exactly which components couldn't be imported and why. Pass `--print-issues warn` (or `info`/`error`) to also print snippet + caret detail inline:
|
|
311
|
+
|
|
312
|
+
```
|
|
313
|
+
warn Card · import · DYNAMIC_CLASSNAME_UNRESOLVED src/Card.tsx:42:18
|
|
314
|
+
Dynamic className expression couldn't be resolved to styles
|
|
315
|
+
41 | const cls = `card-${variant}`;
|
|
316
|
+
42 | return <div className={cls}>...</div>;
|
|
317
|
+
^^^
|
|
318
|
+
43 | }
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
## What the CLI writes
|
|
322
|
+
|
|
323
|
+
**Global (per-machine, never inside a project):**
|
|
324
|
+
|
|
325
|
+
- `~/.zoah/credentials.json`: auth token and base URL (chmod 600). Written by `zoah login` unless a project overrides it.
|
|
326
|
+
|
|
327
|
+
**Project-local** (paths relative to the project where you run `zoah`). The CLI manages `.zoah/.gitignore` so secrets and debug output stay out of git.
|
|
328
|
+
|
|
329
|
+
Commit these files. They bind the checkout to the Zoah project:
|
|
330
|
+
|
|
331
|
+
- `.zoah/config.json`: workspace and project binding, written on the first import.
|
|
332
|
+
- `.zoah/components.json`: component IDs, package exports, and slot anchors.
|
|
333
|
+
- `.zoah/manifest.json`: published package name, version, and registry URL.
|
|
334
|
+
|
|
335
|
+
Ignored automatically through `.zoah/.gitignore`:
|
|
336
|
+
|
|
337
|
+
- `.zoah/credentials.json`: local credential from `login --local`.
|
|
338
|
+
- `.zoah/debug/issues.json`: issues from each run, grouped by phase and severity.
|
|
339
|
+
- `.zoah/debug/payload.json`: raw import payload from `--debug`.
|
|
340
|
+
|
|
341
|
+
The CLI reads old `.opacity` state when the matching `.zoah` file does not exist. New writes use `.zoah`.
|
|
342
|
+
|
|
343
|
+
## Environment variables
|
|
344
|
+
|
|
345
|
+
- `ZOAH_BASE_URL`: default base URL when no flag or credential sets one.
|
|
346
|
+
- `ZOAH_BRANCH`: default branch for `import` when `--branch` is not passed.
|
|
347
|
+
|
|
348
|
+
The old `OPACITY_BASE_URL` and `OPACITY_BRANCH` variables remain compatibility fallbacks.
|