# FakeParrot CLI

---

**Last updated:** October 10, 2026

---

The `fakeparrot` command lets an AI app with a terminal on your Mac or in a Linux
container work with your company in FakeParrot. It can
search and read the wiki, run workflows and read their reports, and check your
connected sources. It calls the same API as the web app and prints the answer
as JSON.

Every command acts as you. It can see and change only what you can in
FakeParrot.

## Choose your connection

Use the [shared routing and recovery contract](/developers/mcp#choose-your-connection):
folder for known pages and supported edits, CLI for search and live work, then MCP.
Check the actual execution host and company. Do not switch connections to bypass
an access denial or replay a write whose result is uncertain.

## Before you start

- On Mac, you need macOS 13 or later. The command runs on Apple silicon and
  Intel Macs.
- Linux x86-64 and ARM64 use the static downloads and secret setup below.
  They need an existing employee API key or OAuth grant.
- Windows and clients without a terminal use the [MCP server](/developers/mcp).
- A cloud terminal can use the Linux CLI when it supports installation and
  credential injection. Access to your Mac folder and Keychain is separate.

## Install

### With the Mac app (recommended)

1. [Download FakeParrot for Mac](/download) and open the installer.
2. Sign in to the app with your work email.

That is the whole setup. The installer puts the command at
`/usr/local/bin/fakeparrot` and runs `fakeparrot integrate` for you, which adds
a FakeParrot skill to Claude Code, Codex and Cursor. It does this again on
every update, so the skill stays current.

### On its own

A Mac without the app can install just the command:

1. [Download the CLI installer](/downloads/fakeparrot-cli.pkg) and open it.
2. Sign in with `fakeparrot auth login`, below.
3. Run `fakeparrot integrate` to add the skill to your AI apps. This installer
   does not run it for you.

Check the installed version with:

```sh
fakeparrot version
```

## Linux and containers

Linux x86-64 and ARM64 use the same Swift parser, transport and JSON contracts as
Mac. Release `1.0.1` is fully static: no Swift runtime, libc or package manager is
needed to run the executable. HTTPS needs the container's CA certificates.
`version`, `describe QUERY` and `call METHOD PATH` are supported. Existing REST
convenience commands share that transport. `integrate`, interactive login,
`compute connect mac` and `sync resolve/status/wait` use Mac capabilities.

Linux does not run `fakeparrot integrate`. Load the
[shared instructions](/developers/mcp#choose-your-connection) through your host's
supported persistent instruction path, such as a trusted workspace `AGENTS.md`
for Codex or `CLAUDE.md` for Claude Code. Preserve existing rules and start a new
session to check what loaded. Never export a Mac credential to make Linux work.

### Install a pinned release

Downloads are public and immutable:

- [x86-64 archive](https://storage.googleapis.com/valiant-cycle-476400-i8-cli-releases/linux/1.0.1/fakeparrot-1.0.1-linux-x86_64.tar.gz)
- [ARM64 archive](https://storage.googleapis.com/valiant-cycle-476400-i8-cli-releases/linux/1.0.1/fakeparrot-1.0.1-linux-aarch64.tar.gz)
- [SHA-256 checksums](https://storage.googleapis.com/valiant-cycle-476400-i8-cli-releases/linux/1.0.1/SHA256SUMS)
- [Build provenance](https://storage.googleapis.com/valiant-cycle-476400-i8-cli-releases/linux/1.0.1/release.json)

On Linux, with `curl`, `tar` and `sha256sum` installed:

```sh
set -eu
case "$(uname -m)" in
  x86_64) arch=x86_64 ;;
  aarch64|arm64) arch=aarch64 ;;
  *) echo 'Supported architectures: x86-64 and ARM64' >&2; exit 2 ;;
esac
base=https://storage.googleapis.com/valiant-cycle-476400-i8-cli-releases/linux/1.0.1
curl -fsSLO "$base/fakeparrot-1.0.1-linux-$arch.tar.gz"
curl -fsSLO "$base/SHA256SUMS"
sha256sum --check --ignore-missing SHA256SUMS
tar -xzf "fakeparrot-1.0.1-linux-$arch.tar.gz"
mkdir -p "$HOME/.local/bin"
install -m 755 fakeparrot "$HOME/.local/bin/fakeparrot"
export PATH="$HOME/.local/bin:$PATH"
fakeparrot version </dev/null
```

Keep `licenses/` and `version.json` with the release when redistributing it. The
binary embeds its version and source revision and works from any installation
prefix. On a minimal image, install `ca-certificates` before making HTTPS calls.

### Supply an existing employee credential

Provision an existing employee API key through the cloud agent's secret manager,
or mount a file containing just the UTF-8 token. It may end with a newline.
Protect the host file (normally mode `0600`) and mount it read-only; do not commit
it or include it in an image. The application owning the secret supplies its
contents; a person must never put a token in a prompt or shell argument.

```sh
# The host's secret mechanism has already provisioned this file.
export FAKEPARROT_TOKEN_FILE=/run/secrets/fakeparrot
export FAKEPARROT_CREDENTIAL_TYPE=api-key
fakeparrot auth status </dev/null
fakeparrot describe /api/workflows </dev/null
fakeparrot call GET /api/workflows </dev/null
```

`FAKEPARROT_TOKEN` also accepts a token injected directly by the host's secret
mechanism. Set either it or `FAKEPARROT_TOKEN_FILE`; setting both is an error.
Never put a literal token in an `export` command or command argument. The CLI
reloads a mounted file on each request, so replacing the secret takes effect
without copying it into another credential store.

Set `FAKEPARROT_CREDENTIAL_TYPE=oauth` for an existing employee OAuth grant.
The default for injected credentials is `api-key`. Both modes use existing
`fkp_` tokens and act as the employee; the prefix cannot distinguish their
provenance. The explicit mode selects status/logout behavior, not authority.
The server still resolves the employee, scopes and permissions on every call.
This does not create a service account. Remote interactive login and unattended
machine identity are separate work. Never export the desktop app's credential.

API-key status verifies the credential through authenticated discovery and returns
that response under `body.validation`, with the HTTP status and request ID. It
claims no OAuth session expiry. API-key logout returns
`credential_management_required`; revoke the key at its issuer and remove it from
the host secret mechanism. OAuth status and logout use the existing OAuth routes.
OAuth logout revokes the grant but leaves an externally managed secret file intact;
remove or replace it at the host. Do not log out a shared verification credential.
`whoami` uses `/api/users/me` for API keys and can be refused for a narrow key;
`auth status` remains the scope-independent credential check.

Missing secrets return `authorization_required` with setup instructions and exit
`2`. Unreadable mounts return `credential_read_failed`; malformed input returns
`authorization_invalid`, without echoing the secret. Revoked credentials retain
the API's exact 401 response and exit `3`. Refusals retain the API body, status and
request ID. Injected credentials never fall back to Mac sign-in or get retried
with another identity. A transport failure during a write reports an unknown
outcome; inspect its receipt or current state before retrying.

### Exact clean-container quickstart

Have the host's secret manager provide an existing employee credential at
`/absolute/path/employee-token`. The following downloads and installs the pinned
release inside a clean Debian container, verifies its checksum, checks the
credential, discovers workflows and performs an authorized read. For an OAuth
grant, change only `FAKEPARROT_CREDENTIAL_TYPE` to `oauth`.

```sh
docker run --rm -i \
  --mount type=bind,source=/absolute/path/employee-token,target=/run/secrets/fakeparrot,readonly \
  -e FAKEPARROT_TOKEN_FILE=/run/secrets/fakeparrot \
  -e FAKEPARROT_CREDENTIAL_TYPE=api-key \
  debian:bookworm-slim sh -s <<'CONTAINER'
set -eu
apt-get update -qq
apt-get install -y -qq --no-install-recommends ca-certificates curl >/dev/null
case "$(uname -m)" in
  x86_64) arch=x86_64 ;;
  aarch64) arch=aarch64 ;;
  *) exit 2 ;;
esac
base=https://storage.googleapis.com/valiant-cycle-476400-i8-cli-releases/linux/1.0.1
cd /tmp
curl -fsSLO "$base/fakeparrot-1.0.1-linux-$arch.tar.gz"
curl -fsSLO "$base/SHA256SUMS"
sha256sum --check --ignore-missing SHA256SUMS
tar -xzf "fakeparrot-1.0.1-linux-$arch.tar.gz"
install -m 755 fakeparrot /usr/local/bin/fakeparrot
fakeparrot version </dev/null
fakeparrot auth status </dev/null
fakeparrot describe /api/workflows </dev/null
fakeparrot call GET /api/workflows </dev/null
CONTAINER
```

Use a key with `workflows:read` or the employee standard scopes for this example.
Discovery reports token admission; resource permissions are checked when the
operation runs. Supply request JSON on stdin and repeat `--query KEY=VALUE` for
repeated parameters. Binary or large responses require `--output FILE`; metadata
includes its absolute path, byte count, content type and SHA-256. Keep files on a
mounted output volume when the container exits.

## Sign in

These interactive sign-in and Keychain steps apply to Mac. Linux uses the injected
credential setup above.

### Through the Mac app

While the Mac app is signed in, you do not need to do anything. The first
command asks the app for a sign-in of the command's own. Nothing opens in your
browser, and the app's own sign-in never leaves the app.

Check that it worked:

```sh
fakeparrot auth status
```

If the app is not installed or not signed in, the command answers
`authorization_required` and says what to do. An AI app's sandbox can stop the
command from reaching the Mac app. If that happens, run
`fakeparrot auth status` once in Terminal.

### Without the Mac app

```sh
fakeparrot auth login --client claude
```

Name the AI app that will use the command: `claude`, `codex` or `cursor`. The
command opens FakeParrot in your browser, where you confirm your company and
approve the sign-in. It uses OAuth with PKCE, the standard sign-in for apps
that cannot keep a secret, and the browser hands the result back to the
command on your Mac only.

### Where the sign-in is kept

The command keeps its sign-in in macOS Keychain and never prints it. Each
signed-in command appears in the web app under **Connections → Agents →
Signed in**, with the name of its Mac, and you can revoke it there.

Do not copy a FakeParrot token into a prompt, a command, a file or an
environment variable. The command does not need one.

## Commands

| Command | What it does |
|---|---|
| `fakeparrot auth status` | Shows who you are signed in as, and at which company |
| `fakeparrot wiki search "QUERY"` | Searches the company wiki |
| `fakeparrot wiki list` | Lists the wiki's folders and pages |
| `fakeparrot wiki get PAGE` | Reads one page, by its ID or its full link |
| `fakeparrot workflow list` | Lists the company's saved workflows you can see |
| `fakeparrot workflow get WORKFLOW_ID` | Shows one workflow |
| `fakeparrot workflow run WORKFLOW_ID` | Starts a workflow and waits up to 3 minutes for it to finish |
| `fakeparrot report list` | Lists workflow run reports |
| `fakeparrot report get REPORT_ID` | Reads one report |
| `fakeparrot report events REPORT_ID` | Reads a run's step-by-step events |
| `fakeparrot source list` | Lists the connected sources you can read |
| `fakeparrot source get SOURCE_ID` | Shows one source |
| `fakeparrot source sync SOURCE_ID` | Asks FakeParrot to sync a source now |
| `fakeparrot describe QUERY` | Finds API routes that match a word or a path, with their request and response formats |
| `fakeparrot call METHOD PATH` | Calls any FakeParrot API route you can use |

`workflow run` takes `--inputs '{"name":"value"}'` for the workflow's inputs and
`--wait-seconds N` to change how long it waits.

### Calling any route

`describe` and `call` reach the rest of the API. A request body is read from
standard input, never from a flag, and query parameters go in `--query`:

```sh
fakeparrot describe workflows
fakeparrot call GET /api/workflows --query include_system=true < /dev/null
printf '%s' '{"title":"Quarterly review","markdown":"# Quarterly review\n"}' \
  | fakeparrot call POST /api/wiki/sync/v2/pages
```

In an AI app's shell, add `< /dev/null` to a command that sends no body. The
command reads a body whenever its input is not a terminal, so without it the
command waits until the shell times out.

`describe` reports route admission and known prerequisites. It does not prove
you can access every target resource. A few routes always refuse the command's sign-in, for example sharing
and access changes, billing, and sign-in routes. The refusal names the reason.

### Output

Every command prints one JSON object:

```json
{ "ok": true, "status": 200, "request_id": "…", "body": { } }
```

For `call`, `body` is the API answer, unchanged. Convenience commands can
compose several responses. The exit code is `0` on command success, `2`
when the command fails locally, `3` when the API refuses or fails, and `4`
when a wait times out.

`workflow run` reports command completion, not workflow success. Inspect
`body.report.body.presentation.execution_status`, the report outcome and required deliverables even
when `ok` is true and the exit code is `0`. A failed, cancelled or paused run
can have a successful command result. A timeout does not cancel execution.
Keep `body.run.body.run_id` and use `report get` and `report events` to resume
observation; do not start another run merely because the wait ended.

## Set up your AI apps: `fakeparrot integrate`

```sh
fakeparrot integrate
```

This adds a FakeParrot skill (a short set of instructions) to each of
Claude Code, Codex and Cursor that it finds in your home folder, and reports
each one. To set up only one, add `--client claude`, `--client codex` or
`--client cursor`. The skill is set for your user, so it works in every
project without editing each repository.

For Claude Code and Codex, it also adds a short marked block to your personal
instruction file (`~/.claude/CLAUDE.md`, and `~/.codex/AGENTS.md` or
`~/.codex/AGENTS.override.md`). The block makes FakeParrot the app's main
memory, kept in your Private folder. Running `integrate` again replaces the
block, and it never changes the text around it. Cursor keeps its personal rules
in its settings rather than in a file, so it gets only the skill.

If another skill named `fakeparrot` is already in that app, `integrate` leaves
it alone and reports a conflict.

To take the skill and the block out of one app:

```sh
fakeparrot remove --client codex
```

## Sign out

```sh
fakeparrot auth logout
```

On Mac, this ends the command's sign-in and removes it from Keychain. While the Mac
app is signed in, the next command signs in again. To stop both, sign out of
the Mac app. You can also revoke the command from **Connections → Agents →
Signed in** in the web app.

## Discover and retry safely

`fakeparrot describe QUERY` searches caller-aware operation discovery. A single
match includes its complete contract; several matches include `contract_url` so
you can fetch only the one you need with `fakeparrot call GET CONTRACT_PATH`.
Admission does not grant access to every target resource.

Native CLI updates ship in signed installer releases separately from the API.
If your installed `describe` reply lacks `token_admitted`, use the existing command:

```sh
fakeparrot call GET /api/developer/operations --query q=custom-schedule < /dev/null
```

If the installed command does not recognize `--run-request-id`, send
`run_request_id` in the JSON body through `fakeparrot call POST`, as shown in the
[API recipe](/developers/api#start-and-follow-one-workflow). Older CLI builds can
end their combined observation early when reading the current report layout;
read the same report with `report get` and inspect `presentation.execution_status`.
Do not start another run because observation ended.

For `workflow run`, mint a UUID v4 and pass `--run-request-id UUID`. Persist that
key and the exact inputs/title before sending. Reusing them recovers one run after
a lost response; changed intent conflicts. A new intended run needs a new key.
Read the [API recipes](/developers/api) for receipt lifetime, report field paths
and completion checks.

## What the CLI does not do

- There is no Windows build or Homebrew package.
- Linux does not perform interactive OAuth login or use Mac desktop capabilities.
- Employee credentials remain employee delegation. This does not establish an
  unattended machine or service-account identity.
- Dedicated commands cover only part of the API. `describe` and `call` also
  reach workflow authoring, scheduling and other admitted routes. For example,
  discover `PUT /api/workflows/{workflow_id}/custom-schedule` before calling it
  with `workflows:write`. Changing audience or access still has its own token
  restrictions; an MCP connection does not bypass them.

## Help

Email [support@fakeparrot.com](mailto:support@fakeparrot.com). Report security
issues to [security@fakeparrot.com](mailto:security@fakeparrot.com).
