@revfleet/hscli 0.8.0 → 0.8.3

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.
Files changed (81) hide show
  1. package/CHANGELOG.md +115 -0
  2. package/LICENSE +1 -1
  3. package/README.md +118 -269
  4. package/SECURITY.md +2 -2
  5. package/dist/cli.js +25 -5
  6. package/dist/cli.js.map +1 -1
  7. package/dist/commands/api/index.d.ts +3 -0
  8. package/dist/commands/api/index.js.map +1 -1
  9. package/dist/commands/auth/index.js +6 -6
  10. package/dist/commands/auth/index.js.map +1 -1
  11. package/dist/commands/crm/companies.d.ts +3 -0
  12. package/dist/commands/crm/companies.js.map +1 -1
  13. package/dist/commands/crm/contacts.d.ts +3 -0
  14. package/dist/commands/crm/contacts.js.map +1 -1
  15. package/dist/commands/crm/custom-objects.d.ts +3 -0
  16. package/dist/commands/crm/custom-objects.js.map +1 -1
  17. package/dist/commands/crm/dated.d.ts +1 -1
  18. package/dist/commands/crm/dated.js +1 -1
  19. package/dist/commands/crm/deals.d.ts +3 -0
  20. package/dist/commands/crm/deals.js.map +1 -1
  21. package/dist/commands/crm/describe.d.ts +3 -0
  22. package/dist/commands/crm/describe.js.map +1 -1
  23. package/dist/commands/crm/engagements.d.ts +3 -0
  24. package/dist/commands/crm/engagements.js.map +1 -1
  25. package/dist/commands/crm/imports.d.ts +3 -0
  26. package/dist/commands/crm/imports.js.map +1 -1
  27. package/dist/commands/crm/owners.d.ts +3 -0
  28. package/dist/commands/crm/owners.js.map +1 -1
  29. package/dist/commands/crm/tickets.d.ts +3 -0
  30. package/dist/commands/crm/tickets.js.map +1 -1
  31. package/dist/commands/doctor/index.js +35 -35
  32. package/dist/commands/doctor/index.js.map +1 -1
  33. package/dist/commands/domains/shared.d.ts +3 -0
  34. package/dist/commands/domains/shared.js.map +1 -1
  35. package/dist/commands/events/index.d.ts +3 -0
  36. package/dist/commands/events/index.js.map +1 -1
  37. package/dist/commands/forms/index.d.ts +3 -0
  38. package/dist/commands/forms/index.js.map +1 -1
  39. package/dist/commands/legacy-v1/index.d.ts +1 -1
  40. package/dist/commands/legacy-v1/index.js +1 -1
  41. package/dist/commands/mcp.d.ts +3 -0
  42. package/dist/commands/mcp.js.map +1 -1
  43. package/dist/commands/seed/cms.js +19 -19
  44. package/dist/commands/seed/cms.js.map +1 -1
  45. package/dist/commands/seed/index.js +1 -1
  46. package/dist/commands/seed/index.js.map +1 -1
  47. package/dist/commands/seed/infra.js +14 -14
  48. package/dist/commands/seed/infra.js.map +1 -1
  49. package/dist/commands/seed/marketing.js +13 -13
  50. package/dist/commands/seed/marketing.js.map +1 -1
  51. package/dist/commands/webhooks/index.d.ts +3 -0
  52. package/dist/commands/webhooks/index.js.map +1 -1
  53. package/dist/commands/workflows/index.d.ts +3 -0
  54. package/dist/commands/workflows/index.js.map +1 -1
  55. package/dist/core/auth.d.ts +1 -1
  56. package/dist/core/auth.js +8 -25
  57. package/dist/core/auth.js.map +1 -1
  58. package/dist/core/capabilities.js +15 -15
  59. package/dist/core/capabilities.js.map +1 -1
  60. package/dist/core/http.js +3 -3
  61. package/dist/core/http.js.map +1 -1
  62. package/dist/core/output.d.ts +3 -0
  63. package/dist/core/output.js.map +1 -1
  64. package/dist/core/permissions.js +1 -1
  65. package/dist/core/permissions.js.map +1 -1
  66. package/dist/core/plugins.d.ts +2 -2
  67. package/dist/core/plugins.js +2 -2
  68. package/dist/core/plugins.js.map +1 -1
  69. package/dist/core/schema-cache.js +3 -3
  70. package/dist/core/schema-cache.js.map +1 -1
  71. package/dist/core/schemas.js +1 -1
  72. package/dist/core/schemas.js.map +1 -1
  73. package/dist/core/urls.d.ts +4 -4
  74. package/dist/core/urls.js +4 -4
  75. package/dist/core/vault.d.ts +5 -5
  76. package/dist/core/vault.js +14 -14
  77. package/dist/core/vault.js.map +1 -1
  78. package/dist/mcp/server.d.ts +1 -1
  79. package/dist/mcp/server.js +7 -7
  80. package/dist/mcp/server.js.map +1 -1
  81. package/package.json +4 -4
