@nomac/cli 0.5.7 → 0.5.8

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nomac/cli",
3
- "version": "0.5.7",
3
+ "version": "0.5.8",
4
4
  "description": "Cloud Mac sessions over SSH and HTTPS, plus iOS builds and publishing — built for agents.",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",
package/skill/SKILL.md CHANGED
@@ -3,8 +3,7 @@ name: nomac
3
3
  description: >
4
4
  Use a full cloud Mac over SSH, HTTPS or MCP for macOS tools, Xcode and iOS
5
5
  development. Start sessions, sync files, run commands, retrieve work and
6
- stop. Also supports the separate iOS Builder product for TestFlight and
7
- App Store publishing, signing, screenshots, metadata and review replies.
6
+ stop.
8
7
  ---
9
8
 
10
9
  # nomac — a Mac for your agent
@@ -40,155 +39,17 @@ Keep the same request key and arguments after uncertain responses; inspect
40
39
  the original job before retrying. Output retrieval failure is not job failure.
41
40
  Managed jobs have a 600-second limit; SSH can run longer within session limits.
42
41
  CLI sync skips symlinks and preserves remote extra files; use native SSH/rsync
43
- when needed. GUI/simulator control and persistent disks are not currently offered.
42
+ when needed. Agents have no GUI control: drive the Simulator with simctl, and
43
+ give the human `open_mac_desktop` when a screen needs a person. Persistent disks
44
+ are not currently offered.
44
45
  Report failures using `report_issue` with `session_id`, optional `job_id` and
45
46
  a description without secrets. Read https://nomac.app/llms.txt for full limits.
46
47
 
47
- ## Separate Builder product
48
+ ## Builder (existing subscribers only)
48
49
 
