cheat-on-content
给所有想把"感觉"变成可校准预测的内容创作者。**方法论通用**——打分 → 盲预测 → T+3d 复盘 → 进化 rubric 的循环适用任何能被量化(播放 / 阅读 / 收听 / 点击)的内容。**rubric 是循环的内容,不是循环本身**——当前内置一份观点视频 rubric(参考博主 25+…
Expert patterns for HubSpot CRM integration including OAuth
$ npx -y skills add LiHongwei-cn/lihongwei-cn --skill hubspot-integration --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/hubspot-integrationContext preview
The summary Claude sees to decide when to auto-load this skill.
Expert patterns for HubSpot CRM integration including OAuth
name: hubspot-integration description: Expert patterns for HubSpot CRM integration including OAuth authentication, CRM objects, associations, batch operations, webhooks, and custom objects. Covers Node.js and Python SDKs. risk: unknown source: vibeship-spawner-skills (Apache 2.0) date_added: 2026-02-27
Expert patterns for HubSpot CRM integration including OAuth authentication, CRM objects, associations, batch operations, webhooks, and custom objects. Covers Node.js and Python SDKs.
Secure authentication for public apps
**When to use**: Building public app or multi-account integration
// OAuth 2.0 flow for HubSpot import { Client } from "@hubspot/api-client";
// Environment variables const CLIENT_ID = process.env.HUBSPOT_CLIENT_ID; const CLIENT_SECRET = process.env.HUBSPOT_CLIENT_SECRET; const REDIRECT_URI = process.env.HUBSPOT_REDIRECT_URI; const SCOPES = "crm.objects.contacts.read crm.objects.contacts.write";
// Step 1: Generate authorization URL function getAuthUrl(): string { const authUrl = new URL("https://app.hubspot.com/oauth/authorize"); authUrl.searchParams.set("client_id", CLIENT_ID); authUrl.searchParams.set("redirect_uri", REDIRECT_URI); authUrl.searchParams.set("scope", SCOPES); return authUrl.toString(); }
// Step 2: Handle OAuth callback async function handleOAuthCallback(code: string) { const response = await fetch("https://api.hubapi.com/oauth/v1/token", { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: new URLSearchParams({ grant_type: "authorization_code", client_id: CLIENT_ID, client_secret: CLIENT_SECRET, redirect_uri: REDIRECT_URI, code: code, }), });
const tokens = await response.json(); // { // access_token: "xxx", // refresh_token: "xxx", // expires_in: 1800 // 30 minutes // }
// Store tokens securely await storeTokens(tokens);
return tokens; }
// Step 3: Refresh access token (before expiry) async function refreshAccessToken(refreshToken: string) { const response = await fetch("https://api.hubapi.com/oauth/v1/token", { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: new URLSearchParams({ grant_type: "refresh_token", client_id: CLIENT_ID, client_secret: CLIENT_SECRET, refresh_token: refreshToken, }), });
return response.json(); }
// Step 4: Create authenticated client function createClient(accessToken: string): Client { const hubspotClient = new Client({ accessToken }); return hubspotClient; }
Authentication for single-account integrations
**When to use**: Building internal integration for one HubSpot account
// Private App Token - simpler for single account import { Client } from "@hubspot/api-client";
// Create client with private app token const hubspotClient = new Client({ accessToken: process.env.HUBSPOT_PRIVATE_APP_TOKEN, });
// Private app tokens don't expire // But should be rotated every 6 months for security
// Example: Get contacts async function getContacts() { try { const response = await hubspotClient.crm.contacts.basicApi.getPage( 100, // limit undefined, // after cursor ["firstname", "lastname", "email", "phone"], // properties );
return response.results; } catch (error) { if (error.code === 429) { // Rate limited - implement backoff const retryAfter = error.headers?.["retry-after"] || 10; await sleep(retryAfter * 1000); return getContacts(); } throw error; } }
// Python equivalent // from hubspot import HubSpot // // client = HubSpot(access_token=os.environ["HUBSPOT_PRIVATE_APP_TOKEN"]) // // contacts = client.crm.contacts.basic_api.get_page( // limit=100, // properties=["firstname", "lastname", "email"] // )
Create, read, update, delete CRM records
**When to use**: Working with contacts, companies, deals, tickets
import { Client } from "@hubspot/api-client";
const hubspotClient = new Client({ accessToken: process.env.HUBSPOT_TOKEN, });
// CREATE contact async function createContact(data: { email: string; firstname: string; lastname: string; }) { const response = await hubspotClient.crm.contacts.basicApi.create({ properties: { email: data.email, firstname: data.firstname, lastname: data.lastname, }, });
return response; }
// READ contact by ID async function getContact(contactId: string) { const response = await hubspotClient.crm.contacts.basicApi.getById( contactId, ["firstname", "lastname", "email", "phone", "company"], );
return response; }
// UPDATE contact async function updateContact(contactId: string, properties: object) { const response = await hubspotClient.crm.contacts.basicApi.update( contactId, { properties }, );
return response; }
// DELETE contact async function deleteContact(contactId: string) { await hubspotClient.crm.contacts.basicApi.archive(contactId); }
// SEARCH contacts async function searchContacts(query: string) { const response = await hubspotClient.crm.contacts.searchApi.doSearch({ query, limit: 100, properties: ["firstname", "lastname", "email"], sorts: [{ propertyName: "createdate", direction: "DESCENDING" }], });
return response.results; }
// LIST with pagination async function getAllContacts() { const allContacts = []; let after = undefined;
do { const response = await hubspotClient.crm.contacts.basicApi.getPage(
MUNDO - THE EMPEROR. Complete AI orchestration system with 1208 skills, 25 capability modules, self-evolving, collective consciousness. GitHub Actions 24/7 automation.
Repo: LiHongwei-cn/lihongwei-cn
给所有想把"感觉"变成可校准预测的内容创作者。**方法论通用**——打分 → 盲预测 → T+3d 复盘 → 进化 rubric 的循环适用任何能被量化(播放 / 阅读 / 收听 / 点击)的内容。**rubric 是循环的内容,不是循环本身**——当前内置一份观点视频 rubric(参考博主 25+…
提议并执行 rubric 或 bucket 升级。两种模式:**完整 rubric bump**(最高风险动作,5 步强制 + 跨模型审核)和 **--bucket-only 轻量重校**(只换 bucket 边界,不动 rubric 公式)。**Phase 2 强制走 cheat-score-blind…
cheat-on-content 的首次 onboarding 与脚手架创建器。统一流程——所有用户都走相同 5 阶段闭环,唯一区别是"发过视频的人"会在 init 时多一步:抓取已有视频建立历史 context(用于后续 cheat-seed 给更贴合的选题、更准的…
从对标账号导入 script + 数据 → 拆 pattern + 派生 base rubric 信号 → 写到 benchmark.md / script_patterns.md / rubric_notes.md。**这是工具最早期信号的来源**——cold-start…
把老用户的 .cheat-state.json 升级到当前 schema_version。读 migrations/registry.md 算迁移链,按顺序应用每一步迁移文件。幂等:跑两次结果一样。失败停在中间版本不前进。触发词:"迁移"/"升级 state"/"migrate"/"我的 state…
从复盘评论数据派生 / 刷新账号的受众画像,写入 audience.md。这是和 rubric 平行的第二个派生物——rubric 答"怎么打分",persona 答"谁在看"。cheat-seed 选题 / 写稿时读它。**audience.md 含实绩信号,cheat-score-blind…