package/CHANGELOG.md CHANGED
@@ -1,5 +1,120 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.8.3 - 2026-04-23
4
+
5
+ **Clean-install fix + CI stability.** Two P1 issues surfaced in a
6
+ post-0.8.2 external review blocked anyone trying `npm ci` from a
7
+ fresh clone — and two tests were hitting Vitest's 5 s default timeout
8
+ on slower CI runners. Neither affected end users running
9
+ `npm install -g @revfleet/hscli@0.8.2`.
10
+
11
+ ### Fixes
12
+
13
+ - **`package-lock.json`** — out of sync with `package.json` on 0.8.2;
14
+ `npm ci` failed with `Missing: @emnapi/{runtime,core}@1.9.2 from
15
+ lock file`. Lock regenerated from scratch against the current
16
+ dependency tree; `npm ci` now passes clean.
17
+ - **`vitest.config.ts`** — new file. Bumps `testTimeout` and
18
+ `hookTimeout` from the 5 s default to 20 s. The `audit timeline
19
+ scans a directory of trace-*.jsonl` and the `parses global flags`
20
+ tests were flaking at 5 s on slower CI runners where the first
21
+ cold `import("../src/cli.js")` plus a tmpdir directory scan added
22
+ several seconds of latency before the assertion window opened.
23
+ 20 s gives headroom without hiding real bugs — a legitimately 20-s
24
+ test would still be a red flag worth investigating.
25
+
26
+ No runtime behavior change. Tests still 255 / 265 pass; typecheck +
27
+ lint clean.
28
+
29
+ ## 0.8.2 - 2026-04-23
30
+
31
+ **Brand + polish release.** No runtime behavior changes for end users
32
+ beyond what CI already enforces — this is a pre-launch cut that ships
33
+ everything that's been on `main` since 0.8.1 alongside a consistent
34
+ visual identity and a codebase with zero "hubcli" references.
35
+
36
+ ### Visible change for `npm install -g` users
37
+
38
+ `hscli --help` now opens with the bracketed monogram banner:
39
+
40
+ ```
41
+ ┌──┐
42
+ │hs│ hscli · agentic HubSpot CLI + MCP server
43
+ └──┘ @revfleet/hscli · MIT · github.com/revfleet/hscli
44
+ ```
45
+
46
+ The banner matches the repo avatar and the `[hs]` monogram used on the
47
+ README hero + social preview. Same safety model, same command surface —
48
+ only the help-screen framing changes.
49
+
50
+ ### Documentation + repo polish
51
+
52
+ - **README** reworked with a confident headline ("Your HubSpot portal,
53
+ in one binary.") + three focused badges (npm · MIT · 1,180
54
+ endpoints). Progressive disclosure via a single `<details>` for the
55
+ full coverage list.
56
+ - **Brand identity** — `brand/` now contains the monogram, wordmark,
57
+ hero band, social preview (PNG + SVG), revfleet org avatar, and the
58
+ ASCII banner.
59
+ - **CODE_OF_CONDUCT.md** — Contributor Covenant v2.1 reference + a
60
+ short project-specific summary.
61
+ - **Doc cross-refs** — obsolete `[[wiki-link]]` style converted to real
62
+ markdown links throughout `docs/`. Dead `[[hubspot-rules]]`
63
+ references dropped.
64
+ - **POLICY_EXAMPLE.json** upgraded to the v2 schema introduced in
65
+ v0.7.0 (rule-based method+path globs, time windows, change-ticket +
66
+ approval gates).
67
+
68
+ ### Internal polish
69
+
70
+ - **ESLint** — stricter rules enabled: `eqeqeq` (safer for HubSpot IDs
71
+ that look numeric) and `prefer-const`.
72
+ - **Dependabot** — Monday schedule, labels for PR triage, TypeScript
73
+ major bumps excluded (manual triage, same pattern used for the 5→6
74
+ breakage).
75
+ - **`src/core/auth.ts`** — the `~/.hubcli/` legacy-fallback path was
76
+ dropped. The `getHubcliHomeDir` export alias was removed too.
77
+ Technically a breaking change for any external consumer that
78
+ imported the old name; none known to exist.
79
+ - **Release-checksums** script documented with a header comment.
80
+ - **Module headers** added to 17 command / core modules.
81
+
82
+ ### Privacy + scrub
83
+
84
+ - Package author field: `"Luigi Vermeulen (revfleet)"` → `"revfleet"`.
85
+ - Portal ID `147975758` removed from every code path where it
86
+ appeared as illustration or test fixture (replaced with `12345678`).
87
+ - Deleted `docs/TESTING/PORTAL-147975758-*.md` snapshot files.
88
+ - Deleted `docs/LAUNCH/` — four pre-launch marketing drafts with
89
+ named-competitor comparisons (Composio, peakmojo, lkm1developer,
90
+ CData, …) and CRMforge references. The repo now describes hscli on
91
+ its own terms only.
92
+ - Deleted `.hubcli-sync-contacts.json` (stale local state, last
93
+ touched 2026-03-19).
94
+
95
+ Git history was rewritten (49 commits, 10 tags repointed) so zero
96
+ "hubcli" references remain anywhere — code, docs, filenames, commit
97
+ messages, tags.
98
+
99
+ Tests: 255 pass. Typecheck + lint clean.
100
+
101
+ ## 0.8.1 - 2026-04-22
102
+
103
+ **Critical fix — globally-installed `hscli` binary was silent on all commands.**
104
+
105
+ The entry-point guard in `src/cli.ts` compared `import.meta.url` against
106
+ `resolve(process.argv[1])`, but `resolve()` does not follow symlinks.
107
+ A global npm install creates `~/.npm-global/bin/hscli` as a symlink into
108
+ `.../node_modules/@revfleet/hscli/dist/cli.js`; with the un-resolved
109
+ compare, the two paths never matched, so `run()` never fired and the
110
+ binary exited with code 0 and no output. Fix: resolve both sides with
111
+ `fs.realpathSync` and `fileURLToPath(import.meta.url)` before comparing.
112
+
113
+ This broke every `hscli <command>` invocation on every version since the
114
+ first publish (v0.5.3). It was masked locally because `npm run dev` /
115
+ `node dist/cli.js` don't go through the symlink. Anyone on npm installs
116
+ should upgrade immediately.
117
+
3
118
  ## 0.8.0 - 2026-04-22
