skills/in-app-ui/SKILL.md
Guidance for implementing Knock in-app UI in a web app, with a focus on setting up, rendering, and debugging Knock guides in React.
npx skillsauth add knocklabs/skills in-app-uiInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
This skill helps you build in-app UI with Knock. It covers the two in-app products — feeds and guides — at a high level, then goes deep on guides: provider setup, rendering with hooks, and debugging.
Reference: https://docs.knock.app/in-app-ui/overview
The skill is organized into four focused rule files. Client-framework guidance is scoped per framework via a -<framework> suffix (currently only React). Cross-framework concepts live in unsuffixed files.
KnockProvider and KnockGuideProvider props, where each value comes from, and how to sequence themuseGuide / useGuides, typed content, and engagement trackingFramework scope: right now this skill only covers React (
@knocklabs/react). If the user is building with Vue, Svelte, plain JS, React Native, iOS, or Android, stop and ask how they'd like to proceed — do not adapt the React rules to another client SDK on your own.
Start with rules/feeds-vs-guides.md:
KnockProvider once and render each product's provider where it's neededrules/setup-guide-providers-react.mdknock whoami — if it errors with something like "not authenticated" or "no user session," run knock login and ask the user to complete the browser flow before continuing (the CLI persists the session so this is a one-time step per machine). Only after knock whoami succeeds, run knock environment list and ask the user to pick (the CLI defaults to development, but most real integrations target production). Remember that slug as <env-slug> and pass --environment <env-slug> on every subsequent environment-scoped knock command.channelId via the Knock CLI: run knock channel list --json | jq -r '.[] | select(.key == "knock-guide") | .id'. Channels are account-scoped, so this command does not take --environment. If it prints a UUID, use it — do not ask the user to confirm or re-paste. Only ask the user if the CLI returns nothing or errors. See the rule file's "Where to get channelId" procedure for the full fallback order.apiKey for the chosen environment (and confirm user.id is coming from the app's auth context). Do not bundle the apiKey ask with channelId.KnockProvider + KnockGuideProvider at the top of the tree.readyToTarget on any async data your targeting depends on.knock guide list --environment <env-slug> --json, show the user the options (key, name, each step's schema_key), and build the first component against a real guide's actual values. Do not scaffold with placeholder strings like "changelog-card". Fetch the message type schema with knock message-type get <schema_key> --environment <env-slug> --json so the content is typed. If the environment has no guides, offer to scaffold a test one via the Knock CLI (knock guide new → edit the JSON → knock guide push --environment <env-slug>) using a built-in message type (card, banner, or modal) with obvious-placeholder content — don't stall waiting for manual dashboard setup. See rules/rendering-guides-react.md → "First guide: discover real guides via CLI before writing code" for the full procedure including the empty-environment branch.pk_ key, flip the guide to active in the dashboard, restart dev server) explicitly — don't leave them to discover it by absence.rules/rendering-guides-react.mdknock guide list --environment <env-slug> --json for the guide's key / step schema_key; knock message-type get <schema_key> --environment <env-slug> --json for the content schema. Avoid placeholder strings.useGuide for single-guide surfaces, useGuides for listsmarkAsSeen, markAsInteracted, and markAsArchived — custom components must do this themselvesrules/debugging-guides.md and work the triage checklist top to bottom?knock_guide_toolbar=true) first — it answers most questions in secondsrules/feeds-vs-guides.md — product selection between feeds and guides (framework-agnostic)rules/setup-guide-providers-react.md — configuring KnockProvider and KnockGuideProvider for guides (React)rules/rendering-guides-react.md — useGuide, useGuides, typed content, engagement tracking (React)rules/debugging-guides.md — toolbar, triage checklist, testing workflow (framework-agnostic)The examples below are React. For any other client SDK, see the note at the top of Overview before proceeding.
<KnockProvider
apiKey={process.env.NEXT_PUBLIC_KNOCK_API_KEY}
user={{ id: currentUser.id }}
>
<KnockGuideProvider
channelId={process.env.NEXT_PUBLIC_KNOCK_GUIDE_CHANNEL_ID}
readyToTarget
listenForUpdates
>
{children}
</KnockGuideProvider>
</KnockProvider>
Auth first, then environment — Knock is environment-scoped. Before any CLI command, verify the CLI is authenticated with knock whoami; if it errors, run knock login and wait for the user to complete the browser flow. Then run knock environment list and confirm the target slug (production, development, …) with the user. Pass --environment <env-slug> on every subsequent environment-scoped knock command. Don't rely on the CLI's development default.
apiKey — Knock dashboard → Platform → API keys → public pk_... key from the tab for the chosen environment (switch envs via the dashboard's environment selector first; remind the user to copy the key for the right env)
user.id — your auth context; must match the id used when identifying the user from your backend
channelId — the UUID of the guide channel, not its key. Channels are account-scoped, so knock channel list does not take --environment. Always attempt CLI discovery before asking the user:
knock channel list --json | jq -r '.[] | select(.key == "knock-guide") | .id'
If this prints a UUID, use it directly — don't prompt for confirmation. The default guide channel key is knock-guide (type in_app_guide). Fall back to the dashboard (Settings → Integrations → Channels) only if the CLI returns nothing or errors. See rules/setup-guide-providers-react.md for the full procedure.
useGuide({ type }) — one guide by message typeuseGuide({ key }) — one specific guide by keyuseGuides({ type }) — array of guides by message typeuseGuideContext() — low-level client accessstep.markAsSeen() — impression (call from useEffect keyed on step)step.markAsInteracted() — primary actionstep.markAsArchived() — dismissal; removes the guide for this user going forwardAppend ?knock_guide_toolbar=true to any URL. The toolbar shows all guides, which are active, which this user is eligible for, and why the rest were filtered out.
KnockProvider.readyToTarget on async data your targeting rules depend on.useGuide<T> should mirror the Knock message type schema.markAsSeen, markAsInteracted, and markAsArchived themselves.documentation
Comprehensive guidelines for designing, writing, and implementing effective notification systems across email, push, SMS, in-app, and chat channels.
tools
Guidelines for working with the Knock CLI to manage workflows, templates, and other notification resources in a Knock project.
development
Maintainer-only workflow for handling GitHub Secret Scanning alerts on OpenClaw. Use when Codex needs to triage, redact, clean up, and resolve secret leakage found in issue comments, issue bodies, PR comments, or other GitHub content.
development
Maintainer workflow for OpenClaw releases, prereleases, changelog release notes, and publish validation. Use when Codex needs to prepare or verify stable or beta release steps, align version naming, assemble release notes, check release auth requirements, or validate publish-time commands and artifacts.