---
name: feast
description: Operate a Feastalytics organization from the terminal — campaigns, automations, funnels, members-program rewards, the wallet pass, creator sourcing, Meta ads, onboarding, and read-only data queries — via the `feast` CLI. Use this skill whenever the user wants to inspect or change Feastalytics data outside the dashboard — "list my campaigns", "create an automation for org X", "approve this creator", "publish the recruitment ad", "query my guests", "update the members program", or any request to script/batch/automate Feastalytics operations. Reach for it even when the user doesn't say "CLI" — if the task is reading or changing Feastalytics data, this is the tool.
---

# Feast CLI

Drive the Feastalytics platform from the terminal. The `feast` CLI exposes the same tool surface the in-app AI agent uses (campaigns, automations, funnels, members program, creator sourcing, Meta ads, onboarding, data queries) as plain commands that hit the production API as the logged-in user.

The CLI is the source of truth for *which* tools exist and *what* they accept — always discover that at runtime rather than assuming, because the tool set grows as new endpoints are tagged. Your job is to pick the right tool, scope it to the right organization, and hand it valid input.

Some environments hand you the CLI already installed, already authenticated, and pinned to one organization. If `feast tools` runs, you're set — otherwise, installing, logging in, and staying current are in `references/setup.md`.

## The core loop: discover → describe → call

Don't guess tool names or input shapes. Introspect the live CLI:

```bash
feast tools                 # list every available tool, its domain, and whether it mutates
feast describe <tool>       # full description + input JSON schema for one tool
feast call <tool> --org <organizationId> --input '<json>'
```

Always `describe` an unfamiliar tool before calling it — the schema tells you the exact required fields, and the CLI validates your `--input` against it locally before sending anything, so a bad payload fails fast with a clear message instead of a confusing server error.

## Organizations: never let the API guess

Most tools act on one organization, and which one must be explicit: pass it with `--org <organizationId>`. Acting on the wrong restaurant is worse than stopping to ask, so the CLI refuses rather than guessing when the target is ambiguous.

If you weren't given an organization id, or a command reports you belong to several, `references/setup.md` has how to resolve one.

## Reads vs. writes

Query tools (listing, describing, reading) are safe and read-only. Mutation tools (create, update, clone, delete, apply) change production data.

- Mutations require `--org` explicitly.
- Before running one, the CLI resolves the organization server-side and prints its name, so a wrong `--org` shows up as the wrong restaurant rather than an opaque id. Read that line.
- **There is no confirmation prompt.** A mutation runs the moment you call it. Nothing asks twice, and nothing undoes it.

That last point matters most for the tools that reach the real world rather than just the database. Buying a phone number bills the account. Approving a creator visit or deciding a submission sends that person a text immediately and cannot be recalled. Paying a creator's bonus charges the organization's card. Publishing a campaign puts it live, and pricing a recurring promotion creates real Stripe products. Activating a Meta campaign spends real ad budget. Saving automation edits changes what guests receive. Treat those as irreversible, and get the user's intent straight *before* the call, because there is no gate after it. (The one schema-level exception: `publishAds` requires `confirm: true` in its input — but that's you confirming, not the CLI asking.)

Prefer reading before writing: e.g. `listCampaigns` to find the right `campaignId` before `updateCampaign`, or `describe`/`listAutomationFlows` before creating a flow.

## Building good input

`--input` takes a JSON string (or `--input-file <path>` for larger payloads). Construct it from the schema you got via `describe`. When a tool references another entity by id (a campaign id, location id, flow id), look that id up first with the relevant list/read tool rather than inventing it.

For the domain-specific meaning of fields — how automations chain, what a funnel screen contains, how offers are structured — consult the guidance in `references/domains.md` when the schema alone isn't enough.

## Workflows

Many tasks are multi-step and have a required ordering the app normally enforces. The most important rule: **automations live inside flows — always find a flow (`listAutomationFlows`) or create one (`createAutomationFlow`) before adding automations; never create an orphan automation.** The same "resolve the parent/ids first, then act" shape recurs across campaigns, funnels, and offers.