49
- nomac is the hands; you are the brain. It builds, signs, uploads, lints for
50
- review-readiness, writes store metadata, manages pricing/products and submits for review —
51
- via MCP tools (preferred) or the `nomac` CLI.
52
-
53
- ## Setup check
54
-
55
- 1. MCP tools available (`connect_status`, `push_project`, `build`, …)? Use them.
56
- 2. Otherwise: `npx @nomac/cli whoami`. If not logged in, run
57
- `npx @nomac/cli login`; give the human the device URL and code to approve.
58
- Then `claude mcp add nomac -- npx @nomac/cli mcp`.
59
- 3. `connect_status` must show a healthy Apple connection. If not, the human
60
- connects at the dashboard (60 seconds, one .p8 upload). Don't guess —
61
- verify, then proceed.
62
-
63
- ## Ship to TestFlight
64
-
65
- ```
66
- push_project # after every code change
67
- build workflow=release # ~3 min; smoke = fast compile-only check
68
- status # poll ~30s until ready | failed
69
- ```
70
-
71
- - `ready` → tell the human: "open TestFlight on your phone." Their taps are
72
- the test run; read `get_feedback` for crashes/comments afterwards.
73
- - `failed` → `get_failure`: kind=project means you fix source and re-push;
74
- kind=account means relay the link to the human. Don't burn release builds
75
- debugging compile errors — use `build workflow=smoke`.
76
-
77
- ## Submit for App Store review
78
-
79
- 1. `review_lint` → fix every red. Apply returned patches (e.g. generated
80
- `PrivacyInfo.xcprivacy`) directly to the source. Yellow "signals"
81
- (4.3 distinctiveness, thin listing) are yours to judge and improve.
82
- 2. `set_metadata` — you write the copy; check `get_metadata_schema` for
83
- limits. Age rating + data usage answers are legal attestations: ask the
84
- human, relay their answers. `upload_screenshots` needs exact dimensions
85
- (in the schema). It runs in the background: poll `get_screenshot_upload`
86
- until complete before publishing. A rolled-back or paused replacement
87
- needs the returned recovery instructions before starting another upload.
88
- 3. `publish` without confirm stages real Apple drafts/build attachments but
89
- does not submit. Fix the returned blockers; retain the exact build/submission IDs.
90
- 4. `publish confirm=true` sends the app to Apple. Ensure the human authorized
91
- this app/version; honor authorization already given. New versions use manual
92
- release, while existing versions retain their Apple release policy.
93
-
94
- If metadata or publish returns pending, keep its `request_key` and repeat
95
- the original arguments with that key. `get_store_operation` recovers the key
96
- and progress after a lost response. A new key starts a separate operation;
97
- do not use one to bypass an unconfirmed Apple request. Staging and confirmation
98
- remain separate invocations. For screenshots, keep the original `request_key`
99
- too, and use `get_screenshot_upload` to find or poll the existing operation.
100
-
101
- ## Fix review rejections and release
102
-
103
- - `get_review` lists live Apple submissions, including ones created outside
104
- nomac. Pass `asc_submission_id` for all item states and exact version/build IDs.
105
- - Apple does not expose App Review messages through its public API. Use the
106
- returned App Store Connect handoff to have the human provide the actual text.
107
- Never invent a rejection reason from a status code or public customer review.
108
- - Fix metadata/screenshots on the exact `version_string`. A binary change needs
109
- push/build, then `publish` with the exact `build_id` and `asc_submission_id`.
110
- `resolve_rejection:true` explicitly asserts that this version's issue is fixed.
111
- - `prepare_review_reply` prepares your authored text but always returns `sent:false`.
112
- The human sends it and any message attachments in App Store Connect. Changing
113
- review_contact.notes is not a reply; sending a reply is not resubmission.
114
- - `update_review` supports `resolve_item`, `remove_item`, `cancel`, `resubmit`,
115
- and `release`. Preview without confirm; confirm the exact requested action.
116
- Fix issues before marking items resolved. Every rejected item must be resolved
117
- or removed before resubmitting. Removed items cannot be added back to that submission.
118
- - Poll `get_review`; approval and release are separate. Release requires an
119
- app-version item in Pending Developer Release. Edit subscription/IAP products,
120
- events and custom pages through the store catalog below. Apple/account/legal
121
- decisions still require the relevant Apple workflow.
122
-
123
- ## External TestFlight
124
-
125
- `ready` from a nomac build means internal TestFlight readiness. External testing
126
- requires its own review and distribution:
127
-
128
- 1. `get_testflight` lists groups, test information and recent Apple builds. Use
129
- `asc_build_id` for a specific build's beta-review/external state, or `group_id`
130
- to list testers. Never infer external approval from internal readiness.
131
- 2. `manage_testflight action=metadata` sets app_info (description/feedbackEmail/URLs),
132
- review_contact (Apple contact/demo fields), locale, and build whats_new.
133
- 3. Select/create an external group. `invite_tester`/`remove_tester` use an explicit
134
- email/tester ID and group_id. `update_group` can enable an optional public link.
135
- 4. `distribute` requires asc_build_id and explicit group_ids. It submits beta
136
- review if needed, then assigns those groups. auto_notify defaults false;
137
- `notify` starts testing after approval. `remove_build` affects one group;
138
- `expire` stops testing for the build across all groups.
139
- 5. All actions preview without confirm and apply with confirm:true. Pending
140
- requests use their original key/body; get_store_operation recovers them.
141
- 6. Relay an accurate human-provided uses_non_exempt_encryption with action=encryption
142
- when appropriate. Never guess. Encryption declarations/documents use the
143
- store catalog; rejected beta messages require App Store Connect. Fix the cause
144
- before resubmitting a rejected binary.
145
-
146
- ## Pricing, products, customer reviews and the wider store API
147
-
148
- 1. `get_store_capabilities` lists operations by category/search with next_offset.
149
- Pass `operation` to get that operation's exact Apple request/query schema.
150
- Categories: listing, releases, pricing, purchases, subscriptions, reviews,
151
- marketing, assets, testflight, analytics, compliance, webhooks.
152
- 2. `read_store` executes listed GET operations. Begin with an `apps_*` relationship
153
- and `scope:[]` for the linked app. Every child has a reusable `scope`; copy it
154
- into the next read/write. Keep the query when following `next_cursor`.
155
- 3. `update_store` takes the operation, scope and exact JSON:API `body`. For creation,
156
- scope the parent. Every existing relationship ID needs its own verified scope
157
- in `references`; the target and its ancestors are already verified. Territories
158
- and categories are global. Inline creates use local IDs such as `${price1}`.
159
- 4. Preview without confirm. `confirm:true` applies real paid prices, availability,
160
- products/offers, public responses, release settings or event subscriptions.
161
- Honor the human's existing authorization; do not ask again for authorized work.
162
- Do not invent prices, legal answers or factual claims in public replies.
163
- 5. `customerReviewResponses_createInstance` replies to a public customer review.
164
- It does not send a message to Apple reviewers. Read their actual messages in
165
- App Store Connect; `prepare_review_reply` only drafts the response.
166
- 6. Product management covers subscriptions/IAP versions, localization, prices,
167
- availability, grace periods and offers. First IAP approval may require the
168
- app version submission. Draft review submission items can attach products;
169
- use `publish` / `update_review` to submit, resolve, resubmit and release.
170
- 7. Events, custom pages, experiments, accessibility and phased releases use their
171
- catalog operations. Apple still validates account permissions and valid states.
172
- Analytics report segments supply download URLs; offer-code CSV exports return
173
- bounded base64 downloads. Webhooks send app events to an owner-selected receiver;
174
- that receiver is responsible for running an agent when events arrive.
175
-
176
- `upload_store_asset` handles new Apple file resources: previews, screenshot files,
177
- purchase images, supplemental review attachments and encryption documents. Choose
178
- the asset create operation, provide its parent relationship/body, and pass a local
179
- `file_path` (CLI, up to 500 MiB) or `data_base64` (hosted, up to 2 MiB). Apple also
180
- has asset-specific limits. The tool reserves, uploads each requested byte range,
181
- then commits its checksum. Keep the same request_key and original bytes to resume.
182
- `uploaded:true` is not processing success: poll `read_store` until
183
- `assetDeliveryState.state` is `COMPLETE`. FAILED requires addressing Apple's errors.
184
- This adds a new file; use `upload_screenshots` for managed screenshot replacement.
185
-
186
- Keep pending write keys and unchanged bodies. `get_store_operation` exposes captured
187
- targets and receipts. Unknown Apple outcomes remain pending and block other writes
188
- to the app until reconciled; never use a fresh key to bypass one. Corrected inputs
189
- or a new intentional action require a fresh key. Correspondence, appeals, App Privacy
190
- questionnaire answers and account-wide financial/admin APIs are not exposed.
191
- This catalog does not run simulators or Xcode Cloud jobs.
50
+ The separate iOS Builder publishing product is closed to new subscriptions.
51
+ If `get_billing_status` shows a Builder plan, its tools are listed and
52
+ https://nomac.app/llms.txt describes them. Otherwise use the cloud Mac above.
192
53
 
