Creates a Pulumi event (workshop, webinar, or partner event) end to end: collects details from the prompt or an interactive wizard, scaffolds the content/events/<slug>/ page bundle, generates social cards via event-meta-image, files the tracking issue in pulumi/marketing from its issue template, and opens the docs PR. Use when the user types /create-event or asks to create, add, announce, or set up a workshop, webinar, livestream, or event page, event registration, or a workshop marketing issue — even if they only say 'new workshop' or 'schedule a webinar'. Accepts pasted details, a pulumi/marketing issue URL to prefill from, a brief file, --dry-run, and -y for no questions.
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
A direct command skips the review prompt. Inspect the source before running it.
Creates a Pulumi event (workshop, webinar, or partner event) end to end: collects details from the prompt or an interactive wizard, scaffolds the content/events/<slug>/ page bundle, generates social cards via event-meta-image, files the tracking issue in pulumi/marketing from its issue template, and opens the docs PR. Use when the user types /create-event or asks to create, add, announce, or set up a workshop, webinar, livestream, or event page, event registration, or a workshop marketing issue — even if they only say 'new workshop' or 'schedule a webinar'. Accepts pasted details, a pulumi/marketing issue URL to prefill from, a brief file, --dry-run, and -y for no questions.
You are the front half of a two-part flow. You run in the main conversation: gather and confirm the event details (Steps 1–3). The event-creator subagent (.claude/agents/event-creator.md, marked as companion-agent in the frontmatter above) is the back half: it executes the confirmed spec — bundle, social cards, marketing issue, PR (Step 4). It runs the mechanical work in its own context so this conversation stays focused; it cannot ask the user anything, which is why every decision is settled first.
here
Display progress as [Step X/5]. Minimize open-ended questions: batch AskUserQuestion calls, prepopulate every option you can infer, and never re-ask what $ARGUMENTS, a fetched issue, or an earlier answer already settled.
references/marketing-issue.md — issue template routing and snapshots, title/label/assignee conventions, form-ID sequencing and extraction.
[Step 1/5] Parse input and detect context
Parse $ARGUMENTS / the user's message for:
Flags: --dry-run (prepare everything, write issue/PR previews, zero GitHub writes — safe to run anytime); -y / --yes / --non-interactive / "no questions" (skip the wizard and the final confirmation, applying the defaults below — also assume this whenever running non-interactively, e.g. under claude -p or an eval, where questions can't be answered); --no-issue (marketing.issue: skip); --no-pr (run.pr: skip).
A pulumi/marketing issue URL or number → this is an existing tracking issue. gh issue view <n> --repo pulumi/marketing --json title,body,labels --comments and prefill: title, date/time, duration, presenters, theme, tags, abstract, learn bullets — and scan the comments for HubSpot form ID / Salesforce campaign ID (regexes in references/marketing-issue.md). Set marketing.issue: existing.
A file path (brief, Google-Doc export, notes) → read it and extract the same fields.
Free text → extract what's there.
Then check for prior art — this skill is idempotent:
Derive the slug (lowercase title, spaces → hyphens, alphanumerics and hyphens only; drop filler words only if the user's title is over 60 chars).
If content/events/<slug>/index.md exists → update mode: diff what the spec provides against the page, plan only the gap (most often: wiring in form IDs that landed on the issue). If page and issue exist and there is no gap, report that the event is fully set up and stop — never duplicate.
If no tracking issue was given, search for one: gh issue list --repo pulumi/marketing --search "<title words>" --state all --limit 5. A match → offer it as the existing issue instead of creating a duplicate.
[Step 2/5] Wizard — fill the gaps only
Ask only for fields still unknown after Step 1, in at most two AskUserQuestion batches (≤4 questions each), with smart defaults marked "(Recommended)". In -y mode skip entirely and take every default. Free-text answers (title, description) that can't be multiple-choice: prefill suggestions from context and let "Other" carry the custom value.
Field
Default / guidance
Event type
workshop | webinar | talk (page) — partner-hosted events route to the partner template, see references/marketing-issue.md
Title
≤ 60 chars (hard limit — trim with the user if over)
Meta description
50–160 chars, single sentence; suggest one from the abstract
Date + time + timezone
No default — this is the one field worth a blocking question outside -y; in -y with no date, use a weekday ~60 days out, 9:00 AM PT, and flag it loudly
Duration
60 minutes (90 when asked)
Location
virtual; otherwise City, ST
Gated
true for Pulumi-hosted workshops/webinars; false for external/on-demand
External?
Default false. true → url_slug = external URL + block_external_search_index: true, no form
Description (abstract)
1–2 paragraphs; draft from whatever the user gave and show it
Learn bullets
Exactly 3 outcome bullets (template convention); draft them
Presenters
Prefill from git config → data/team/team/<id>.toml (role = its title + ", Pulumi"). Externals: name, role, company, optional photo
Tags
level: Beginner/Intermediate/Advanced; topics/languages/clouds from the vocabulary in references/event-page.md — reuse, don't mint
Marketing theme
One of AI, IaC, Platform Engineering, Security, TF-Takeover (issue template's closed set)
HubSpot segmentation
Optional; derive from tags; "when in doubt, do not add"
Form IDs
Only if already known (issue comments / user). Never invented — pending IDs become frontmatter TODOs
needs-design
false; true adds the label for a designer-made card
Sessions
Only when the user mentions multiple dates (AMER + EMEA etc.) — rules in references/event-page.md
[Step 3/5] Compose the spec and confirm
Assemble the event spec — the single artifact handed to the agent:
Show the user the spec plus a short preview: the would-be issue title ([YYYY-MM-DD]: <Title> (<presenter first name>)), the files to be created, and whether issue/PR will really be created. Then gate:
Dry-run → proceed without asking (nothing outward happens).
-y → proceed (the flag is the user's standing go-ahead), but still show the preview.
Otherwise → one AskUserQuestion: "Create it now (issue + PR)" / "Dry run first (Recommended for a first pass)" / "Cancel". Creating a GitHub issue and PR is outward-facing — never do it silently.
[Step 4/5] Delegate to the event-creator agent
Spawn the event-creator subagent (Task/Agent tool, subagent_type: event-creator), passing the spec verbatim as its task plus one line: "Execute this event spec per your protocol." Wait for the result — the next step depends on it.
If that agent type isn't registered in this session, don't stall: read .claude/agents/event-creator.md and execute its protocol yourself, inline, honoring the same hard rules (dry-run = zero GitHub writes; never push master; never invent form IDs).
[Step 5/5] Relay the report and next steps
Relay the agent's structured report, then close the loop:
Preview before shipping: the rendered PNGs (or the build's auto-card), and make serve → http://localhost:1313/events/<slug>/.
Dry-run → the previews live in .context/create-event/<slug>/; rerun without --dry-run to create the issue and PR.
Pending form IDs → gated page ships with TODOs; watch the tracking issue for marketing's comment, then rerun /create-event <issue-url> to wire them in (update mode).
PR is a draft → mark ready after previewing; each ready-transition fires a full review, so do it once.
Suggest /docs-review for a content pass when the description was substantially drafted by the wizard.
Error handling
Slug collision with a different event (same slug, different topic) → suffix the slug (-2026, or the month) and tell the user.
gh unauthenticated / marketing repo unreachable → finish everything local, write the issue preview, and hand the user the exact gh issue create command to run.
Date in the past → confirm it's intentional (recordings/on-demand pages are legitimate).
User cancels at Step 3 → keep nothing outward; offer to save the spec to .context/create-event/<slug>/spec.yaml so a later run can resume from it.