@revfleet/hscli 0.8.0 → 0.8.2
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/CHANGELOG.md +89 -0
- package/LICENSE +1 -1
- package/README.md +118 -269
- package/SECURITY.md +2 -2
- package/dist/cli.js +25 -5
- package/dist/cli.js.map +1 -1
- package/dist/commands/api/index.d.ts +3 -0
- package/dist/commands/api/index.js.map +1 -1
- package/dist/commands/auth/index.js +6 -6
- package/dist/commands/auth/index.js.map +1 -1
- package/dist/commands/crm/companies.d.ts +3 -0
- package/dist/commands/crm/companies.js.map +1 -1
- package/dist/commands/crm/contacts.d.ts +3 -0
- package/dist/commands/crm/contacts.js.map +1 -1
- package/dist/commands/crm/custom-objects.d.ts +3 -0
- package/dist/commands/crm/custom-objects.js.map +1 -1
- package/dist/commands/crm/dated.d.ts +1 -1
- package/dist/commands/crm/dated.js +1 -1
- package/dist/commands/crm/deals.d.ts +3 -0
- package/dist/commands/crm/deals.js.map +1 -1
- package/dist/commands/crm/describe.d.ts +3 -0
- package/dist/commands/crm/describe.js.map +1 -1
- package/dist/commands/crm/engagements.d.ts +3 -0
- package/dist/commands/crm/engagements.js.map +1 -1
- package/dist/commands/crm/imports.d.ts +3 -0
- package/dist/commands/crm/imports.js.map +1 -1
- package/dist/commands/crm/owners.d.ts +3 -0
- package/dist/commands/crm/owners.js.map +1 -1
- package/dist/commands/crm/tickets.d.ts +3 -0
- package/dist/commands/crm/tickets.js.map +1 -1
- package/dist/commands/doctor/index.js +35 -35
- package/dist/commands/doctor/index.js.map +1 -1
- package/dist/commands/domains/shared.d.ts +3 -0
- package/dist/commands/domains/shared.js.map +1 -1
- package/dist/commands/events/index.d.ts +3 -0
- package/dist/commands/events/index.js.map +1 -1
- package/dist/commands/forms/index.d.ts +3 -0
- package/dist/commands/forms/index.js.map +1 -1
- package/dist/commands/legacy-v1/index.d.ts +1 -1
- package/dist/commands/legacy-v1/index.js +1 -1
- package/dist/commands/mcp.d.ts +3 -0
- package/dist/commands/mcp.js.map +1 -1
- package/dist/commands/seed/cms.js +19 -19
- package/dist/commands/seed/cms.js.map +1 -1
- package/dist/commands/seed/index.js +1 -1
- package/dist/commands/seed/index.js.map +1 -1
- package/dist/commands/seed/infra.js +14 -14
- package/dist/commands/seed/infra.js.map +1 -1
- package/dist/commands/seed/marketing.js +13 -13
- package/dist/commands/seed/marketing.js.map +1 -1
- package/dist/commands/webhooks/index.d.ts +3 -0
- package/dist/commands/webhooks/index.js.map +1 -1
- package/dist/commands/workflows/index.d.ts +3 -0
- package/dist/commands/workflows/index.js.map +1 -1
- package/dist/core/auth.d.ts +1 -1
- package/dist/core/auth.js +8 -25
- package/dist/core/auth.js.map +1 -1
- package/dist/core/capabilities.js +15 -15
- package/dist/core/capabilities.js.map +1 -1
- package/dist/core/http.js +3 -3
- package/dist/core/http.js.map +1 -1
- package/dist/core/output.d.ts +3 -0
- package/dist/core/output.js.map +1 -1
- package/dist/core/permissions.js +1 -1
- package/dist/core/permissions.js.map +1 -1
- package/dist/core/plugins.d.ts +2 -2
- package/dist/core/plugins.js +2 -2
- package/dist/core/plugins.js.map +1 -1
- package/dist/core/schema-cache.js +3 -3
- package/dist/core/schema-cache.js.map +1 -1
- package/dist/core/schemas.js +1 -1
- package/dist/core/schemas.js.map +1 -1
- package/dist/core/urls.d.ts +4 -4
- package/dist/core/urls.js +4 -4
- package/dist/core/vault.d.ts +5 -5
- package/dist/core/vault.js +14 -14
- package/dist/core/vault.js.map +1 -1
- package/dist/mcp/server.d.ts +1 -1
- package/dist/mcp/server.js +7 -7
- package/dist/mcp/server.js.map +1 -1
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,94 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.8.2 - 2026-04-23
|
|
4
|
+
|
|
5
|
+
**Brand + polish release.** No runtime behavior changes for end users
|
|
6
|
+
beyond what CI already enforces — this is a pre-launch cut that ships
|
|
7
|
+
everything that's been on `main` since 0.8.1 alongside a consistent
|
|
8
|
+
visual identity and a codebase with zero "hubcli" references.
|
|
9
|
+
|
|
10
|
+
### Visible change for `npm install -g` users
|
|
11
|
+
|
|
12
|
+
`hscli --help` now opens with the bracketed monogram banner:
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
┌──┐
|
|
16
|
+
│hs│ hscli · agentic HubSpot CLI + MCP server
|
|
17
|
+
└──┘ @revfleet/hscli · MIT · github.com/revfleet/hscli
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
The banner matches the repo avatar and the `[hs]` monogram used on the
|
|
21
|
+
README hero + social preview. Same safety model, same command surface —
|
|
22
|
+
only the help-screen framing changes.
|
|
23
|
+
|
|
24
|
+
### Documentation + repo polish
|
|
25
|
+
|
|
26
|
+
- **README** reworked with a confident headline ("Your HubSpot portal,
|
|
27
|
+
in one binary.") + three focused badges (npm · MIT · 1,180
|
|
28
|
+
endpoints). Progressive disclosure via a single `<details>` for the
|
|
29
|
+
full coverage list.
|
|
30
|
+
- **Brand identity** — `brand/` now contains the monogram, wordmark,
|
|
31
|
+
hero band, social preview (PNG + SVG), revfleet org avatar, and the
|
|
32
|
+
ASCII banner.
|
|
33
|
+
- **CODE_OF_CONDUCT.md** — Contributor Covenant v2.1 reference + a
|
|
34
|
+
short project-specific summary.
|
|
35
|
+
- **Doc cross-refs** — obsolete `[[wiki-link]]` style converted to real
|
|
36
|
+
markdown links throughout `docs/`. Dead `[[hubspot-rules]]`
|
|
37
|
+
references dropped.
|
|
38
|
+
- **POLICY_EXAMPLE.json** upgraded to the v2 schema introduced in
|
|
39
|
+
v0.7.0 (rule-based method+path globs, time windows, change-ticket +
|
|
40
|
+
approval gates).
|
|
41
|
+
|
|
42
|
+
### Internal polish
|
|
43
|
+
|
|
44
|
+
- **ESLint** — stricter rules enabled: `eqeqeq` (safer for HubSpot IDs
|
|
45
|
+
that look numeric) and `prefer-const`.
|
|
46
|
+
- **Dependabot** — Monday schedule, labels for PR triage, TypeScript
|
|
47
|
+
major bumps excluded (manual triage, same pattern used for the 5→6
|
|
48
|
+
breakage).
|
|
49
|
+
- **`src/core/auth.ts`** — the `~/.hubcli/` legacy-fallback path was
|
|
50
|
+
dropped. The `getHubcliHomeDir` export alias was removed too.
|
|
51
|
+
Technically a breaking change for any external consumer that
|
|
52
|
+
imported the old name; none known to exist.
|
|
53
|
+
- **Release-checksums** script documented with a header comment.
|
|
54
|
+
- **Module headers** added to 17 command / core modules.
|
|
55
|
+
|
|
56
|
+
### Privacy + scrub
|
|
57
|
+
|
|
58
|
+
- Package author field: `"Luigi Vermeulen (revfleet)"` → `"revfleet"`.
|
|
59
|
+
- Portal ID `147975758` removed from every code path where it
|
|
60
|
+
appeared as illustration or test fixture (replaced with `12345678`).
|
|
61
|
+
- Deleted `docs/TESTING/PORTAL-147975758-*.md` snapshot files.
|
|
62
|
+
- Deleted `docs/LAUNCH/` — four pre-launch marketing drafts with
|
|
63
|
+
named-competitor comparisons (Composio, peakmojo, lkm1developer,
|
|
64
|
+
CData, …) and CRMforge references. The repo now describes hscli on
|
|
65
|
+
its own terms only.
|
|
66
|
+
- Deleted `.hubcli-sync-contacts.json` (stale local state, last
|
|
67
|
+
touched 2026-03-19).
|
|
68
|
+
|
|
69
|
+
Git history was rewritten (49 commits, 10 tags repointed) so zero
|
|
70
|
+
"hubcli" references remain anywhere — code, docs, filenames, commit
|
|
71
|
+
messages, tags.
|
|
72
|
+
|
|
73
|
+
Tests: 255 pass. Typecheck + lint clean.
|
|
74
|
+
|
|
75
|
+
## 0.8.1 - 2026-04-22
|
|
76
|
+
|
|
77
|
+
**Critical fix — globally-installed `hscli` binary was silent on all commands.**
|
|
78
|
+
|
|
79
|
+
The entry-point guard in `src/cli.ts` compared `import.meta.url` against
|
|
80
|
+
`resolve(process.argv[1])`, but `resolve()` does not follow symlinks.
|
|
81
|
+
A global npm install creates `~/.npm-global/bin/hscli` as a symlink into
|
|
82
|
+
`.../node_modules/@revfleet/hscli/dist/cli.js`; with the un-resolved
|
|
83
|
+
compare, the two paths never matched, so `run()` never fired and the
|
|
84
|
+
binary exited with code 0 and no output. Fix: resolve both sides with
|
|
85
|
+
`fs.realpathSync` and `fileURLToPath(import.meta.url)` before comparing.
|
|
86
|
+
|
|
87
|
+
This broke every `hscli <command>` invocation on every version since the
|
|
88
|
+
first publish (v0.5.3). It was masked locally because `npm run dev` /
|
|
89
|
+
`node dist/cli.js` don't go through the symlink. Anyone on npm installs
|
|
90
|
+
should upgrade immediately.
|
|
91
|
+
|
|
3
92
|
## 0.8.0 - 2026-04-22
|
|
4
93
|
|
|
5
94
|
**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
package/README.md
CHANGED
|
@@ -1,352 +1,201 @@
|
|
|
1
|
-
|
|
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
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
[](package.json)
|
|
7
|
-
[-7c3aed)](docs/TIERS.md)
|
|
5
|
+
<p align="center">
|
|
6
|
+
<strong>Your HubSpot portal, in one binary.</strong>
|
|
7
|
+
</p>
|
|
8
8
|
|
|
9
|
-
|
|
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
|
-
|
|
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
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
41
|
+
## Write safely
|
|
118
42
|
|
|
119
43
|
```bash
|
|
120
|
-
|
|
121
|
-
hscli
|
|
122
|
-
|
|
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
|
-
|
|
48
|
+
# Preview what the call would look like
|
|
49
|
+
hscli --dry-run crm contacts create --data '{"properties":{"email":"jane@acme.com"}}'
|
|
128
50
|
|
|
129
|
-
|
|
130
|
-
hscli --
|
|
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
|
-
|
|
55
|
+
Policy file + change-ticket enforcement for ops teams:
|
|
134
56
|
|
|
135
57
|
```bash
|
|
136
|
-
hscli --force
|
|
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
|
-
|
|
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
|
-
|
|
64
|
+
Drop `hscli` into any MCP client — Claude Desktop, Cursor, Claude Code, or your own agent runtime.
|
|
150
65
|
|
|
151
66
|
```bash
|
|
152
|
-
|
|
153
|
-
|
|
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
|
-
|
|
159
|
-
hscli policy validate ./policy.json
|
|
70
|
+
For Claude Desktop, add to `claude_desktop_config.json`:
|
|
160
71
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
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
|
-
|
|
84
|
+
The MCP server exposes three tool families:
|
|
167
85
|
|
|
168
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
#
|
|
179
|
-
hscli
|
|
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
|
-
#
|
|
189
|
-
hscli trace
|
|
190
|
-
hscli
|
|
191
|
-
hscli
|
|
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
|
-
|
|
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
|
-
|
|
201
|
-
|
|
202
|
-
</details>
|
|
107
|
+
## What's in the box
|
|
203
108
|
|
|
204
109
|
<details>
|
|
205
|
-
<summary><strong>
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
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
|
-
|
|
141
|
+
Exact endpoint → tier mapping in [docs/TIERS.md](docs/TIERS.md).
|
|
260
142
|
|
|
261
|
-
|
|
262
|
-
hscli doctor capabilities --refresh
|
|
263
|
-
```
|
|
143
|
+
## Design principles
|
|
264
144
|
|
|
265
|
-
|
|
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
|
-
|
|
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
|
|
275
|
-
hscli crm
|
|
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
|
-
|
|
159
|
+
## Terminal session
|
|
279
160
|
|
|
280
|
-
|
|
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
|
-
|
|
283
|
-
|
|
284
|
-
|
|
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
|
-
|
|
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
|
|
171
|
+
Under `HSCLI_HOME` (default: `~/.revfleet`):
|
|
296
172
|
|
|
297
|
-
- `auth.json` — profile tokens (0600
|
|
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
|
-
- `
|
|
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) —
|
|
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/
|
|
313
|
-
- [docs/
|
|
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/
|
|
318
|
-
- [docs/
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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: [
|
|
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 `
|
|
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.
|
package/dist/cli.js
CHANGED
|
@@ -47,7 +47,13 @@ export function createProgram() {
|
|
|
47
47
|
const runId = randomUUID();
|
|
48
48
|
program
|
|
49
49
|
.name("hscli")
|
|
50
|
-
.description(
|
|
50
|
+
.description(
|
|
51
|
+
// Brand banner — rendered at the top of `hscli --help`. ASCII art
|
|
52
|
+
// matches the bracketed monogram in brand/logo-monogram.svg so the
|
|
53
|
+
// CLI, avatar, and docs all share the same visual identity.
|
|
54
|
+
" ┌──┐\n"
|
|
55
|
+
+ " │hs│ hscli · agentic HubSpot CLI + MCP server\n"
|
|
56
|
+
+ " └──┘ @revfleet/hscli · MIT · github.com/revfleet/hscli")
|
|
51
57
|
.version(pkg.version)
|
|
52
58
|
.option("--profile <name>", "Auth profile", "default")
|
|
53
59
|
.option("--json", "JSON output")
|
|
@@ -178,10 +184,24 @@ export async function run(argv = process.argv) {
|
|
|
178
184
|
process.exitCode = 1;
|
|
179
185
|
}
|
|
180
186
|
}
|
|
181
|
-
import {
|
|
182
|
-
import {
|
|
183
|
-
|
|
184
|
-
|
|
187
|
+
import { fileURLToPath } from "node:url";
|
|
188
|
+
import { realpathSync } from "node:fs";
|
|
189
|
+
// Only auto-run when invoked directly, not when imported. We need realpath
|
|
190
|
+
// on BOTH sides: `import.meta.url` follows symlinks automatically (it's
|
|
191
|
+
// the real file), but `process.argv[1]` is the string the user typed —
|
|
192
|
+
// which, for a globally-installed npm bin, is the symlink in
|
|
193
|
+
// /usr/local/bin/ or ~/.npm-global/bin/, not the resolved target. Without
|
|
194
|
+
// realpath on argv[1], the comparison never matches and `run()` never
|
|
195
|
+
// fires → the CLI exits silently with code 0.
|
|
196
|
+
try {
|
|
197
|
+
const entryReal = realpathSync(process.argv[1] ?? "");
|
|
198
|
+
const selfReal = fileURLToPath(import.meta.url);
|
|
199
|
+
if (entryReal === selfReal) {
|
|
200
|
+
void run();
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
catch {
|
|
204
|
+
// If realpath fails (e.g. imported as ESM for testing), silently skip.
|
|
185
205
|
}
|
|
186
206
|
function resolveOutputFormat(raw, jsonFlag) {
|
|
187
207
|
const fallback = "table";
|