> ## Documentation Index
> Fetch the complete documentation index at: https://www.pickfu.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# PickFu CLI for surveys and automation

> Install the PickFu CLI on macOS, Linux, or Windows to create surveys, fetch results, and automate polls with JSON output for CI/CD workflows.

The PickFu CLI (`@pickfu/cli`) lets you create surveys, check results, and manage polls directly from your terminal. It supports structured JSON output for automation and CI/CD workflows.

## Installation

<CodeGroup>
  ```bash Homebrew theme={null}
  brew install pickfu/tap/pickfu
  ```

  ```bash macOS / Linux theme={null}
  curl -fsSL https://agents.pickfu.com/install.sh | bash
  ```

  ```powershell Windows theme={null}
  irm https://agents.pickfu.com/install.ps1 | iex
  ```

  ```bash npx (zero-install) theme={null}
  npx @pickfu/cli@latest survey list
  ```

  ```bash npm (global) theme={null}
  npm install -g @pickfu/cli
  ```
</CodeGroup>

### Supported platforms

| Platform | Architecture          | Install method           |
| -------- | --------------------- | ------------------------ |
| macOS    | Apple Silicon (arm64) | Homebrew, curl, npx, npm |
| macOS    | Intel (x64)           | Homebrew, curl, npx, npm |
| Linux    | x64                   | curl, npx, npm           |
| Linux    | arm64                 | curl, npx, npm           |
| Windows  | x64                   | PowerShell, npx, npm     |

The curl/PowerShell installers download a standalone binary — no Node.js required. The `npx` method requires Node.js 20+ but needs no installation.

## Authentication

### OAuth (recommended)

Log in through the browser to connect the CLI to your PickFu account:

```bash theme={null}
pickfu auth login
```

This opens a browser window for OAuth authorization. Once approved, your credentials are stored locally and refreshed automatically.

For headless environments (servers, CI), use the `--headless` flag to print the authorization URL instead of opening a browser:

```bash theme={null}
pickfu auth login --headless
```

### API key

For non-interactive environments like CI pipelines or automation scripts, use an API key instead of OAuth:

```bash theme={null}
# Interactive prompt (key never appears in shell history)
pickfu auth set-key

# Or pipe from clipboard (macOS)
pbpaste | pickfu auth set-key

# Or use an environment variable (for CI/automation)
export PICKFU_API_KEY=sk_...
pickfu survey list

# Or pass per-command via flag
pickfu survey list --token sk_...
```

<Note>
  Avoid `echo "sk_..." | pickfu auth set-key` — the key appears in shell history. Use the interactive prompt or pipe from clipboard instead.
</Note>

**Token precedence:** `--token` flag > `PICKFU_API_KEY` env var > stored OAuth token > stored API key.

### Managing credentials

```bash theme={null}
pickfu auth status       # Check authentication status
pickfu auth status --local  # Check without contacting the API
pickfu auth logout       # Clear stored credentials
```

## Commands

All commands support `--json` for machine-readable output.

### Surveys

#### Create a survey

```bash theme={null}
pickfu survey create
```

The CLI walks you through poll creation interactively. You can also provide options via flags:

```bash theme={null}
pickfu survey create \
  --name "Logo test" \
  --question "Which logo do you prefer?" \
  --type head_to_head \
  --option "Logo A" \
  --option "Logo B" \
  --sample-size 50 \
  --country US \
  --targeting amznpr \
  --reporting age \
  --tag "Q2 testing"
```

Image polls use `--option-image-url` instead of `--option`:

```bash theme={null}
pickfu survey create \
  --name "Packaging variants" \
  --question "Which design works best?" \
  --type ranked \
  --option-image-url https://cdn.example.com/v1.jpg \
  --option-image-url https://cdn.example.com/v2.jpg \
  --option-image-url https://cdn.example.com/v3.jpg \
  --sample-size 50 \
  --project proj_xyz
```

Or create from a JSON file:

