# Gooseworks

> GooseWorks growth coworker and specialist-skill router. Research brands, customers, competitors, creators, markets, and prospects; analyze ads and performance; create ads, product photos, graphics, and video; search and scrape public web and social data; find and enrich leads. Use it as the single GooseWorks entry point for brand growth, B2B, sales, research, and GTM work.

- Skill: `gooseworks-ai/gooseworks` (Agent Skill)
- Install (CLI): `npx skillmds@latest add gooseworks-ai/gooseworks`
- Raw SKILL.md: https://api.skillmd.com/api/skills/gooseworks-ai/gooseworks/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Marketing & Growth
- Author: gooseworks-ai (https://skillmd.com/u/gooseworks-ai)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/gooseworks-ai/gooseworks

---


# GooseWorks

You have access to GooseWorks — an AI coworker with specialist skills for research, analysis, creative work, lead generation, enrichment, and public web/social data. Use the right specialist when the request needs brand context, a managed creative workflow, data at scale, a source behind authentication, or a specific provider.

This skill is also the **parent router** for the GooseWorks family. Data/GTM work you handle here (see "How to Use"); specialized work you hand off to a dedicated `goose-*` skill.

## Route to the right skill FIRST

First apply the **Common company onboarding** gate below. Preserve the user's original request while onboarding, then continue with it as soon as onboarding is complete. Then load the brand context (**"Load the brand context FIRST"**, immediately below). After that, check whether the request belongs to a specialized domain. If so, **switch to that skill** instead of the data flow below:

| If the user wants… | Route to | How |
| --- | --- | --- |
| Remix/make an ad, research a brand for ads, OR analyze ad performance — Meta/Google ad campaigns, creative fatigue, CAC/lead quality, competitor ad intel, ad angles & hooks | **`goose-ads`** | Installed locally as an entry skill. Just use it. If unavailable, run `gooseworks install --claude`. |
| Charts, infographics, slides, social graphics, branded visual designs from a style/format | **`goose-graphics`** | If installed locally, use it. Otherwise `gooseworks fetch goose-graphics` (or `gooseworks install --claude --with goose-graphics`). |
| Make a **video** ad — remix a video ad template (e.g. iMessage chat-reveal), or "make the video for project <id>" | **`goose-video`** | Installed locally as an entry skill. Just use it. If unavailable, run `gooseworks install --claude`. |
| Make **product photos** — studio, lifestyle, marketplace, social, or on-model product photography | **`goose-product-photos`** | Installed locally as an entry skill. Just use it. If unavailable, run `gooseworks install --claude`. |
| Animate an approved static ad or product image | **`animate-image`** | Fetch with `gooseworks fetch animate-image` and follow its GooseWorks MCP workflow. |
| Anything else — scraping, research, lead gen, enrichment, any data lookup | (stay here) | Follow "How to Use" below. |

Examples — all of these route to `goose-ads`, not the data flow: "remix this ad with project id 123", "make an ad for my product", "research my brand", "why is my Meta campaign underperforming", "which creatives should I cut".

## Load the brand context FIRST (mandatory — before you route, and before you ask anything)

**Call `brand_get_context` before the first substantive step of ANY task**, and before you route to a specialist skill. It is a cheap, read-only call that returns the brand's canonical facts:

| It returns | Use it for |
| --- | --- |
| **voice** — tone, style, banned phrasing | Any copy, script, caption, hook, or headline. Don't ask "what tone?" |
| **products** — names, descriptions, pricing, links, imagery | Picking the product to feature. Don't ask "which product?" — offer the list. |
| **audience** — segments, demographics, jobs-to-be-done | Targeting, angles, creator fit. Don't ask "who is this for?" |
| **positioning** — category, value props, proof points, tagline | Angles, offers, competitive framing. Don't ask "what makes you different?" |
| **research status** — whether the brand's research pass has completed | Whether the facts are trustworthy yet, or still being filled in. |

Then:

1. **Pass what it returned INTO the routed skill.** When you hand off to `goose-ads`, `goose-video`, `goose-product-photos`, `goose-graphics`, or a fetched Brand Growth recipe, carry the voice / products / audience / positioning with you. Do **not** make the routed skill re-derive them, and do **not** re-run brand research when the context is already there.
2. **Never re-ask the user for something the brand context already answers.** If a routed skill's own prose asks a question the context answers, the context wins — answer it yourself and move on. Ask only for what is genuinely missing or ambiguous.
3. **If research status is not complete**, say so in one line, use what you have, and continue. Only run brand research when the context comes back empty or the user asks for it.
4. **If `brand_get_context` is unavailable** (no MCP connection), fall back to `get_brand_kit` for the selected brand and treat its fields the same way. If neither is available, tell the user the GooseWorks MCP connection is needed rather than guessing brand facts.
5. **Treat it as read-only.** Writing brand facts back is the reconciliation flow in `goose-ads` (ask first, then `update_brand_kit`) — not something this router does.

Never invent a brand fact. If it isn't in the brand context and the user hasn't said it, ask.

## Setup

All commands below auto-load credentials from `~/.gooseworks/credentials.json`. If a command exits with "Not logged in", tell the user to run: `npx gooseworks login`. To log out: `npx gooseworks logout`.

### Choose the available runtime — MCP first, then CLI

Skills may describe a managed provider request as an environment-neutral operation with
`provider`, `method`, `path`, and optional `query` or `body`. Execute the operation through
the first available runtime:

1. If the matching GooseWorks MCP tool is registered, use it. For ScrapeCreators, pass the
   operation directly to `call_data_provider`. This is the preferred path in ChatGPT, Cowork,
   and other terminal-free clients. Do not shell out and do not ask for a separate provider key.
2. Otherwise, if a local terminal and the `gooseworks` CLI are available, translate the same
   operation into `gooseworks call <provider> <path>` with its method, query, and body options.
3. Otherwise, follow the provider dependency's direct-key path only when the user has supplied
   their own key. If no runtime is available, explain what connection is missing; never pretend
   the provider call ran.

The same selection applies to catalog and account operations. When the CLI is unavailable but the
`mcp__gooseworks__*` tools are connected, use these equivalents:
- `gooseworks search <q>` → the **`search_skills`** MCP tool.
- `gooseworks fetch <slug>` → the **`fetch_skill`** MCP tool (same content/scripts/files/deps).
- `gooseworks credits` → the **`get_ad_credits`** MCP tool.

Discovery, skill fetching, and ScrapeCreators-backed Brand Growth workflows work fully CLI-free
this way. Task skills own the endpoint and analysis workflow; this runtime rule owns how the same
provider operation is executed.

To check credit balance:
```bash
gooseworks credits
```

## Common company onboarding

Onboarding happens inside the current agent and is the first-run gate for every GooseWorks task. It uses the exact same saved state and step order as the web onboarding. The user does not need to type **`/gooseworks onboard me`**; that explicit command only starts or resumes the same flow.

Keep the user's original task pending. Call **`brand_onboarding { action: "status" }`** before routing or executing it, then:

- follow only the returned `next_step`;
- save each answer immediately with `brand_onboarding` so web, Claude, Codex, ChatGPT, and Cowork can resume one another;
- continue the original request immediately when `onboarding_completed` is true.

If `brand_onboarding` is unavailable, explain that the GooseWorks MCP connection must be enabled. Do not write a parallel local profile and do not run the retired role / discovery-source / ad-owner questionnaire.

### Shared flow

Use the host's native question controls. Ask one short group at a time and rely on the live tool schema for accepted values.

1. **Start** — If status returns `start`, ask for the company website or Apple App Store URL. Also offer the optional hero product URL and “Where do you do your work?” choices: Slack, WhatsApp, iMessage, Claude Code, Claude, Codex, and ChatGPT. Call `action: "start"`; server-side research begins immediately. If status returns `select_brand`, ask which company/client to use. Otherwise reuse the only brand automatically.
2. **Your coworker** — Ask what they want to name their Growth Coworker. A text-only client may keep the default avatar; do not block on an image. Save with `action: "save_coworker"`.
3. **Your company** — Use the returned `company_draft` as the starting point and ask the user to verify or edit: what they sell (`marketCategory`), where people buy (`appPlatforms`), primary customer, customer problem, promised outcome, and optional differentiator. Save with `action: "save_company"`.
4. **Your taste** — If the host can show the returned `taste_deck` images, let the user heart or skip cards until they have three hearts. They may explicitly skip the whole step. Save decisions with `action: "save_taste"`; send `complete: true` after three hearts or an explicit skip.
5. **First campaign** — Ask **“What’s happening right now?”**: launch `launch`, promotion `promo`, seasonal moment `seasonal`, or nothing special `nothing`, plus an optional note. Call `action: "propose_campaign"`, show the returned editable card (name, objective, offer, audience, 2–3 angles, CTA, and product URL), and save edits with `action: "save_campaign"`. Send `accept: true` only after approval; acceptance can start the complimentary first creatives.
6. **Where you are** — Ask monthly ad spend (`none`, `under_1k`, `1k_5k`, `5k_25k`, `25k_plus`), annual revenue (`under_1m`, `1m_10m`, `10m_100m`, `100m_plus`), the 90-day goal, current channels (an empty list is a valid “nothing yet”), and at least one channel they are willing to use. Channel values: `paid_social`, `search_ads`, `content`, `creators`, `seo`, `communities`, `referrals`, `partnerships`, `outbound`, `app_stores`, `other`. Save with `action: "save_progress"`.
7. **Review** — Show the returned founder, researched, and inferred facts with their provenance. The user may correct positioning, audience, voice, value propositions, proof points, or competitors through `action: "review_research"`. Complete the review even when research is still running, failed, or sparse; never trap the user waiting for it.
8. **Channels** — If `channel_connected` is already true, this is complete automatically. Otherwise ask whether they want to connect Slack, WhatsApp, or iMessage later, or skip for now. An explicit skip is valid; call `action: "complete_channels"`.

Do not ask for role, discovery source, who makes creatives, who manages ads, or a separate “what do you want to do first?” menu. Those belonged to the retired CLI questionnaire. The task the user already asked for is their first task.

## Brand Growth discovery

Brand Growth is a collection inside the normal skill catalog, not a command or installable pack. Use these known routes when relevant, while preserving all existing B2B, sales, research, lead-generation, and data behavior:

| Job | Skill |
| --- | --- |
| Brand foundation | `brand-research` |
| Competitor ads | `competitor-ad-intelligence` |
| Customer language and angles | `comment-mining`, `ad-angle-miner` |
| Competitor social content | `competitor-social-research` |
| Audience definition | `audience-research` |
| Creator discovery and evaluation | `influencer-prospecting`, `creator-profile-teardown` |
| Trends and outlier posts | `trend-discovery`, `outlier-post-finder` |
| Social listening and product demand | `social-listening-brief`, `product-demand-research` |
| Long-form source material (calls, podcasts, videos) | `transcript-intelligence` |
| Meta performance, policy, and landing-page match | `meta-ads-analyzer`, `meta-ad-policy-checker`, `ad-to-landing-page-auditor` |
| Static ads | `goose-ads`, `remix-graphic-ad-from-reference` |
| Product photos | `goose-product-photos`, `product-photoshoot` |
| Written content and repurposing | `content-repurposing` |
| Graphics and animation | `goose-graphics`, `animate-image` |

Fetch the named public skill before following it. You already called `brand_get_context` — hand the brand's voice, products, audience, and positioning to the fetched skill instead of letting it re-derive or re-ask them. Provider helpers such as `scrapecreators-api` and `transcript-intelligence` are dependencies, not user-facing results.

For a multi-part request, repeat this routing check before each new job. Fetch and follow the
closest outcome skill first (for example, `comment-mining`, `creator-profile-teardown`, or
`content-repurposing`) before calling provider APIs or improvising a workflow. Provider calls
collect inputs for the outcome skill; they do not replace it.

## How to Use

### If a specific skill is requested (e.g. --skill <slug> or "use the <name> skill")
Skip search and go directly to **Step 2** with the given slug.

### Step 1: Search for a skill
When the user asks you to do ANY data task (scrape reddit, find emails, research competitors, etc.) **without specifying a skill name**, search the skill catalog first:
```bash
gooseworks search "reddit scraping"
```

### Step 2: Fetch the skill
Once you have a skill slug, fetch its full content and scripts:
```bash
gooseworks fetch <slug>
```

This prints a JSON object with:
- **content**: The skill's instructions (SKILL.md) — follow these step by step
- **scripts**: Python scripts the skill uses — save them locally and run them
- **files**: Extra files the skill needs (configs, shared tools like `tools/apify_guard.py`) — save them relative to `/tmp/gooseworks-scripts/`
- **requiresSkills**: Array of dependency skill slugs (for composite skills)
- **dependencySkills**: Full content and scripts for each dependency

### Step 3: Set up dependency skills (if any)
If the response includes `dependencySkills` (non-empty array), set up each dependency BEFORE running the main skill:
1. For each dependency in `dependencySkills`:
   - Save its scripts to `/tmp/gooseworks-scripts/<dep-slug>/`
   - Install any pip dependencies it needs
2. When the main skill's instructions reference a dependency script (e.g. `python3 skills/reddit-scraper/scripts/scrape_reddit.py`), run it from `/tmp/gooseworks-scripts/<dep-slug>/` instead

### Step 4: Set up and run the skill
Follow the instructions in the skill's `content` field. **Save ALL files from both `scripts` AND `files` before running anything:**

> **Credential translation rule:** Individual skill instructions may contain a legacy `## Setup` block with `export GOOSEWORKS_API_KEY=$(python3 ...)` and raw `curl` commands. **Replace those with the clean equivalents below.**
> - **Credentials (only needed before running Python scripts, NOT before gooseworks commands):** replace the python one-liner exports with `eval $(gooseworks env)`. Skip entirely if you are only using `gooseworks call` — it loads credentials automatically.
> - **Orthogonal run:** replace `curl ... /v1/proxy/orthogonal/run ... -d '{"api":"X","path":"/Y","body":{...}}'` with `gooseworks call X /Y --body='{...}'`
> - **Direct proxy:** replace `curl ... /v1/proxy/<provider>/<path> ... -d '{...}'` with `gooseworks call <provider> <path> --body='{...}'`
> - **ScrapeCreators:** call its first-party GooseWorks proxy directly with `gooseworks call scrapecreators <path> --query='{...}'`. Use ScrapeCreators' official OpenAPI for endpoint parameters; do not use Orthogonal as its endpoint catalog. GET is the default; add `--method POST --body='{...}'` only for an official POST operation.
> - **Orthogonal search:** replace `curl ... /v1/proxy/orthogonal/search ... -d '{"prompt":"..."}'` with `gooseworks orthogonal find "..."`

1. Save each script from `scripts` to `/tmp/gooseworks-scripts/<slug>/scripts/` — **NEVER save scripts into the user's project directory**
2. **IMPORTANT: Also save everything from `files`** — these contain required modules (like `tools/apify_guard.py`) that scripts import at runtime:
   - Files starting with `tools/` → save to `/tmp/gooseworks-scripts/tools/` (shared path, NOT inside the skill dir)
   - All other files → save to `/tmp/gooseworks-scripts/<slug>/<path>`
   - **If you skip this step, scripts will crash with ImportError**
3. Install any required pip dependencies mentioned in the instructions
4. Run the script with the parameters described in the instructions
5. When instructions reference dependency scripts, use paths from Step 3: `/tmp/gooseworks-scripts/<dep-slug>/<script>`

## Raw API Discovery (fallback)

If no GooseWorks skill matches the user's request, you can discover and call **any API** through the Orthogonal gateway. This gives you access to 300+ APIs (Hunter, Clearbit, PDL, ZoomInfo, etc.) without needing separate API keys.

### Search for an API
Find APIs that can handle the task:
```bash
gooseworks orthogonal find "find email by name and company"
```
Returns matching APIs with endpoint descriptions and per-call pricing.

### Get endpoint details
Before calling an API, check its parameters:
```bash
gooseworks orthogonal describe hunter /v2/email-finder
```

### Call the API
Execute the API call (billed per call based on provider cost):
```bash
gooseworks call hunter /v2/email-finder --query='{"domain":"stripe.com","first_name":"John"}'
```
- Use `--body='{...}'` for POST body parameters
- Use `--query='{...}'` for query string parameters
- Output: JSON response data, followed by a `Cost: <N> credits` line when applicable
- **Always tell the user the cost** after each call

The same `gooseworks call` command also handles direct-proxy providers (apify, apollo, crustdata, scrapecreators):
```bash
gooseworks call apify acts/parseforge~reddit-posts-scraper/runs --body='{"subreddit":"ClaudeAI"}'
gooseworks call scrapecreators /v2/instagram/post/comments --query='{"url":"https://www.instagram.com/p/POST_ID/"}'
```

### Workflow
1. Search first (`gooseworks orthogonal find`) — pick the best API + endpoint
2. Get details (`gooseworks orthogonal describe`) — understand required parameters
3. Call (`gooseworks call`) — invoke with the right parameters
4. Parse the JSON output for the actual API result

## Working Directory & Output Files

- **Scripts** always go to `/tmp/gooseworks-scripts/<slug>/` — NEVER the user's project directory
- **Output files** (CSVs, reports, data exports) go to a **GooseWorks working directory**:
  1. If the user specifies where to save results, use that location
  2. Otherwise, default to `~/Gooseworks/` — create it if it doesn't exist
  3. **Before saving output**, confirm with the user: *"I'll save the results to ~/Gooseworks/<filename>. Would you like a different location?"*
  4. Organize outputs in subfolders by task type when it makes sense (e.g. `~/Gooseworks/reddit-scrapes/`, `~/Gooseworks/research/`)
- **Never overwrite existing files** without asking. If a file already exists, append a timestamp or ask the user

## External Endpoints

The `gooseworks` CLI sends authenticated requests (Bearer `GOOSEWORKS_API_KEY`) to:

| Endpoint | Method | Wrapped by |
|----------|--------|------------|
| `$GOOSEWORKS_API_BASE/api/skills/search` | POST | `gooseworks search` |
| `$GOOSEWORKS_API_BASE/api/skills/catalog/:slug` | GET | `gooseworks fetch` |
| `$GOOSEWORKS_API_BASE/v1/credits` | GET | `gooseworks credits` |
| `$GOOSEWORKS_API_BASE/v1/proxy/orthogonal/search` | POST | `gooseworks orthogonal find` |
| `$GOOSEWORKS_API_BASE/v1/proxy/orthogonal/details` | POST | `gooseworks orthogonal describe` |
| `$GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run` | POST | `gooseworks call` (orthogonal-routed providers) |
| `$GOOSEWORKS_API_BASE/v1/proxy/{apify,apollo,crustdata,scrapecreators}/*` | Various | `gooseworks call` (direct-proxy providers; ScrapeCreators uses its managed first-party key) |

## Security & Privacy

- All API calls are authenticated via Bearer token stored locally in `~/.gooseworks/credentials.json` (file mode 0600)
- No credentials are hardcoded or sent to third parties
- API keys for external services (Apify, Apollo, etc.) are managed server-side — your token never touches them
- Scripts run locally on your machine; only API requests go through GooseWorks servers. Skill scripts are open source (github.com/gooseworks-ai/goose-skills) — read or pin them before running
- Credit usage is tracked per-call and visible via `gooseworks credits`

## Rules

0. **Call `brand_get_context` before anything else**, pass what it returns into whatever skill you route to, and never re-ask the user for a fact it already answers (see "Load the brand context FIRST").
1. **Consider a GooseWorks skill when it fits the task** — scraping, research, lead gen, enrichment, especially at scale, behind auth, or from a specific source. For a quick lookup your built-in tools are fine; use your judgement and pick the best tool for the user.
2. **Before paid operations**, tell the user the estimated credit cost
3. **If a `gooseworks` command exits with "Not logged in"**: tell the user to run `npx gooseworks login`
4. **Parse JSON responses** and present data in a readable format to the user
5. **When running scripts**: save to `/tmp/gooseworks-scripts/`, install pip deps, then execute. NEVER pollute the user's project directory
6. **Output files default to `~/Gooseworks/`** — always confirm with the user before saving
7. **Prefer `gooseworks call` over raw curl** — if it returns an error, first fix the parameters (check types, required fields, format) and retry. Only fall back to raw curl if you have strong reason to believe it is a CLI bug, not a parameter issue.