193
54
  ## When stuck
194
55
 
package/src/cli.mjs CHANGED
@@ -29,14 +29,9 @@ Nomac 2.0 transport probe:
29
29
  nomac tunnel <session> SSH through the configured port-443 gateway
30
30
  nomac transport --help HTTPS jobs, resumable output and binary probes
31
31
 
32
- Existing publishing commands:
32
+ Account and agents:
33
33
  nomac login connect this device (approve in the browser)
34
34
  nomac login <api-key> store an nmk_ key directly (CI / power users)
35
- nomac push pack this directory and upload a snapshot
36
- nomac build [--smoke] start a release (or smoke) build
37
- nomac build --testflight release build; waits until TestFlight-ready
38
- nomac status [build-id] show latest (or given) build status
39
- nomac logs <build-id> show build logs
40
35
  nomac mcp run the stdio MCP server (for agents)
41
36
  nomac whoami show org + usage
42
37
 
package/src/mcp.mjs CHANGED
@@ -40,11 +40,6 @@ export const TOOLS = [
40
40
  inputSchema: { type: "object", properties: {}, additionalProperties: false },
41
41
  handler: async () => text(await api("GET", "/api/v1/billing/status")),
42
42
  },
43
- {
44
- name: "get_checkout_link", description: "Return an org-bound checkout link; the human chooses a plan and pays explicitly. This tool does not charge them. Reuses pending checkout; existing subscribers get billing management instead.",
45
- inputSchema: { type: "object", properties: { plan: { type: "string", enum: ["starter", "pro"] } }, additionalProperties: false },
46
- handler: async args => text(await api("POST", "/api/v1/billing/checkout", { body: args })),
47
- },
48
43
  {
49
44
  name: "get_refund_status", description: "Read the progress of a refund the account owner requested at nomac.app/usage. Agents cannot request refunds; point the human to that page. Does not submit a refund or cancel anything.",
50
45
  inputSchema: { type: "object", properties: { request_id: { type: "string" } }, required: ["request_id"], additionalProperties: false },
@@ -383,6 +378,20 @@ export const TOOLS = [
383
378
  },
384
379
  ];
385
380
 
381
+ /** Shown to everyone: the Mac tools and support. The rest serve Builder subscribers. */
382
+ const PUBLIC_TOOLS = new Set([...MAC_TOOLS.map(t => t.name), "report_issue"]);
383
+ let subscriber;
384
+
385
+ /**
386
+ * The Builder (publishing) plans are closed to new subscriptions, so their tools
387
+ * are listed only for accounts that still have one. Hidden tools still answer
388
+ * when called, so existing subscribers' agents keep working.
389
+ */
390
+ export async function listedTools(isSubscriber = () => (subscriber ??= api("GET", "/api/v1/billing/status").then(s => Boolean(s?.tier) && s.tier !== "none", () => false))) {
391
+ const legacy = await isSubscriber();
392
+ return TOOLS.filter(t => legacy || PUBLIC_TOOLS.has(t.name));
393
+ }
394
+
386
395
  export async function runMcpServer() {
387
396
  const rl = createInterface({ input: process.stdin, terminal: false });
388
397
  const send = (msg) => process.stdout.write(JSON.stringify(msg) + "\n");
@@ -417,7 +426,7 @@ export async function runMcpServer() {
417
426
  break;
418
427
  case "tools/list":
419
428
  reply({
420
- tools: TOOLS.map(({ name, description, inputSchema }) => ({ name, description, inputSchema })),
429
+ tools: (await listedTools()).map(({ name, description, inputSchema }) => ({ name, description, inputSchema })),
421
430
  });
422
431
  break;
423
432
  case "tools/call": {