4
119
 
5
120
  **MCP compatibility surface + extension tools.** HubSpot promoted their hosted Remote MCP server at `mcp.hubspot.com` to GA on 2026-04-13. This release makes `hscli mcp` a drop-in target for agents built against that surface, and adds a second tool family for everything HubSpot's hosted version doesn't cover.
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2026 Luigi Vermeulen
3
+ Copyright (c) 2026 Revfleet
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -1,352 +1,201 @@
1
- # hscli
1
+ <p align="center">
2
+ <img src="brand/readme-hero.svg" alt="hscli — agentic HubSpot CLI + MCP server" width="100%">
3
+ </p>
2
4
 
3
- [![CI](https://github.com/revfleet/hscli/actions/workflows/ci.yml/badge.svg)](https://github.com/revfleet/hscli/actions/workflows/ci.yml)
4
- [![npm version](https://img.shields.io/npm/v/@revfleet/hscli.svg)](https://www.npmjs.com/package/@revfleet/hscli)
5
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
6
- [![Node: >=20](https://img.shields.io/badge/Node-%3E%3D20-brightgreen)](package.json)
7
- [![HubSpot API coverage: 100%](https://img.shields.io/badge/HubSpot%20API-100%25%20(1180%20endpoints)-7c3aed)](docs/TIERS.md)
5
+ <p align="center">
6
+ <strong>Your HubSpot portal, in one binary.</strong>
7
+ </p>
8
8
 
9
- **The headless HubSpot CLI + MCP server. 100% public API coverage (1,180 endpoints, 55+ command domains), enterprise safety rails, self-hosted.**
9
+ <p align="center">
10
+ <a href="https://www.npmjs.com/package/@revfleet/hscli"><img src="https://img.shields.io/npm/v/@revfleet/hscli.svg?style=flat-square&color=22D3EE&labelColor=0F172A" alt="npm"></a>
11
+ <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-22D3EE?style=flat-square&labelColor=0F172A" alt="MIT"></a>
12
+ <a href="docs/TIERS.md"><img src="https://img.shields.io/badge/HubSpot%20API-1%2C180%20endpoints-22D3EE?style=flat-square&labelColor=0F172A" alt="1,180 HubSpot endpoints"></a>
13
+ </p>
10
14
 
11
- ## Get started in 30 seconds
15
+ <p align="center">
16
+ <img src="docs/demo-hubspot.gif" alt="hscli writing into a HubSpot portal in real time — records appear in the UI as hscli creates them" width="100%">
17
+ </p>
12
18
 
13
- ```bash
14
- # 1. Install
15
- npm install -g @revfleet/hscli
16
-
17
- # 2. Auth with a HubSpot Private App token (create one at
18
- # Settings → Integrations → Private Apps → Create private app)
19
- printf '%s' 'pat-eu1-XXXX-XXXX-XXXX' | hscli auth login --token-stdin
20
-
21
- # 3. Read
22
- hscli crm contacts list --limit 5
23
-
24
- # 4. Write (dry-run by default, --force to execute)
25
- hscli --force crm contacts create --data '{"properties":{"email":"jane@example.com"}}'
26
-
27
- # 5. Run as an MCP server for Claude Desktop, Cursor, Claude Code
28
- hscli mcp
29
- ```
30
-
31
- That's the whole thing. For the full picture of what's available, read on.
19
+ <p align="center">
20
+ <sub>↳ Live tour · terminal writes, HubSpot reflects · ~60s on a real portal.</sub>
21
+ </p>
32
22
 
33
23
  ---
34
24
 
35
- <details>
36
- <summary><strong>Full coverage map (55+ domains)</strong></summary>
37
-
38
- hscli gives you one TypeScript binary that covers **every** endpoint of HubSpot's public API surface — verified against a scrape of HubSpot's own dev docs (1,178 source files, 1,180 endpoints). Whether an endpoint actually returns data on *your* portal depends on the HubSpot tier you're on (see [docs/TIERS.md](docs/TIERS.md)). hscli exposes them all.
39
-
40
- - **Full CRM** — contacts, companies, deals, tickets, leads, quotes, products, line items, orders, carts, discounts, fees, taxes, invoices, subscriptions, payments, goals, communications, users, feedback-submissions, custom objects, properties (+ legacy v1/v2), pipelines, associations v4 (+ labels CRUD + dated 2025-09), owners, imports, exports, engagements (notes/tasks/calls/meetings), sync, describe/validate, timeline, CRM Cards (UI Extensions), filter + count primitives on every object
41
- - **Marketing** — emails (v3 + legacy v1, per-email stats), campaigns, ads, social, SEO, landing pages, transactional, subscriptions, events (+ attendance + participations), behavioral events, forms, form integrations, legacy email events stream (per-recipient)
42
- - **Sales** — sequences (+ enroll/unenroll), meetings, calling, goals, scheduler (meeting links, book/reschedule/cancel), sales extensions (videoconferencing, accounting)
43
- - **Service** — conversations (threads, messages, inboxes, channels, channel-accounts, actors, custom-channels), feedback, chatflows, knowledge-base, ticket pipelines, visitor-identification
44
- - **CMS** — site pages, landing pages (+ folders), blog posts (+ authors + tags + blog-settings), HubDB (tables, rows, drafts, publishing), URL redirects, source-code, domains, SEO audit, site search, topics, audit-logs, comments, legacy content/api/v2 (Pages, Layouts, Templates, Modules, UrlMappings)
45
- - **Settings** — users, teams, business units, currencies, GDPR, audit-logs, communication preferences (v3 + v4 batch)
46
- - **Account** — info, audit-logs, private-apps, API usage
47
- - **Operations** — lists (+ folders + memberships), reporting, exports, workflows (v4 + legacy v2/v3), automation custom actions, webhooks (subscriptions), timeline (templates + events + integrators)
48
- - **Commerce Hub** — quotes, products, line-items, invoices, subscriptions, payments, orders, carts, discounts, fees, taxes, payments-subscriptions, tax rates
49
- - **Developer Platform** — feature flags, CRM cards, integrators timeline, media bridge (properties + schemas + settings + events), extensions (calling + videoconferencing + accounting + sales)
50
- - **Legacy v1/v2** — contacts-v1, companies-v2, deals-v1, owners-v2, engagements-v1, properties-legacy, reports-v2, calling-v1, channels, broadcast, appinstalls, marketing-emails-v1
51
- - **Niche** — email events, email events per-recipient stream, submissions, visitor-identification, scheduler, tax, appinstalls, marketing-extras, owners-extras
52
- - **Raw API** command with path-scope controls + OAuth flow support
53
- - **Built-in MCP server** over stdio (140+ tools) for Claude Desktop, Cursor, Claude Code, any MCP client
54
-
55
- Enterprise-grade from day one: `--dry-run`, `--force`, policy files, change tickets, capability probing, rate-limit intelligence, token redaction, path scope allowlisting, idempotency keys.
56
-
57
- </details>
58
-
59
-
60
- ## What hscli focuses on
61
-
62
- 1. **CLI-first with MCP as a peer surface.** Every MCP tool has a matching `hscli` command — same write gates, same redaction, same capability probing in both.
63
- 2. **Self-hosted and token-sovereign.** Your HubSpot private app token stays on your machine.
64
- 3. **Safety gates by default.** `--dry-run`, `--force`, policy files, change tickets, path scope allowlisting, idempotency keys on every write.
65
- 4. **HubSpot-native engineering.** Reads HubSpot's `X-HubSpot-RateLimit-*` headers, proactive throttling, capability probing by `portalId + scopes`, offline schema validation.
66
-
67
- ## "100% coverage" — what that means
68
-
69
- hscli's coverage claim is precise: **every one of HubSpot's 1,180 documented public API endpoints has a corresponding CLI subcommand.** This is verified against an automated scrape of HubSpot's developer documentation (committed at [docs/TESTING/PORTAL-147975758-COVERAGE.md](docs/TESTING/PORTAL-147975758-COVERAGE.md) and [PORTAL-147975758-WRITES.md](docs/TESTING/PORTAL-147975758-WRITES.md)).
70
-
71
- It does **not** mean every endpoint returns 2xx on your portal — HubSpot tier-locks hundreds of endpoints behind paid plans:
72
-
73
- | Portal profile | Reachable endpoints (read + write) |
74
- |---|---:|
75
- | Free account | ~550 / 1180 (46.6%) |
76
- | Starter hubs | ~640 / 1180 (54.2%) |
77
- | Professional hubs | ~890 / 1180 (75.4%) |
78
- | Enterprise hubs (all) + Commerce + Ops | ~1140 / 1180 (96.6%) |
79
- | Developer App OAuth install | adds ~30 app-dev endpoints |
80
- | Legacy hapikey (pre-June-2023 accounts) | adds ~40 zombie endpoints |
81
-
82
- See [docs/TIERS.md](docs/TIERS.md) for the exact endpoint → tier mapping.
25
+ ## Why
83
26
 
84
- **If an endpoint your portal should access doesn't work**, open an [endpoint issue](https://github.com/revfleet/hscli/issues/new?template=endpoint_not_working.md) we triage these fast.
27
+ 1,180 HubSpot endpoints, one TypeScript binary. Every write blocked unless you explicitly `--force` it. Every request auditable. Token stays on your machine. MCP-ready for Claude Desktop, Cursor, and any agent that speaks the protocol.
85
28
 
86
- ## Install
29
+ No SaaS middleman, no proprietary dashboard, no "download the CLI, then also install the desktop app". Just a CLI that respects production.
87
30
 
88
- From npm (once published):
31
+ ## Install & auth
89
32
 
90
33
  ```bash
91
34
  npm install -g @revfleet/hscli
35
+ printf '%s' 'pat-eu1-XXXX-XXXX-XXXX' | hscli auth login --token-stdin
36
+ hscli crm contacts list --limit 5
92
37
  ```
93
38
 
94
- From source:
95
-
96
- ```bash
97
- git clone https://github.com/revfleet/hscli.git
98
- cd hscli
99
- npm install
100
- npm run build
101
- ```
102
-
103
- ## Quickstart
104
-
105
- Save a token (recommended — avoids shell history):
106
-
107
- ```bash
108
- printf '%s' '<HUBSPOT_PRIVATE_APP_TOKEN>' | hscli auth login --token-stdin
109
- ```
110
-
111
- Inline token (also supported):
112
-
113
- ```bash
114
- hscli auth login --token <HUBSPOT_PRIVATE_APP_TOKEN>
115
- ```
39
+ Create a Private App token at **Settings → Integrations → Private Apps → Create private app** in your HubSpot portal.
116
40
 
117
- Read:
41
+ ## Write safely
118
42
 
119
43
  ```bash
120
- hscli crm contacts list --limit 5
121
- hscli marketing emails stats 123456
122
- hscli sales sequences list
123
- hscli reporting dashboards list
124
- hscli settings teams list
125
- ```
44
+ # Blocked writes need explicit intent
45
+ hscli crm contacts create --data '{"properties":{"email":"jane@acme.com"}}'
46
+ # WRITE_CONFIRMATION_REQUIRED
126
47
 
127
- Dry-run write:
48
+ # Preview what the call would look like
49
+ hscli --dry-run crm contacts create --data '{"properties":{"email":"jane@acme.com"}}'
128
50
 
129
- ```bash
130
- hscli --dry-run crm contacts create --data '{"properties":{"email":"test@example.com"}}'
51
+ # Execute — with an Idempotency-Key baked in automatically
52
+ hscli --force crm contacts create --data '{"properties":{"email":"jane@acme.com"}}'
131
53
  ```
132
54
 
133
- Live write (explicit):
55
+ Policy file + change-ticket enforcement for ops teams:
134
56
 
135
57
  ```bash
136
- hscli --force crm contacts create --data '{"properties":{"email":"test@example.com"}}'
137
- ```
138
-
139
- Policy-guarded delete with change ticket:
140
-
141
- ```bash
142
- hscli --force --policy-file docs/POLICY_EXAMPLE.json --change-ticket CHG-123 \
58
+ hscli --force --policy-file ./policy.json --change-ticket CHG-123 \
143
59
  crm contacts delete 123
144
60
  ```
145
61
 
146
- <details>
147
- <summary><strong>Policy-as-code (v0.7)</strong> — glob matching, time windows, approval gates, built-in templates</summary>
62
+ ## Run as an MCP server
148
63
 
149
- Policy files let ops define *what* an agent is allowed to do not just *whether* it can write. Rule matching is first-match-wins: method + path glob (`*` within a segment, `**` across segments), optional time window (`window.hours`, `window.days`, `window.tz`), optional change-ticket requirement, optional approval gate.
64
+ Drop `hscli` into any MCP clientClaude Desktop, Cursor, Claude Code, or your own agent runtime.
150
65
 
151
66
  ```bash
152
- # List built-in templates (read-only, no-deletes, business-hours, compliance-strict, change-ticket-required)
153
- hscli policy templates list
154
-
155
- # Copy a template to edit locally
156
- hscli policy templates extract no-deletes --to ./policy.json
67
+ hscli mcp
68
+ ```
157
69
 
158
- # Validate before shipping
159
- hscli policy validate ./policy.json
70
+ For Claude Desktop, add to `claude_desktop_config.json`:
160
71
 
161
- # Dry-run which rule would fire for a hypothetical request
162
- hscli --policy-file ./policy.json \
163
- policy show-matching DELETE /crm/v3/objects/contacts/123
72
+ ```json
73
+ {
74
+ "mcpServers": {
75
+ "hscli": {
76
+ "command": "hscli",
77
+ "args": ["mcp"],
78
+ "env": { "HSCLI_MCP_PROFILE": "default" }
79
+ }
80
+ }
81
+ }
164
82
  ```
165
83
 
166
- Enforcement is automatic once `--policy-file` is set (or `HSCLI_POLICY_FILE` env var). Error codes (`POLICY_RULE_DENY`, `POLICY_DEFAULT_DENY`, `POLICY_CHANGE_TICKET_REQUIRED`, `POLICY_APPROVAL_REQUIRED`, `POLICY_OUT_OF_WINDOW`) are machine-readable.
84
+ The MCP server exposes three tool families:
167
85
 
168
- Tutorial: [docs/TUTORIALS/secure-agent-writes.md](docs/TUTORIALS/secure-agent-writes.md).
86
+ - **Per-object tools** — `crm_contacts_list`, `crm_deals_create`, `crm_custom_records_search`, …
87
+ - **HubSpot Remote MCP compat** — same tool names as `mcp.hubspot.com` (`search_crm_objects`, `manage_crm_objects`, …) so agents built for HubSpot's hosted MCP drop in without changes
88
+ - **Extension surface** — workflows, files, forms, webhooks, HubDB, conversations, and more, all with the same `--force` + policy gates as the CLI
169
89
 
170
- </details>
90
+ Every MCP tool call goes through the same safety rails as the CLI. Token redaction is enforced on every response. `HSCLI_MCP_PROFILE` locks the stdio server to one auth profile to prevent cross-tenant access.
171
91
 
172
- <details>
173
- <summary><strong>Trace + replay (v0.6+)</strong> — observability of every request, human + MCP</summary>
174
-
175
- `hscli trace` records every request to a JSONL file — method, path, status, latency, profile, `toolName` (when invoked from an MCP tool), optional request/response bodies. Useful for reproducibility, regression detection between portals, debugging agent behavior.
92
+ ## Observability
176
93
 
177
94
  ```bash
178
- # Start recording to ~/.revfleet/trace-<ts>.jsonl (or pass --out)
179
- hscli trace start --include-bodies --scope all
180
-
181
- # Run anything. Every request appends.
182
- hscli crm contacts list
183
- hscli mcp # MCP requests tagged with toolName
184
-
185
- # Stop; the file stays, session state clears.
95
+ hscli trace start # start recording every request
96
+ hscli --force crm contacts create … # → appends to the trace JSONL
186
97
  hscli trace stop
187
98
 
188
- # Inspect
189
- hscli trace show ./trace-<ts>.jsonl --filter status=>=400
190
- hscli trace stats ./trace-<ts>.jsonl # p50/p95/p99 latency, method breakdown
191
- hscli trace errors ./trace-<ts>.jsonl # only errors
192
- hscli trace diff ./run-a.jsonl ./run-b.jsonl # detect reproducibility divergence
193
-
194
- # Replay GETs (safe-by-default: dry-run unless --force)
195
- hscli trace replay ./trace-<ts>.jsonl
99
+ hscli trace stats ./trace-*.jsonl # p50/p95/p99 latency, method breakdown
100
+ hscli trace diff ./run-a.jsonl ./run-b.jsonl # spot reproducibility drift
101
+ hscli audit writes --since 24h # who wrote what, when
102
+ hscli audit by-tool # per-MCP-tool call count + error rate
196
103
  ```
197
104
 
198
- Writes (`POST/PUT/PATCH/DELETE`) are intentionally not replayable to prevent accidental re-mutation.
105
+ Every request hscli makes is append-only JSONL. Pair `trace` with `audit` for full "who did what when" provenance — no extra infrastructure required.
199
106
 
200
- Tutorial: [docs/TUTORIALS/trace-replay-repro.md](docs/TUTORIALS/trace-replay-repro.md).
201
-
202
- </details>
107
+ ## What's in the box
203
108
 
204
109
  <details>
205
- <summary><strong>Audit (v0.7)</strong> — &ldquo;who did what when&rdquo; across every recorded session</summary>
206
-
207
- `hscli audit` reads trace JSONL files (single file or an entire directory of `trace-*.jsonl`) and answers operational audit questions. Pairs with `trace` for full provenance.
208
-
209
- ```bash
210
- hscli audit timeline --since 24h # chronological event list, last 24h
211
- hscli audit who alice --since 7d # what has profile 'alice' done?
212
- hscli audit what /crm/v3/objects/contacts --since 7d # who touched this path?
213
- hscli audit writes --since 24h # all writes in the last 24h (+ failures)
214
- hscli audit by-tool # per-MCP-tool call count, error rate, avg latency
215
- ```
216
-
217
- Tutorial: [docs/TUTORIALS/audit-portal-writes.md](docs/TUTORIALS/audit-portal-writes.md).
110
+ <summary><strong>Full surface coverage</strong> — click to expand</summary>
111
+
112
+ - **CRM** contacts, companies, deals, tickets, leads, quotes, products, line items, orders, carts, discounts, fees, taxes, invoices, subscriptions, payments, goals, communications, users, custom objects, properties, pipelines, associations v4, owners, imports, exports, engagements, sync, describe/validate, timeline, CRM Cards
113
+ - **Marketing** — emails (v3 + legacy v1), campaigns, ads, social, SEO, landing pages, transactional, subscriptions, events, behavioral events, forms
114
+ - **Sales** — sequences, meetings, calling, scheduler, sales extensions
115
+ - **Service** conversations, feedback, chatflows, knowledge-base, ticket pipelines, visitor-identification
116
+ - **CMS** site/landing/blog pages, HubDB, URL redirects, source-code, domains, SEO audit
117
+ - **Settings** users, teams, business units, currencies, GDPR, audit-logs, communication preferences
118
+ - **Operations** lists, reporting, exports, workflows (v4 + legacy), automation, webhooks, timeline
119
+ - **Commerce Hub** — quotes, products, line-items, invoices, subscriptions, payments, orders, carts, taxes
120
+ - **Developer Platform** — feature flags, CRM cards, integrators timeline, media bridge, extensions
121
+ - **Legacy v1/v2** — every pre-v3 surface preserved for portals that still need them
122
+ - **Raw API** command with path-scope controls + full OAuth flow support
123
+
124
+ Enterprise defaults: `--dry-run`, `--force`, policy files, change tickets, capability probing, rate-limit intelligence, token redaction, path scope allowlisting, idempotency keys on every write.
218
125
 
219
126
  </details>
220
127
 
221
- ## Output modes
222
-
223
- ```bash
224
- hscli --json crm companies list --limit 3 # JSON envelope
225
- hscli --format csv crm contacts list --limit 5 # CSV
226
- hscli --format yaml crm deals get 123 # YAML
227
- ```
228
-
229
- ## MCP: AI agents as first-class consumers
128
+ ### What "1,180 endpoints" means
230
129
 
231
- hscli ships a built-in MCP server over stdio with ~125 tools exposing the full surface:
130
+ Every one of HubSpot's documented public API endpoints has a corresponding CLI subcommand verified against an automated scrape of HubSpot's developer documentation.
232
131
 
233
- ```bash
234
- hscli mcp
235
- ```
132
+ It does **not** mean every endpoint returns 2xx on your portal. HubSpot tier-locks hundreds of endpoints behind paid plans:
236
133
 
237
- For Claude Desktop, add to `claude_desktop_config.json`:
238
-
239
- ```json
240
- {
241
- "mcpServers": {
242
- "hscli": {
243
- "command": "hscli",
244
- "args": ["mcp"],
245
- "env": {
246
- "HSCLI_MCP_PROFILE": "default"
247
- }
248
- }
249
- }
250
- }
251
- ```
252
-
253
- Restart Claude. Now Claude can list contacts, search deals, inspect workflows, and — with `--force` passed at tool-call time — perform safe writes. All CLI safety rails apply to MCP calls. Secrets are redacted from every tool response. `HSCLI_MCP_PROFILE` locks the stdio server to one auth profile to prevent cross-tenant access.
254
-
255
- See [docs/MCP.md](docs/MCP.md) for the full tool catalog.
256
-
257
- ## Capability / tier awareness
134
+ | Portal profile | Reachable endpoints |
135
+ |---|---:|
136
+ | Free | ~550 / 1,180 (47%) |
137
+ | Starter | ~640 / 1,180 (54%) |
138
+ | Professional | ~890 / 1,180 (75%) |
139
+ | Enterprise (all hubs) + Commerce + Ops | ~1,140 / 1,180 (97%) |
258
140
 
259
- Probe portal capabilities and cache them by `portalId + scopes`:
141
+ Exact endpoint tier mapping in [docs/TIERS.md](docs/TIERS.md).
260
142
 
261
- ```bash
262
- hscli doctor capabilities --refresh
263
- ```
143
+ ## Design principles
264
144
 
265
- Fail fast when a command hits an unsupported endpoint:
145
+ 1. **CLI-first, MCP as a peer.** Every MCP tool has a matching `hscli` command same write gates, same redaction, same capability probing in both.
146
+ 2. **Self-hosted, token-sovereign.** Your HubSpot private app token stays on your machine. No telemetry, no phone-home.
147
+ 3. **Safe by default.** Mutations are blocked unless `--force` is explicit. `--dry-run` previews every write. Idempotency-Key on every mutation.
148
+ 4. **HubSpot-native.** Reads `X-HubSpot-RateLimit-*` headers, throttles proactively, caches capabilities by `portalId + scopes`, validates payloads offline.
266
149
 
267
- ```bash
268
- hscli --strict-capabilities marketing emails list
269
- ```
270
-
271
- ## Schema introspection + offline validation
150
+ ## Output modes
272
151
 
273
152
  ```bash
274
- hscli crm describe contacts --refresh-cache
275
- hscli crm validate contacts --offline --data '{"properties":{"email":"x@example.com"}}'
153
+ hscli --json crm companies list --limit 3 # JSON envelope
154
+ hscli --format csv crm contacts list --limit 5 # CSV
155
+ hscli --format yaml crm deals get 123 # YAML
156
+ hscli --format table crm contacts list --limit 5 # table (default)
276
157
  ```
277
158
 
278
- Local schema cache means you can validate payloads without hitting HubSpot.
159
+ ## Terminal session
279
160
 
280
- ## Runtime safety model
161
+ The HubSpot-UI recording at the top shows the *outcome*. Here's the *cause* — the same fixture built and torn down entirely from the shell:
281
162
 
282
- - Mutations are **blocked** unless `--force` is passed (or intercepted by `--dry-run`)
283
- - Write/delete can be constrained by policy (`--policy-file`) and change-ticket enforcement
284
- - Requests are origin-locked to `https://api.hubapi.com` and restricted to approved API path roots
285
- - Path segments are hardened against traversal / control characters
286
- - Output and error payloads are redacted for secrets and token-like strings
287
- - Transport retries transient failures with exponential backoff
288
- - Rate-limit controller reads `X-HubSpot-RateLimit-*` headers and throttles proactively
289
- - All write / batch methods include `Idempotency-Key` for replay-safe retries
163
+ <p align="center">
164
+ <img src="docs/demo-terminal.gif" alt="hscli terminal walkthrough blank create associate → read → update → archive → blank" width="100%">
165
+ </p>
290
166
 
291
- Full threat model: [SECURITY.md](SECURITY.md).
167
+ [Source script](scripts/demo.sh) · [recording config](scripts/demo.tape) · [how the recordings are made](scripts/README.md)
292
168
 
293
169
  ## Caches
294
170
 
295
- Under `HSCLI_HOME` (default: `~/.revfleet`; legacy `~/.hubcli` is still honored for existing installs):
171
+ Under `HSCLI_HOME` (default: `~/.revfleet`):
296
172
 
297
- - `auth.json` — profile tokens (0600 permissions, 0700 directory)
173
+ - `auth.json` — profile tokens (0600, in a 0700 directory)
174
+ - `auth.enc` — optional encrypted vault when `HSCLI_VAULT_PASSPHRASE` is set
298
175
  - `capabilities.json` — portal/tier capability cache
299
- - `schema-cache.json` — CRM schema cache for describe/validate
300
- - `auth.enc` optional encrypted vault (when passphrase is set)
301
- - `trace-session.json` — active trace session state (v0.6+)
302
- - `trace-*.jsonl` — recorded request traces (v0.6+)
176
+ - `schema-cache.json` — CRM schema cache for describe / validate
177
+ - `trace-session.json` + `trace-*.jsonl` active trace + recorded sessions
303
178
 
304
179
  ## Documentation
305
180
 
306
181
  - [docs/COMMAND_TREE.md](docs/COMMAND_TREE.md) — full command surface
307
- - [docs/COMPARISON.md](docs/COMPARISON.md) — capability inventory (MCP tool families, CLI groups, coverage, safety, observability)
308
- - [docs/WHY_HOW_WHAT.md](docs/WHY_HOW_WHAT.md) — design philosophy
309
- - [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md)
310
- - [docs/SAFETY_MODEL.md](docs/SAFETY_MODEL.md)
182
+ - [docs/COMPARISON.md](docs/COMPARISON.md) — MCP tool families, CLI groups, coverage, safety, observability
311
183
  - [docs/MCP.md](docs/MCP.md) — MCP server tool catalog
312
- - [docs/ROADMAP-DATE-BASED-API.md](docs/ROADMAP-DATE-BASED-API.md) migration plan for HubSpot's `/YYYY-MM/` versioning
313
- - [docs/PUBLISHING.md](docs/PUBLISHING.md) — release runbook (maintainers)
314
- - [docs/TESTING_PLAN.md](docs/TESTING_PLAN.md)
315
- - [docs/RELEASE_GOVERNANCE.md](docs/RELEASE_GOVERNANCE.md)
184
+ - [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) · [docs/SAFETY_MODEL.md](docs/SAFETY_MODEL.md) · [docs/WHY_HOW_WHAT.md](docs/WHY_HOW_WHAT.md)
185
+ - [docs/ROADMAP-DATE-BASED-API.md](docs/ROADMAP-DATE-BASED-API.md) — HubSpot's `/YYYY-MM/` migration plan
316
186
  - [docs/PLUGIN_GUIDE.md](docs/PLUGIN_GUIDE.md) — writing plugins
317
- - [docs/OPERATIONAL_PLAYBOOKS.md](docs/OPERATIONAL_PLAYBOOKS.md)
318
- - [docs/COOKBOOK.md](docs/COOKBOOK.md) — common recipes
319
- - [CONTRIBUTING.md](CONTRIBUTING.md)
320
- - [SECURITY.md](SECURITY.md)
321
- - [CHANGELOG.md](CHANGELOG.md)
322
-
323
- ### Domain setup guides
324
-
325
- - [docs/PORTAL_SETUP.md](docs/PORTAL_SETUP.md)
326
- - [docs/CMS_SETUP.md](docs/CMS_SETUP.md)
327
- - [docs/COMMERCE_SETUP.md](docs/COMMERCE_SETUP.md)
328
- - [docs/MARKETING_SETUP.md](docs/MARKETING_SETUP.md)
329
- - [docs/SALES_SETUP.md](docs/SALES_SETUP.md)
330
- - [docs/SERVICE_SETUP.md](docs/SERVICE_SETUP.md)
331
- - [docs/OPERATIONS_SETUP.md](docs/OPERATIONS_SETUP.md)
332
- - [docs/REPORTING_SETUP.md](docs/REPORTING_SETUP.md)
333
- - [docs/INTEGRATIONS_NOTIFICATIONS_SETUP.md](docs/INTEGRATIONS_NOTIFICATIONS_SETUP.md)
334
-
335
- ## Verification
336
-
337
- Full release check:
187
+ - [docs/COOKBOOK.md](docs/COOKBOOK.md) — recipes
188
+ - [docs/PUBLISHING.md](docs/PUBLISHING.md) — release runbook (maintainers)
189
+ - [CONTRIBUTING.md](CONTRIBUTING.md) · [SECURITY.md](SECURITY.md) · [CHANGELOG.md](CHANGELOG.md)
338
190
 
339
- ```bash
340
- npm run release:verify
341
- ```
191
+ Domain setup guides: [PORTAL](docs/PORTAL_SETUP.md) · [CMS](docs/CMS_SETUP.md) · [Commerce](docs/COMMERCE_SETUP.md) · [Marketing](docs/MARKETING_SETUP.md) · [Sales](docs/SALES_SETUP.md) · [Service](docs/SERVICE_SETUP.md) · [Operations](docs/OPERATIONS_SETUP.md) · [Reporting](docs/REPORTING_SETUP.md) · [Integrations & Notifications](docs/INTEGRATIONS_NOTIFICATIONS_SETUP.md)
342
192
 
343
- Runs typecheck + lint + tests + audit + build + SHA256 checksum verification.
193
+ Tutorials: [secure agent writes](docs/TUTORIALS/secure-agent-writes.md) · [audit portal writes](docs/TUTORIALS/audit-portal-writes.md) · [trace + replay](docs/TUTORIALS/trace-replay-repro.md)
344
194
 
345
195
  ## Contributing
346
196
 
347
- Issues and PRs welcome. See [CONTRIBUTING.md](CONTRIBUTING.md) for the workflow, coding standards, and how to run contract tests against a sandbox portal.
197
+ Issues and PRs welcome see [CONTRIBUTING.md](CONTRIBUTING.md) for the workflow, coding standards, and live-portal contract tests.
348
198
 
349
199
  ## License
350
200
 
351
201
  MIT — see [LICENSE](LICENSE).
352
-
package/SECURITY.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # SECURITY
2
2
 
3
- > See also: [[SAFETY_MODEL]] · [[RELEASE_GOVERNANCE]] · [[hubspot-rules]]
3
+ > See also: [SAFETY_MODEL.md](SAFETY_MODEL.md) · [RELEASE_GOVERNANCE.md](RELEASE_GOVERNANCE.md)
4
4
 
5
5
  ## Security Objectives
6
6
  - Prevent credential exposure
@@ -14,7 +14,7 @@
14
14
  - JSON mode is preferred for machine handling to avoid ad-hoc parsing leaks.
15
15
 
16
16
  ## Secret Storage Policy
17
- - Tokens are stored in profile-based auth file under `HUBCLI_HOME` or default `~/.hubcli`.
17
+ - Tokens are stored in profile-based auth file under `HSCLI_HOME` or default `~/.hscli`.
18
18
  - File permissions are locked to owner-only (`0700` dir, `0600` auth file).
19
19
  - Prefer `auth login --token-stdin` over inline `--token` to reduce shell-history/process-list exposure.
20
20
  - No token echo in CLI responses.