Skip to content

The plugin#

bb-hubspot packages this process for Claude Code. It does three things: skills tell the agent how each stage is done, a guard hook stops the commands that could hurt a live portal, and the scripts do the work. These docs are written for people; the skills are the short procedural version for the agent.

Install#

/plugin install bb-hubspot --marketplace thomasjefferson/bb-hubspot

To develop the plugin itself, run it from a clone with claude --plugin-dir /path/to/bb-hubspot.

Skills#

Claude loads a skill when the task matches its description. Each one is short and points to the scripts.

Skill Loads when Covers
hubspot-site-setup Starting on a new site, or in a repo without hubspot-site.json Accounts and safety, Theme baseline, the templates
hubspot-audit Crawling, writing design rules, regenerating the catalog Crawl and audit, Design rules, Catalog and previews
hubspot-module-change Before editing any module Module conventions
hubspot-page-build Turning copy into a page, publishing to dev Copy doc to dev page
hubspot-live-change Only when you type /bb-hubspot:hubspot-live-change Going to live

The live skill can't be started by the model on its own. A change to production starts with a person asking for it.

The guard hook#

The guard runs before every shell command Claude runs. It does nothing outside a folder that holds a hubspot-site.json. Inside one, it refuses:

Refused Why
An hs command that reaches a portal without --account / -a The CLI would use its default account, which every repo on the machine shares.
An account that isn't one of this site's (by name or portal id) An unknown name silently falls through to the default account.
On live: anything but reads, File Manager uploads and hs cms upload of one module or file Live is read-only except for the gated changes.
A live module upload without today's before-* snapshot and today's backup of that module in backups/live-modules/<date>/ The regression gate, enforced.
hs api with a write method on live Live page writes go through the draft-only scripts.
Any command that names the live service-key variable The same: only the scripts read the key.

The scripts don't depend on the hook. Each one checks the account allowlist, hs account list and the sentinel page itself, so they are just as safe when run by hand.

What the guard can't see

The guard reads the command text. A command hidden inside a script file, or built at run time, gets past it. That's why the scripts guard themselves, and why live writes need the service key, which only the scripts read.

Run its tests with python3 tests/test_guard.py. They cover 23 commands, allowed and refused, against a throwaway site.

What stays per site#

The crawler, the copy-doc exporter, the preview generator and the draft generator depend on one theme's markup, so each site writes its own (see Tools). They write the formats the plugin scripts read: @section annotations, pages.json and reports/site-crawl.json.