```bash theme={null}
pickfu survey create --from-file survey.json
```

<Expandable title="JSON file format">
  ```json theme={null}
  {
    "name": "Logo test",
    "country": "US",
    "sampleSize": "50",
    "surveyIntent": "Determine which logo resonates better with our target audience",
    "questions": [
      {
        "type": "head_to_head",
        "prompt": "Which logo do you prefer for a children's educational app?",
        "context": {
          "text": "We're launching a new learning app for kids aged 5-10"
        },
        "options": [
          { "value": "Logo A — playful, colorful design" },
          { "value": "Logo B — clean, modern design" }
        ]
      }
    ],
    "targeting": ["amznpr"],
    "reporting": ["age", "gender"],
    "tags": [{ "name": "Q2 testing" }],
    "projectId": "proj_xyz"
  }
  ```

  Image options use `mediaUrl` (not `imageUrl`); product options use `asin`; image-set options use `imageSet`. Unknown fields on options are rejected with a 400 — see the [API reference](/api-reference/surveys/create-survey) for the full schema.
</Expandable>

| Flag                 | Description                                                       |
| -------------------- | ----------------------------------------------------------------- |
| `--from-file`        | Path to a JSON file with survey definition                        |
| `--name`             | Survey name                                                       |
| `--question`         | The question text                                                 |
| `--type`             | Question type (see [supported types](#supported-question-types))  |
| `--option`           | Text option (repeatable — use once per option)                    |
| `--option-image-url` | Image option URL (repeatable, mutually exclusive with `--option`) |
| `--sample-size`      | Number of respondents                                             |
| `--country`          | Two-letter country code. Omit to default to `US`.                 |
| `--targeting`        | Targeting trait code, e.g. `amznpr` (repeatable)                  |
| `--reporting`        | Reporting trait code, e.g. `age` (repeatable)                     |
| `--project`          | Project ID to assign the survey to                                |
| `--tag`              | Tag name to attach (repeatable)                                   |

#### Get survey details

```bash theme={null}
pickfu survey get <survey-id>
```

#### List surveys

```bash theme={null}
pickfu survey list
```

| Flag        | Description                                                              | Default     |
| ----------- | ------------------------------------------------------------------------ | ----------- |
| `--status`  | Filter by status (`completed`, `in-progress`, `unpublished`, `archived`) | All         |
| `--limit`   | Results per page                                                         | 20          |
| `--page`    | Page number                                                              | 1           |
| `--sort-by` | Sort field (`createdAt`, `name`, `creator`, `status`)                    | `createdAt` |
| `--dir`     | Sort direction (`asc`, `desc`)                                           | `desc`      |

#### Update a draft survey

```bash theme={null}
pickfu survey update <survey-id> --name "Updated name" --sample-size 100
```

Or update from a JSON file:

```bash theme={null}
pickfu survey update <survey-id> --from-file updated-survey.json
```

| Flag            | Description                    |
| --------------- | ------------------------------ |
| `--from-file`   | Path to JSON file with updates |
| `--name`        | Updated survey name            |
| `--sample-size` | Updated respondent count       |
| `--country`     | Updated country code           |

#### Publish a survey

Publish a draft survey to start collecting responses:

```bash theme={null}
pickfu survey publish <survey-id>
```

<Note>
  Calling `publish` on an already-published survey returns a `400 Already published` with a pointer to the [`/v1/surveys/{id}/respondents`](/api-reference/surveys/add-respondents) endpoint. Use `pickfu survey add-respondents` to extend the sample size of a running survey instead.
</Note>

#### Stop a survey

Stop a live survey from collecting responses before it reaches its target sample size:

```bash theme={null}
pickfu survey stop <survey-id>
pickfu survey stop <survey-id> --json
```

#### Clone a survey

Duplicate an existing survey as a new draft. Useful for re-running a poll with the same audience targeting and options, or for iterating on a previous test:

```bash theme={null}
pickfu survey clone <survey-id>
pickfu survey clone <survey-id> --name "Round 2" --sample-size 30
pickfu survey clone <survey-id> --project proj_xyz --json
```

| Flag            | Description                                                     |
| --------------- | --------------------------------------------------------------- |
| `--name`        | Override the cloned survey name (defaults to "Copy of \<name>") |
| `--sample-size` | Override sample size (defaults to source survey)                |
| `--project`     | Project ID to assign the clone to                               |

#### Extract image URLs

List the image URLs of every option in a survey — useful for downloading source images for further processing:

```bash theme={null}
pickfu survey extract-images <survey-id>
pickfu survey extract-images <survey-id> --json
```

#### View responses

Get individual responses with explanations and demographics:

```bash theme={null}
pickfu survey responses <survey-id>
```

| Flag            | Description                  | Default       |
| --------------- | ---------------------------- | ------------- |
| `--page`        | Page number                  | 1             |
| `--limit`       | Responses per page           | 20            |
| `--question-id` | Filter responses by question | All questions |

#### Watch a survey

Block until a survey completes — useful in scripts and CI:

```bash theme={null}
pickfu survey watch <survey-id>
```

| Flag            | Description                                                                    | Default |
| --------------- | ------------------------------------------------------------------------------ | ------- |
| `--interval`    | Polling interval in seconds                                                    | 30      |
| `--exit-status` | Exit with code 2 if cancelled or archived                                      | false   |
| `--json`        | Emit one NDJSON object per poll tick to stdout, plus a final completion object | false   |

#### Delete a survey

Delete a draft survey, or archive one that has already been published:

```bash theme={null}
pickfu survey delete <survey-id>
pickfu survey delete <survey-id> --json
```

<Note>
  For a draft survey this permanently deletes it. For a published survey it archives instead — the survey still appears in `pickfu survey list --status archived`.
</Note>

### Targeting and reporting

#### List available targeting traits

```bash theme={null}
pickfu targeting list --country US
```

Returns all demographic targeting traits available for the specified country. Pass each `permalink` value as a `--targeting` flag in `survey create` (e.g. `--targeting amznpr`).

Targeting a non-US country also localizes the poll: PickFu translates the question, context, and options into that market's language and returns results in both languages. See [International surveys and translation](/guides/international-surveys).

#### List available reporting demographics

```bash theme={null}
pickfu reporting list --country US
```

Returns all demographic breakdowns available for survey results.

### Tags

```bash theme={null}
pickfu tag list                    # List your tags
pickfu tag list --query "amazon"   # Search tags
pickfu tag create "Q2 testing"     # Create a new tag
```

### Media

#### Generate an image

Generate an image from a text prompt and get a CDN URL:

```bash theme={null}
pickfu media generate --prompt "A playful logo for a kids app"
pickfu media generate --prompt "Product banner" --aspect-ratio 16:9
```

Pass one or more reference images so the model can preserve product appearance across regenerated variants — useful for iterating on packaging, A+ content, or main-image variants:

```bash theme={null}
pickfu media generate \
  --prompt "Same product, holiday-themed packaging" \
  --reference-image-url https://cdn.example.com/source.jpg \
  --aspect-ratio 1:1
```

| Flag                    | Description                                                                | Default |
| ----------------------- | -------------------------------------------------------------------------- | ------- |
| `--prompt`              | Text prompt describing the image (required)                                |         |
| `--aspect-ratio`        | Aspect ratio (`1:1`, `16:9`, `9:16`, `3:2`, `2:3`, etc.)                   | `1:1`   |
| `--reference-image-url` | Reference image URL the model can see while generating (repeatable, max 3) |         |

#### Upload media

Upload an image or video to the PickFu CDN from a URL or local file:

```bash theme={null}
pickfu media upload --url https://example.com/image.png
pickfu media upload --file ./logo.png
pickfu media upload --file ./demo.mp4 --resource-type video
```

| Flag              | Description                                                      |
| ----------------- | ---------------------------------------------------------------- |
| `--url`           | URL of the media to upload (mutually exclusive with `--file`)    |
| `--file`          | Path to a local file to upload (mutually exclusive with `--url`) |
| `--filename`      | Display name hint for the uploaded media                         |
| `--resource-type` | `image` or `video` (auto-detected if omitted)                    |

YouTube, Vimeo, and Wistia URLs are returned as-is since PickFu embeds them natively.

#### Inspect media

Fetch metadata (content type, size, ETag) for an image or video URL without downloading the full payload:

```bash theme={null}
pickfu media show https://media-cdn.pickfu.com/.../v1.jpg
pickfu media show https://media-cdn.pickfu.com/.../v1.jpg --open
pickfu media show https://media-cdn.pickfu.com/.../v1.jpg --json
```

| Flag     | Description                                                        | Default |
| -------- | ------------------------------------------------------------------ | ------- |
| `--open` | Open the URL in the system default browser after fetching metadata | false   |

### Projects

```bash theme={null}
pickfu project list                          # List projects
pickfu project create --name "Q2 Research"   # Create a project
pickfu project get <project-id>              # Get project details
pickfu project update <project-id> --name "Updated name"
```

| Flag            | Description          |
| --------------- | -------------------- |
| `--name`        | Project name         |
| `--description` | Project description  |
| `--bookmark`    | Bookmark the project |
| `--archive`     | Archive the project  |

### Playbooks

Browse step-by-step research guides:

```bash theme={null}
pickfu playbook list                     # List available playbooks
pickfu playbook get <slug>               # Get full playbook with instructions
```

### Schema introspection

View the full input/output schemas for any command — useful for building integrations:

```bash theme={null}
pickfu schema             # List all commands
pickfu schema survey.create  # Detailed schema for a specific command
```

### Generic API access

Make authenticated API requests directly:

```bash theme={null}
pickfu api GET /v1/surveys
pickfu api POST /v1/surveys --body '{"name": "test"}'
pickfu api GET /v1/traits/targeting --query country=US
```

## OpenClaw

See the [OpenClaw page](/integrations/openclaw) to run the PickFu CLI inside an agentic skill, including the ready-made Claw Hub market research workflow.

## Supported question types

<Note>
  **Every response includes a written explanation by default.** When a respondent picks an
  option, ranks, rates, or clicks, they're also required to explain *why* in their own words
  — that's already part of every question type except `screen_recording` (which returns a
  transcription instead). **Do not create a multi-question survey (`--question` twice) just
  to add a separate "explain why" question — it wastes a question slot (priced per question)
  and produces redundant data.** Phrase your real question with `--question`, and PickFu
  collects the explanation automatically. The text comes back on each response as the
  `explanation` field. See [surveys overview](/guides/surveys-overview) for more.
</Note>

| Type               | Description                                                  |
| ------------------ | ------------------------------------------------------------ |
| `head_to_head`     | A/B comparison where respondents pick a favorite (2 options) |
| `ranked`           | Respondents rank options in preference order (3-8 options)   |
| `open_ended`       | Single-concept poll with written feedback                    |
| `click_test`       | Heatmap generation from image clicks                         |
| `emoji_rating`     | Emoji sentiment selection with explanation                   |
| `star_rating`      | 1-5 star rating with feedback                                |
| `five_second_test` | Brief timed exposure for first impressions                   |
| `screen_recording` | Record user interaction with content                         |
| `single_select`    | Choose one from multiple options (3-8 options)               |
| `multi_select`     | Select multiple answers from options (3-8 options)           |

## Sample sizes

Available respondent counts: **15**, **30**, **50**, **75**, **100**, **200**, **300**, **500**

## Need help?

```bash theme={null}
pickfu --help
pickfu survey --help
pickfu survey create --help
```

Or contact [support@pickfu.com](mailto:support@pickfu.com) for assistance.