**Before acting on any multi-step task, read the workflow file for it.** Each one carries the required call ordering and the domain rules that make the result good rather than merely valid — neither of which is in the tool schemas. Read it first; don't reconstruct the sequence from tool descriptions.

| Doing this | Read |
|---|---|
| Creating, cloning or configuring a campaign; promotions | `references/workflows/campaigns.md` |
| Anything touching automations — creating, editing, simulating, promoting a draft | `references/workflows/automations.md` |
| Editing funnel screens, applying a funnel template, staging a new screen | `references/workflows/funnels.md` |
| Writing guest-facing Meta ad copy (`adCopy`) | `references/workflows/ad-copy-guest.md` |
| Writing creator-recruitment ad copy (`recruitmentAdCopy`) | `references/workflows/ad-copy-creator.md` |
| Publishing, pausing, budgeting or diagnosing Meta ads | `references/workflows/ads.md` |
| Creator sourcing — approving applicants, reviewing content, creatives, payouts | `references/workflows/creators.md` |
| Members-program rewards; reading or saving the wallet pass configuration | `references/workflows/members-program.md` |
| Working the onboarding taskboard; brand identity; phone, media, invites, billing | `references/workflows/onboarding.md` |
| Searching guests/members; querying anything via the data catalog | `references/workflows/guests.md` |

Every row names one file, and one file is the whole answer for that row — pick the row that matches what you're doing and read only it. The two ad-copy rows are mutually exclusive: you are writing to guests or to creators, never both in one piece of copy.

Read more than one file when a task genuinely spans steps — a new campaign usually means `campaigns.md` plus `automations.md` and `funnels.md`. Read each one as you reach that step rather than gathering them up front: a file stays in context for the rest of the session, so one you open speculatively is re-read on every later turn.

When the ask is a question rather than a change — where something lives, what a field means, which link to send — read the single file the table names and answer from it.

Some things are deliberately **not exposed**: replying to a guest or a creator by SMS, firing an automation at a live member, pass image generation, ad-copy generation (write it yourself), and publishing creator content as partnership ads. The workflow files say which. Don't fabricate a call for a workflow whose tools aren't listed by `feast tools` — tell the user that part isn't available yet.

## Link to what you touched

Work you do through the CLI lands somewhere in the product, and a link is a cheap thing to offer — so offer them freely. After a turn where you created, changed, or published something, close with a short markdown list: where to see it, where to edit it, where to preview it. Not because anyone has to go check your work, but because opening the thing is usually the next step anyway. When someone asks where a thing lives or how to set it up, lead with the link rather than click-by-click directions.

**You don't know these URLs — read `references/links.md` before you write one.** The dashboard's shape is not the one you'd extrapolate from the guest-facing links elsewhere in this skill, so a URL that looks obviously right is the exact case to check. A wrong link is worse than no link: it looks authoritative and 404s.

That file has the dashboard routes with their panel and tab names, the guest-facing pages on the organization's own subdomain, the preview route that completes the funnel draft loop, and which query params actually suppress analytics versus merely tagging a visit as a preview.

## Worked example

User: "add a Free Dessert reward members can redeem for 100 points in my Plum Vietnamese org."

```bash
feast whoami                                     # only if you weren't given the org id already
feast describe createMembersProgramReward        # learn the input shape (type: item vs name)
feast call listMembersProgramRewards --org <orgId>   # avoid duplicating an existing reward or catalog item
feast call createMembersProgramReward --org <orgId> --input '{"type":"name","name":"Free Dessert","pointsCost":100}'
```

The pattern generalizes: identify the org, learn the tool, resolve any referenced ids, then act.

## When something fails

- "Not logged in / session expired", or `feast` isn't on PATH → `references/setup.md`.
- "You belong to multiple organizations" → pick one with `--org`; `references/setup.md` has how to find the id.
- "Input does not match the tool schema" → re-read `feast describe <tool>` and fix the named fields.
- A tool you expected isn't listed by `feast tools` → it may not be exposed yet; don't fabricate a call, tell the user.
