一键导入
dent
Operate Dent via first-party API. Trigger: Dent API, Funnels, Offers, Pages, Articles, Courses, Spaces, Analytics. Do not trigger for WordPress-only work.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Operate Dent via first-party API. Trigger: Dent API, Funnels, Offers, Pages, Articles, Courses, Spaces, Analytics. Do not trigger for WordPress-only work.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Use when encountering any bug, test failure, or unexpected behavior, before proposing fixes
Broad-to-narrow research Orchestration - start with a wide census, harden the scope from returned Evidence, and specialize Subagents only once the exact situation is proven. TRIGGER when the Architect says "progressive research", "start broad", or when dispatching research or debugging Subagents into a situation whose cause or shape is unknown. DO NOT TRIGGER when the exact scope is already proven - dispatch the specialized Subagent per /subagents directly.
Consolidate the knowledge wiki — revisit journaled topics, fold repeated findings into each topic's Claude.md, surface contradictions, keep cross-links true. TRIGGER on a scheduled pass or when a topic tree has grown messy or redundant. DO NOT TRIGGER to file fresh session material (that is journal), or to gather new research.
File a session's loose material into the knowledge wiki — each capture into its owning topic folder, the topic's Claude.md kept current. TRIGGER after a session hands you loose captures (notes, clippings, findings, screenshots) that need a home in the wiki. DO NOT TRIGGER to gather new research, or to consolidate the wiki itself (that is dream).
Autonomous async Execution. The Architect hands off and walks away; the Agent drives the Task to done — makes every Architectural call via /trace + /pcc + ranking, executes through /subagents, verifies from each implementing Subagent's Evidence (they exercise their own flows, real browser for UI), and returns finished code plus the recorded Decisions for review. TRIGGER when the Architect says "code-first", "/code-first", "execute with /subagents", "execute directly & autonomously", "drive it and report back", "iterate until done", "I'm going to bed", "off to bed", or signals an AFK / overnight handoff. DO NOT TRIGGER when the Architect wants options before action — that is the default mode (propose via /pcc and wait).
Drive codex CLI runs as your Agents — you own Orchestration, codex does the work. One wrapper, `codex-run`, owns the mechanics (flags, output storage, stream parsing, failure detection); you write the Task Prompt and do the judgment. Calls /subagents for Orchestration doctrine on a codex-run substrate. TRIGGER when the Architect says "codex", "/codex", "codex-run", "use codex", "dispatch to codex", "run this through codex", "codex agents", "review with codex", "codex review", or asks to fan out work across codex runs. DO NOT TRIGGER for native Claude Code Subagents (use /subagents) — those run inside this Harness; codex is a separate CLI process.
| name | dent |
| description | Operate Dent via first-party API. Trigger: Dent API, Funnels, Offers, Pages, Articles, Courses, Spaces, Analytics. Do not trigger for WordPress-only work. |
Dent spins up marketing Sites that sell and deliver digital Products. Operate it through the first-party schema-driven API. Vocabulary is strict: Funnel, Funnel Step, Offer, Product, Order, Cart, Checkout, Journey, Experiment, Conversion, Link, Session, Visitor Event, Attribution, Designer, Design, Designable, Site, Page, Article, Space, Course.
Establish the session before touching data.
IF dent is not on PATH, run each Dent CLI command as npx @parkerlabs/dent@latest <command>.
Run the local checks:
dent check
dent whoami
If the session-start check or dent check says the skill is stale, update the skill before a write. Use the update reference instead of asking the user to touch a terminal.
If dent whoami fails, run dent login. The standalone CLI starts Dent's OAuth 2.0 Authorization Code + PKCE login against production Dent by default (https://ondent.app): it opens the browser, the operator signs in and clicks Authorize, the loopback callback receives the authorization code, and the CLI exchanges code + verifier before saving the token. This is the same flow an agent can guide; the agent layer does not replace the CLI.
If loopback cannot reach the CLI (remote browser, web agent, locked-down machine), run dent login --copy-code. The operator authorizes in the browser, copies the short code Dent shows, and pastes it into the CLI. The code still exchanges only with that CLI's PKCE verifier.
Never ask the operator to create a personal access token for normal login. Never put a token in argv. Explicit token input remains only for power-user recovery with --token-prompt or --stdin.
dent login
dent login --copy-code
Use dent setup only when developing against a local Dent repo. It switches the CLI and skill to the local target while preserving the live credential. Use dent reset to switch back to the live target without re-authenticating either target.
Use dent logout when the active target's stored credential should be removed.
Power users may set the credential variables below. DENT_TARGET selects live or local; DENT_SITE_URL and DENT_API_KEY each override the matching active stored credential and fall back to stored config for the other:
export DENT_TARGET=live
export DENT_SITE_URL=https://example.com
export DENT_API_KEY=...
Fetch the schema catalog first; never guess entity names, fields, actions, or routes.
GET /api/v1/schema/.dent setup and dent reset; do not hardcode local Dent URLs in the skill.fields, actions, parameters, mode, target, and access before writing. The Funnel Step status field is in the catalog; set it through the generic step update route.{attributes: ...} unless the catalog parameter is literally named attributes and the action expects that wrapper from a non-generic endpoint. For Dent generic create/update/actions, send the fields directly.dent schema
dent schema funnels
dent api funnels
dent api courses 9203 sections
dent api dent breakdown --param dimension=source --param period=last_month --param includeAdmin=true --param limit=5
dent api resolves HTTP methods from the tenant schema catalog for each invocation: read actions use GET, write and remote actions use POST, and destroy actions use DELETE. --method is the explicit override. Do not infer a write from positional shape; a bare nested collection like dent api courses 9203 sections is a list (GET). Creates require --data or an explicit method.
Use the generic route grammar the catalog confirms, and route every Page surface through interview, writing, then design.
GET /api/v1/{entities} lists records.GET /api/v1/{entities}/{id} reads one record.POST /api/v1/{entities} creates a record.POST /api/v1/{entities}/{id} updates a record.DELETE /api/v1/{entities}/{id} deletes when the catalog and the user intent allow it.GET|POST|DELETE /api/v1/{entities}/{action} invokes a collection action.GET|POST|DELETE /api/v1/{entities}/{id}/{action} invokes a member action.POST /api/v1/funnels/{funnelId}/stepsPOST /api/v1/funnels/{funnelId}/steps/{stepId}POST /api/v1/courses/{courseId}/sectionsGET /api/v1/courses/{courseId}/sectionsGET /api/v1/courses/{courseId}/sections/{sectionId}POST /api/v1/sections/{sectionId}/lessonsGET /api/v1/sections/{sectionId}/lessonsGET /api/v1/sections/{sectionId}/lessons/{lessonId}references/interview.md.references/writing/copywriting.md plus the matching writing leaf.references/design/designing.md plus the matching design leaf.references/writing/optin-page.md and references/design/optin-page.md.references/writing/sales-page.md and references/design/sales-page.md.references/writing/sales-page.md and the Checkout starter inside references/design/sales-page.md.references/writing/upsell-page.md and references/design/upsell-page.md.references/writing/thank-you-page.md and references/design/thank-you-page.md.references/writing/article.md and references/design/article.md.Designer write contracts:
{owner, design, revision}; send {revision, design} to replace-design. A stale revision returns 409; read again and deliberately reapply the change rather than retrying the stale document.form value is the id the author gave the form, not a label or the Designer element key. Send the rendered owner, holder when present, and link_id hidden values unchanged.POST /api/v1/checkout/{cartId}/submit. Establish the Cart by visiting the public Checkout URL first and keep that cookie jar.POST /api/v1/media/upload-url with filename → PUT bytes to the returned URL → POST /api/v1/media/process with the returned key. Never POST /api/v1/media directly.position: "head" or position: "body" and exactly one of a reusable script key or inline code. The renderer emits position: "body" scripts at the end of the document body (external ones with defer) and position: "head" scripts in the head. So DOM-touching code in a head script needs a DOMContentLoaded guard; a body script already runs after the page markup.raw-html is for inert markup only. It rejects <script> tags and event-handler attributes such as onclick. URL-bearing attributes allow only http, https, mailto, tel, relative, and anchor URLs; other schemes such as javascript, data, and vbscript return 422. Rejection happens at the write boundary, not by silent stripping. Use a script element for JavaScript.{{ ... }} tags interpolate only in an element's first-class fields — text, classes, style, and attributes. A raw-html element's markup and a script element's code are emitted verbatim and are never interpolated; put dynamic values in real fields, or read them in the script itself. In a field, an unknown {{ var }} resolves to the empty string and an unbound @root chain stays verbatim. Publish validation still scans {{ }} everywhere, raw-html and script code included, so write \{{ for a literal {{ — it passes strict validation in any carrier, and in a field it also renders as {{.GET /api/v1/settings/theme returns the writable theme block under theme. Send that same public shape to POST /api/v1/settings/save-theme: colors, colorsDark, radius, fontSize, tracking, shadow, fontSans, fontMono, fontSerif, presetStyle, presetBaseColor, presetThemeColor, locks, and the returned artifact when round-tripping the whole block. Unknown keys return 422.Build an opt-in Funnel with a thank-you Funnel Step.
Start with the page creation sequence for both public steps:
Create the Funnel: POST /api/v1/funnels with { "name": "Lead magnet opt-in" }.
Use homeStepId from the response as the opt-in Funnel Step.
Create the thank-you Funnel Step: POST /api/v1/funnels/{funnelId}/steps with { "title": "Thank You" }.
Author the opt-in Design through the Funnel Step, not WordPress. Every {{ fields.* }} value used by a behavior must have a matching input whose config.name is that field.
Read the current Funnel Step Design, then send { "revision": revision, "design": design } to POST /api/v1/funnels/{funnelId}/steps/{stepId}/replace-design.
Put a polished thank-you Design on the thank-you Funnel Step so the public URL is not empty.
Read the current Thank-you Step Design, then send its revision with the finished Design to POST /api/v1/funnels/{funnelId}/steps/{thankYouStepId}/replace-design.
Publish every public Funnel Step before opening viewUrl or submitting the form:
{"status": "published"}
Send it to POST /api/v1/funnels/{funnelId}/steps/{stepId} for the opt-in and thank-you Funnel Steps. Public URLs and public form submits require a published Funnel Step on an active Funnel.
Read the Funnel Step with GET /api/v1/funnels/{funnelId}/steps/{stepId} after replace-design and publishing. Confirm status: "published", viewUrl, hasOptinAction: true for an opt-in step, and hasBuilder before opening the public URL. replace-design returns the saved Design, not the Step metadata.
Verify the public opt-in path with a real pageview and form submit:
GET the opt-in Step viewUrl with a cookie jar to render the form and establish the Visitor Session.POST /api/v1/forms/submit with the same cookies and body { "owner": {"type": "step", "id": stepId}, "form": "<authored form id>", "fields": {"email": "visitor@example.com", "name": "Visitor Name"} }. form is the authored form id per the write contract above.success: true and the returned redirectUrl as the submit proof; follow redirectUrl when the form redirects.GET /api/v1/contacts?search=visitor@example.com.Every Site render sets the _vid visitor cookie server-side, so a cookie-jar curl is tracked as a Visitor — but only if its User-Agent is not bot-flagged. The crawler filter rejects curl's default curl/* agent, so send a real browser User-Agent header or the request identifies no Visitor. A tracked Visitor is still anonymous: a {{ contact.* }} personalized render needs that Visitor linked to a Contact, which happens when the same cookie jar submits an opt-in or Checkout (email capture). Submit first, keep the cookies, then the personalized render resolves.
Build a sales Funnel with Order bump, upsell, and thank-you Funnel Step.
Start with the page creation sequence for each public step:
Create each Product: POST /api/v1/products with top-level fields such as { "name": "Core Course", "value": 97, "status": "publish" }.
Create each Offer: POST /api/v1/offers with { "name": "Core Offer", "price": 97, "active": true, "products": [{"productId": productId}] }.
Create the Funnel and Funnel Steps:
POST /api/v1/funnels for the Funnel.POST /api/v1/funnels/{funnelId}/steps for Checkout.POST /api/v1/funnels/{funnelId}/steps for Upsell.POST /api/v1/funnels/{funnelId}/steps for Thank You.Attach the main Offer and bump to Checkout:
{"offers": [{"offerId": 123}], "bumps": [{"offerId": 456}]}
Send it to POST /api/v1/funnels/{funnelId}/steps/{checkoutStepId}.
Attach the upsell Offer to the Upsell Funnel Step with POST /api/v1/funnels/{funnelId}/steps/{upsellStepId} and { "offers": [{"offerId": upsellOfferId}] }.
Read each Step Design first, then send each finished Design with that read's revision to its owner:
Checkout Design → POST /api/v1/funnels/{funnelId}/steps/{checkoutStepId}/replace-design.
Upsell Design → POST /api/v1/funnels/{funnelId}/steps/{upsellStepId}/replace-design.
Thank-you Design → POST /api/v1/funnels/{funnelId}/steps/{thankYouStepId}/replace-design.
Publish every public Funnel Step before opening viewUrl or submitting Checkout:
{"status": "published"}
Send it to POST /api/v1/funnels/{funnelId}/steps/{stepId} for the Checkout, Upsell, and Thank You Funnel Steps. Public URLs, form submits, and Checkout require a published Funnel Step on an active Funnel.
Start Checkout like a real Visitor: GET the Checkout Funnel Step viewUrl first and keep the response cookies. That pageview creates the Funnel Session/Journey/Cart context. Send later POST /api/v1/funnel/cart mutations and Checkout submit calls with those same cookies; without the step pageview they return 401 No active funnel session.
Build a Dent-selling Funnel that delivers Dent access and triggers tenant provisioning.
Start with the page creation sequence for the Dent-selling Checkout, Upsell, and Thank You Funnel Steps so the Funnel presents the Offer like a polished sales surface, not a wireframe.
Provisioning is Product delivery. Configure the Product included in the sold Offer with the access grants and provisioning webhook it must deliver after purchase; do not add a separate operator API step.
Create or choose the Webhook Endpoint for the provisioning webhook target. customHeaders is write-only; use it only for the secret that target expects:
{
"name": "Dent Provisioning",
"url": "https://provisioning.example.com/dent/product-delivery",
"events": [],
"customHeaders": {"Authorization": "Bearer <provisioning-secret>"},
"enabled": true
}
Send it to POST /api/v1/webhook-endpoints.
Create the Dent Product with Product delivery configuration. Use courseIds or spaceIds for Dent access grants the buyer receives, and webhooks for the provisioning webhook payload:
{
"name": "Dent Pro",
"value": 197,
"status": "publish",
"courseIds": [321],
"spaceIds": [654],
"webhooks": [{
"endpointId": 17,
"parameters": {
"email": "{{ contact.email }}",
"first_name": "{{ contact.firstName }}",
"last_name": "{{ contact.lastName }}",
"plan": "pro",
"order_id": "{{ order.id }}",
"source": "dent-selling-funnel",
"slug": "buyer-tenant-slug",
"name": "Buyer Tenant"
}
}]
}
Send it to POST /api/v1/products.
Create the Offer for that Product, then build Checkout, Upsell, and Thank You Funnel Steps exactly as in step 5.
Publish every public Funnel Step exactly as in step 5 before opening viewUrl, changing the Cart, or submitting Checkout.
Before Cart or Checkout API calls, GET the Checkout Funnel Step viewUrl with a cookie jar and reuse those cookies for POST /api/v1/funnel/cart and Checkout submit calls.
A TestGateway purchase of the Offer creates the Order, runs Product delivery, grants the configured Course or Space access, posts product.delivery to the configured provisioning webhook, and records the Webhook Delivery response. Treat tenant creation as the provisioning webhook's downstream effect, not as a separate operator API step in this skill.
Create Articles and Pages as Designables.
design field or calling replace-design:
POST /api/v1/articles with top-level { "title", "status", "excerpt", "slug", "design" }. Dent renders the Article content from the Design.POST /api/v1/pages with { "title", "status", "slug" }, read GET /api/v1/pages/{pageId}/design, then POST /api/v1/pages/{pageId}/replace-design with { "revision": revision, "design": {"version": 1, "elements": [...] } }.GET /api/v1/pages/{pageId}/design or GET /api/v1/articles/{articleId}.Iterate on Funnel Step Design until the operator approves.
GET /api/v1/funnels/{funnelId}/steps/{stepId}/design.references/writing/copywriting.md and the matching writing leaf before changing layout.references/design/designing.md and the matching design leaf.POST /api/v1/funnels/{funnelId}/steps/{stepId}/replace-design with { "revision": "<revision from the read>", "design": ... }.viewUrl, publish the Funnel Step first with POST /api/v1/funnels/{funnelId}/steps/{stepId} and { "status": "published" }.GET /api/v1/funnels/{funnelId}/steps/{stepId}.viewUrl, inspect the rendered Site result, then repeat. If a render needs WordPress-only admin routes, stop and report the gap instead of using them.Create Components and Templates.
Template create works first-party: POST /api/v1/templates with { "name", "type": "single", "entityType": "page", "status": "publish", "design" }.
Read Template Design with GET /api/v1/templates/{templateId}/design.
Component create works first-party: POST /api/v1/components with { "key", "name", "status": "publish", "design" }.
Component Design uses variants:
{
"design": {
"version": 1,
"defaultVariant": "base",
"properties": [],
"slots": [],
"variants": [{
"key": "base",
"name": "Base",
"elements": [{"key": "component-root", "type": "section", "children": []}]
}]
}
}
Read Component Design with GET /api/v1/components/{componentId}/design.
Replace Component Design with POST /api/v1/components/{componentId}/replace-design, sending the revision from the preceding Design read.
Query Analytics and break down revenue.
Use GET /api/v1/dent/breakdown?dimension=source&period=last_month&includeAdmin=true&limit=5 for breakdowns.
Use GET /api/v1/orders/revenue-by-source?period=last_month&attribution=first_touch for source revenue.
breakdown accepts dimension. Available dimensions: source, referrer, campaign, country, region, city, device, browser, entry_pages.
In the CLI variant, pass catalog action parameters as query parameters:
dent api dent breakdown --param dimension=source --param period=last_month --param includeAdmin=true --param limit=5
POST /api/v1/courses with { "title", "slug", "description", "status": "published", "privacy": "secret" }.POST /api/v1/products with { "name", "value", "status": "publish", "courseIds": [courseId] }.spaceIds: [spaceId].POST /api/v1/offers with { "name", "price", "active": true, "products": [{"productId": productId}] }.POST /api/v1/courses/{courseId}/sections with { "title", "position", "status": "published" }.GET /api/v1/courses/{courseId}/sections.POST /api/v1/sections/{sectionId}/lessons with { "title", "body", "position", "status": "published", "contentType": "text" }.GET /api/v1/sections/{sectionId}/lessons.POST /api/v1/spaces with { "title", "slug", "privacy": "secret", "status": "published" }.POST /api/v1/spaces/{spaceId}/add-member with { "contact_id": contactId, "role": "member" }.GET /api/v1/spaces/{spaceId}/list-members./wp/wp-login.php, WordPress admin-ajax, Bricks save routes, or WordPress REST routes for these workflows. A need for those routes is a first-party API gap to report.