Docs · Mac app
Tool packs
What a pack is
A pack is a small, versioned bundle from the pack catalog. It adds one or more tabs to the app (file generators, command builders, snippet lists, cheat sheets and built-in checks such as DNS or TLS lookups) and can ship extensions: helper files such as CSS, JavaScript, Helm charts or Terraform modules that you copy into your own projects.
The Tools & Extensions subscription
- Subscribe inside DevOps for Mac: Tools & Extensions, $3.99 a month through the App Store. Manage or cancel it in your App Store account settings.
- The app's one-time premium purchases don't include packs.
- The subscription is linked to the htmltool.io account you're signed in with, and one subscription links to one account.
- Packs you install are remembered on your account and appear on every Mac you sign in on. If the subscription lapses, they stay listed but their tabs are hidden until you renew.
For developers: the packs API
These endpoints are for DevOps for Mac. They take the app's Bearer token (see Signing in), speak snake_case JSON, send Cache-Control: no-store, and return errors as { error, error_description? }.
| Endpoint | Purpose |
|---|---|
| GET /api/app/packs | The catalog with each pack's installed_version, the subscription, and the app_account_token. |
| PATCH /api/app/packs | Sync installs: { install?: [{ id, version }], remove?: [id] }, up to 100 items. |
| POST /api/app/packs/subscription | Send the latest StoreKit 2 jwsRepresentation as signed_transaction. |
| GET /api/app/packs/:id | The pack's bundle JSON (latest catalog version). Subscribers only. |
Purchasing
Pass the app_account_token from GET /api/app/packs to StoreKit's .appAccountToken(_:) purchase option, then send the transaction to the site. The site checks Apple's signature and certificate chain, the bundle com.malcolmstone.FontAwesomePro, one of the product IDs com.malcolmstone.devops.packs.monthly or com.malcolmstone.devops.packs.yearly, expiry and revocation.
POST https://htmltool.io/api/app/packs/subscription
Authorization: Bearer <access_token>
Content-Type: application/json
{ "signed_transaction": "<Transaction.jwsRepresentation>" }
200 { "subscription": { "active": true, "expires_at": "<ISO-8601>", "environment": "Production" } }
400 { "error": "invalid_transaction", "error_description": "…" }
403 { "error": "transaction_other_account" } // bought with another account's app_account_token
409 { "error": "transaction_in_use" } // already linked to another htmltool.io account
429 { "error": "rate_limited" } // 10 requests per 10 minutes; Retry-AfterInstalls and bundles
PATCH https://htmltool.io/api/app/packs
Authorization: Bearer <access_token>
Content-Type: application/json
{ "install": [{ "id": "kubernetes-toolkit", "version": "1.0.0" }], "remove": ["css-layout-helpers"] }
200 { "installed": [{ "id": "kubernetes-toolkit", "version": "1.0.0", "installed_at": "<ISO-8601>" }] }
400 { "error": "invalid_request", "error_description": "…" } // bad ids, unknown packs, > 100 items
403 { "error": "subscription_required" } // installing needs an active subscription; removing always worksGET https://htmltool.io/api/app/packs/kubernetes-toolkit
Authorization: Bearer <access_token>
200 { "schema": 1, "id": "kubernetes-toolkit", "version": "1.0.0", …, "tabs": [ … ], "readme": "…", "files": { "files/…": "…" } }
403 { "error": "subscription_required" }
404 { "error": "not_found" }GET /api/app/packs still answers with your subscription and an empty packs list, and sets catalog_error. Keep showing the packs you already downloaded.