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

# NeetoForm CLI

> Work with forms, submissions and team members from the terminal.

The NeetoForm CLI is a single binary, `neetoform`, that talks to the same
[external API](/getting-started/introduction) the REST endpoints expose. It
signs you in through the browser, stores the credential per workspace, and
prints results as tables, JSON or TOON.

<CardGroup cols={2}>
  <Card title="No API key to manage" icon="key">
    `neetoform login` opens a browser and stores a session per workspace. There
    is no key to generate, paste or rotate.
  </Card>

  <Card title="Scoped to you" icon="user-shield">
    Requests run with your own permissions, so the CLI can only reach what your
    account can reach.
  </Card>

  <Card title="Built for scripting" icon="terminal">
    `--json`, `--quiet` and `--toon` give machine-readable output, and every
    command exits non-zero on failure.
  </Card>

  <Card title="Ready for AI assistants" icon="robot">
    `neetoform setup` installs a NeetoForm skill into Claude Code, Cursor,
    Windsurf, Copilot, Gemini CLI and Codex.
  </Card>
</CardGroup>

## CLI vs MCP: which should I use?

NeetoForm's [MCP server](/mcp/introduction) reaches the same resources the CLI
does - forms, their submissions and team members. It is ahead in one place only:
it can find a form by title and read that form's questions back, which no
`neetoform` command does. Past that neither can do more than the other, so
choose on how the work reaches NeetoForm.

### Reach for the CLI when

* **No AI assistant should be in the loop.** A nightly job that pulls yesterday's
  submissions into your own store runs `neetoform` with nothing but the binary
  and a workspace it is already signed in to - no assistant open, no model
  account, no tokens spent per run. Over MCP, something with model access has to
  be running before any call happens at all.
* **The output feeds another program.** `neetoform forms list --quiet | jq -r '.[].id'`
  hands the ids straight to the next command, and a create prints only the new
  id, so `id=$(neetoform team-members create --emails oliver@example.com --role Standard --quiet)`
  captures it. `--json` keeps the envelope, which is what you want when the
  records are headed for `jq`, a spreadsheet or your own script. An assistant
  answers in prose you would have to copy out by hand.
* **You are exporting thousands of submissions.** A form with 5,000 of them is 50
  pages at the maximum `--page-size 100`, and every answer to every question
  comes back with each one. `neetoform forms submissions list <form-id> --json --page-size 100`
  returns `total_pages` and `total_records` next to the records, so a loop knows
  how many pages are left and walks all 50 unattended, writing each page to a
  file or into `jq` on the way to a spreadsheet. Over MCP every one of those
  pages is a separate tool call whose whole payload lands in the assistant's
  context, and a list that long crowds out everything else.
* **The run has to be repeatable and reviewable.** The command is the artifact:
  put it in a runbook or a pull request and it makes the identical call next
  time, against the same form id with the same page size. Ask twice over MCP and
  the assistant may take a different route.

### Reach for MCP instead when

* **The details live in your chat, not in your head.** Paste the thread where
  three people asked for access and they are invited with the role you name,
  with no address retyped. The CLI cannot see any of it.
* **The answers need reading, not matching.** Submissions carry free text - "what
  would you change?", "why did you cancel?" - and an assistant can go through two
  hundred of them and tell you which complaints keep repeating. `jq` only matches
  wording you already knew to look for.
* **One request should cover several steps.** "Find the onboarding feedback form,
  read last week's submissions and tell me who scored us below 5" is one
  sentence: search by title, pull the submissions, then judge - with no id copied
  between commands.
* **The person doing it does not use a terminal.** NeetoForm hosts the server, so
  there is nothing to install on the machine and nothing to keep updated.

<Tip>
  You can have both. Run [`neetoform setup claude`](/cli/ai-assistants) and your
  AI assistant drives the CLI itself, so a plain-language request still ends in
  an exact command you can read, repeat and paste into a script.
</Tip>

## Prerequisites

* A NeetoForm workspace and your [workspace subdomain](/getting-started/workspace-subdomain).
* An account in that workspace. The CLI acts as you, so a command fails if your
  organization role does not allow the operation.
* macOS, Linux or Windows. See [Installation](/cli/installation).

## Where to go next

<CardGroup cols={2}>
  <Card title="Installation" icon="download" href="/cli/installation">
    Install the binary with Homebrew or an install script.
  </Card>

  <Card title="Authentication" icon="right-to-bracket" href="/cli/authentication">
    Sign in, work with several workspaces, and see where credentials are stored.
  </Card>

  <Card title="Commands overview" icon="list" href="/cli-reference/overview">
    Every command grouped by resource, with global flags.
  </Card>

  <Card title="Output formats" icon="code" href="/cli/output-formats">
    Pretty tables, the JSON envelope, quiet mode and TOON.
  </Card>
</CardGroup>
