Anythink # Anythink CLI The official command-line interface for [Anythink](https://anythink.cloud) — the headless backend platform for developers and founders. Manage your projects, entities, data, workflows, users, files, and payments without leaving the terminal. [![NuGet](https://img.shields.io/nuget/v/anythink-mcp?logo=nuget&label=anythink-mcp)](https://www.nuget.org/packages/anythink-mcp) [![Release](https://img.shields.io/github/v/release/anythink-cloud/anythink-cli?logo=github&label=release)](https://github.com/anythink-cloud/anythink-cli/releases/latest) [![Homebrew](https://img.shields.io/badge/homebrew-anythink--cloud%2Ftap-F9A825?logo=homebrew&logoColor=white)](https://github.com/anythink-cloud/homebrew-tap) [![MCP Registry](https://img.shields.io/badge/MCP_registry-cloud.anythink%2Fanythink-0098FF)](https://registry.modelcontextprotocol.io) [![License: MIT](https://img.shields.io/badge/license-MIT-green)](LICENSE) ``` ░███ ░██ ░██ ░██ ░██ ░██░██ ░██ ░██ ░██ ░██ ░██ ░████████ ░██ ░██ ░████████ ░████████ ░██░████████ ░██ ░██ ░█████████ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██░██ ░██ ░███████ ░██ ░██ ░██ ░██ ░██ ░███ ░██ ░██ ░██ ░██░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░█████░██ ░████ ░██ ░██ ░██░██ ░██ ░██ ░██ ░██ ░███████ ``` --- ## Contents - [Installation](#installation) - [Getting started](#getting-started) - [Command reference](#command-reference) - [signup / login / logout](#signup--login--logout) - [accounts](#accounts) - [projects](#projects) - [config](#config) - [entities](#entities) - [fields](#fields) - [data](#data) - [search](#search) - [workflows](#workflows) - [users](#users) - [files](#files) - [email](#email) - [roles](#roles) - [api-keys](#api-keys) - [menus](#menus) - [charts](#charts) - [dashboards](#dashboards) - [settings](#settings) - [integrations](#integrations) - [pay](#pay) - [oauth](#oauth) - [api](#api) - [docs](#docs) - [migrate](#migrate) - [plans](#plans) - [MCP server](#mcp-server) - [Contributing](#contributing) - [License](#license) --- ## Installation Both the `anythink` CLI and the `anythink-mcp` server are distributed together. The quickest way to get both is Homebrew. ### Homebrew (macOS / Linux) — recommended ```bash brew install anythink-cloud/tap/anythink ``` This installs **both** commands onto your `PATH`: - `anythink` — the CLI - `anythink-mcp` — the MCP server (see [MCP server](#mcp-server)) Or tap first, then install: ```bash brew tap anythink-cloud/tap brew install anythink ``` Update to the latest release: ```bash brew upgrade anythink ``` Uninstall: ```bash brew uninstall anythink ``` ### macOS / Linux — download binary Grab the latest release for your platform from the [Releases](https://github.com/anythink-cloud/anythink-cli/releases/latest) page: | Platform | Binary | | --------------------- | ---------------------- | | macOS (Apple Silicon) | `anythink-osx-arm64` | | macOS (Intel) | `anythink-osx-x64` | | Linux (x86_64) | `anythink-linux-x64` | | Linux (ARM64) | `anythink-linux-arm64` | ```bash # Example — macOS Apple Silicon curl -Lo anythink https://github.com/anythink-cloud/anythink-cli/releases/latest/download/anythink-osx-arm64 chmod +x anythink sudo mv anythink /usr/local/bin/ ``` The MCP server ships as a matching `anythink-mcp-` binary on the same release — download and install it the same way (e.g. `anythink-mcp-osx-arm64`). Verify the download against `checksums.txt` in the release assets: ```bash sha256sum -c checksums.txt --ignore-missing ``` ### .NET global tool If you have the [.NET 8 SDK](https://dotnet.microsoft.com/download) installed: ```bash dotnet tool install --global anythink-cli ``` ### Build from source ```bash git clone https://github.com/anythink-cloud/anythink-cli cd anythink-cli dotnet build dotnet run --project src/AnythinkCli.csproj -- --help ``` --- ## Getting started ```bash # 1. Create an account (or log in if you already have one) anythink signup # 2. Create a billing account anythink accounts create --name "My Company" # 3. Create a project anythink projects create "My App" --region lon1 # 4. Connect to the project anythink projects use # 5. Start building anythink entities list anythink workflows list ``` Your credentials and project profiles are stored in `~/.anythink/config.json`. You can manage multiple projects by running `projects use` to switch between them. --- ## Command reference ### signup / login / logout ``` anythink signup Create a new Anythink account anythink login Log in to the platform anythink logout Remove saved credentials for a project profile ``` `signup` and `login` are interactive — they prompt for email and password and walk you through connecting to a billing account and project on first run. --- ### accounts Manage billing accounts. A billing account is the container for one or more projects and holds your subscription and payment details. ``` anythink accounts list List your billing accounts anythink accounts create Create a new billing account anythink accounts use Set the active billing account ``` **Examples** ```bash anythink accounts create --name "Acme Ltd" --email billing@acme.com anythink accounts use a1b2c3d4 ``` --- ### projects Create and manage Anythink projects. Each project is an isolated backend instance with its own database, auth, files, and workflows. ``` anythink projects list List projects in the active billing account anythink projects create Create a new project anythink projects use Connect to a project (sets it as the active profile) anythink projects delete Delete a project ``` **Options — `projects create`** | Flag | Description | | --------------- | ------------------------------- | | `--region ` | Deployment region (e.g. `lon1`) | | `--plan ` | Plan ID (see `anythink plans`) | **Examples** ```bash anythink projects create "My App" --region lon1 anythink projects use a1b2c3d4 anythink projects delete a1b2c3d4 --yes ``` --- ### config View and manage saved CLI profiles. ``` anythink config show List all profiles and platform settings anythink config use Set the active project profile anythink config remove Remove a profile ``` Profiles are named by project alias or ID and stored in `~/.anythink/config.json`. --- ### entities Manage entities (database tables) in the active project. ``` anythink entities list List all entities anythink entities get Get entity details and fields anythink entities create Create a new entity anythink entities update Update entity settings anythink entities delete Delete an entity and all its data ``` **Options — `entities create`** | Flag | Description | | ------------ | ------------------------------------------ | | `--rls` | Enable row-level security | | `--public` | Make the entity publicly readable | | `--lock` | Lock new records (prevent direct creation) | | `--junction` | Mark as a junction (many-to-many) table | **Examples** ```bash anythink entities create orders --rls anythink entities get customers anythink entities delete temp_data --yes ``` --- ### fields Manage fields on an entity. Fields map directly to database columns. ``` anythink fields list List fields on an entity anythink fields add Add a field anythink fields delete Delete a field ``` **Options — `fields add`** | Flag | Description | | ------------------- | --------------------------------------------------------------------------------- | | `--type ` | Field type: `varchar`, `text`, `int`, `float`, `bool`, `datetime`, `json`, `uuid` | | `--required` | Mark the field as required | | `--unique` | Enforce a unique constraint | | `--indexed` | Add a database index | | `--default ` | Default value | **Examples** ```bash anythink fields list customers anythink fields add customers email --type varchar --unique --required anythink fields add products price --type float --required anythink fields delete customers 1234 --yes ``` --- ### data CRUD operations on entity records. ``` anythink data list List records anythink data get Get a single record by ID anythink data create Create a new record anythink data update Update a record anythink data delete Delete a record anythink data export Export records to CSV, JSON or JSONL anythink data import Create records from CSV, JSON or JSONL ``` **Options — `data list`** | Flag | Description | | ----------------- | ---------------------------------------------------------------------------------- | | `--limit ` | Records per page (default: 20) | | `--page ` | Page number (default: 1) | | `--filter ` | Field filters — JSON (`{"status":"draft","total":{"gte":10}}`) or `field=value` pairs (`status=draft&total=GTE:10`). See below. | | `--json` | Output raw JSON instead of table | | `--all` | Stream all pages as sequential JSON objects (requires `--json`, constant memory) | **Filter operators (JSON form)** — `{"field": value}` matches exactly, `{"field": [a, b]}` matches any, `{"field": null}` matches empty. For anything else use an operator object, e.g. `{"price": {"gte": 10, "lt": 100}}`: | Operator | Meaning | `field=value` form | | ------------------------------ | --------------------------- | ------------------ | | `eq` / `ne` | Equal / not equal | `x=v` / `x=!v` | | `gt` `gte` `lt` `lte` | Comparisons | `x=GT:v` … | | `contains` / `not_contains` | Case-insensitive substring | `x=C:v` / `x=NC:v` | | `starts_with` / `ends_with` | Case-insensitive prefix/suffix | `x=SW:v` / `x=EW:v` | | `in` | Any of a list | `x=IN:a,b` | | `null: true` / `null: false` | Empty / not empty | `x=NULL:` / `x=NNULL:` | | `exists: true` / `exists: false` | Has / lacks related records | `x=EXISTS:` / `x=NOT_EXISTS:` | **Options — `data create` / `data update`** | Flag | Description | | --------------- | --------------------------- | | `--data ` | JSON object of field values | **Examples** ```bash anythink data list blog_posts --limit 10 anythink data get blog_posts 42 anythink data create blog_posts --data '{"title":"Hello World","status":"draft"}' anythink data update blog_posts 42 --data '{"status":"approved"}' anythink data delete blog_posts 42 --yes ``` **Export and import** — `data export` streams records page by page to a file; `data import` creates one record per row. Always run an import with `--dry-run` first: it validates every row and sends nothing. ```bash anythink data export customers customers.csv anythink data export orders orders.jsonl --filter 'status=paid' --fields id,total anythink data import customers customers.csv --dry-run anythink data import customers customers.csv --errors rejected.csv --yes ``` | Flag (`export`) | Description | | --------------------- | ----------- | | `--format ` | `csv`, `json` or `jsonl`. Default: from the extension (`.csv`, `.json`, `.jsonl`, `.ndjson`). `-` as the file writes to stdout (needs `--format`) | | `--filter ` | Same syntax as `data list --filter` | | `--fields a,b` | Columns to export, in order. CSV defaults to the entity's fields | | `--page-size ` | Records per request (default 200, max 1000) | | `--force` | Overwrite an existing file. Without it an existing file is never touched. The file is written to a temporary name and renamed on success, so a failed export never leaves a partial file | | `--no-formula-guard` | CSV only: see below | | Flag (`import`) | Description | | --------------------- | ----------- | | `--format ` | `csv`, `json` (an array of objects) or `jsonl`. Default: from the extension, else the first character (`[` or `{`) | | `--dry-run` | Validate and report; nothing is sent | | `--concurrency ` | Parallel creates (default 4, max 16) | | `--errors ` | Write skipped and failed rows, with an `_error` column or property, so they can be fixed and re-imported | | `--ignore-unknown` | Drop columns that aren't fields on the entity instead of rejecting the row | | `--yes` | Skip the confirmation prompt. Required when not running interactively (CI, scripts, agents), otherwise the import refuses before writing anything | How values are handled: - **CSV is RFC 4180**: cells containing a comma, quote or line break are quoted, quotes are doubled, and quoted cells can span lines. Objects, arrays, JSON fields and relations are written as compact JSON text. - **Formula guard (export)**: CSV text starting with `=`, `+`, `-`, `@`, tab or carriage return is prefixed with `'` so spreadsheets don't run it as a formula. Numbers are never changed. This includes phone numbers such as `+44 20 7946 0000` and any text with a leading `+` or `-`. The guard is one-way: importing the file keeps the `'` unless the file was exported with `--no-formula-guard`. - **Types follow the entity's fields.** Text keeps its exact characters (`00123` stays `00123`); integers and decimals are parsed with `.` as the decimal separator (`1,5` is rejected, never guessed); booleans accept `true/false`, `1/0` and `yes/no`; dates must be ISO 8601 (`2025-03-31`, `2025-03-31T09:30:00Z`; no offset means UTC); JSON fields must be valid JSON. - **An empty CSV cell is sent as `null`.** In JSON and JSONL input an empty string stays an empty string. - **Bad rows are skipped, never sent.** They are reported with a row number (CSV: record number, so the header is row 1; JSONL: line number; JSON: position in the array) and counted as *skipped*. Rows the server rejects are counted as *failed*. The exit code is non-zero if any row was skipped or failed. - **Retries**: `400`, `409` and `422` are never retried, so a create is not repeated. See *Uncertain failures* below for what is retried. - **System columns are ignored on import**: `id`, `created_at`, `updated_at`, `tenant_id` and `locked` are never sent, and the import says which it ignored. Importing an export back into the same project therefore creates duplicates with new ids and timestamps; it does not update the originals. - **One-to-many collections and secret fields are skipped on import** (the import lists them), and one-to-many columns are left out of an export unless you name them in `--fields`. Many-to-many, file and user columns are copied as ids, which only mean something inside the same project; the import warns once per column. - **Empty boolean cells** are sent as `null` rather than `false`. - **Uncertain failures**: only `429`/`503` responses and requests that never reached the server (DNS, connection or TLS failures) are retried. If a request times out or the connection drops after sending, the row is reported as `UNCERTAIN: may have been created`, in the errors file too; check the project before re-importing it. Rate-limit waits pause every worker together and are retried for over a minute before giving up. - **Ctrl+C** stops reading the file, finishes the rows already queued and prints a partial summary (exit code 1). An interrupted export removes its temporary file. - `data import` and `data export` read and write local files, so they are not available through the hosted (HTTP) MCP server. Not supported yet: updating or upserting existing records by key, looking up relations by a natural key (use the related record's id), and file uploads. --- ### search Full-text search across your entities, plus index lifecycle management. ``` anythink search query Run a search anythink search similar Find similar documents anythink search rehydrate [] Rebuild the search index (admin) anythink search purge [] Wipe the search index (admin) anythink search audit Compare configured public-searchable fields with what public search actually returns ``` **Options — `search query`** | Flag | Description | | --------------------- | -------------------------------------------------------------------------------------- | | `--entities ` | Comma-separated entity names. Default: all indexed entities. | | `--filter ` | Filter expression, e.g. `"status=published AND category=news"`. Supports `_geoRadius`. | | `--sort ` | Comma-separated sort fields, e.g. `"created_at:desc,id:asc"`. | | `--facet ` | Comma-separated fields to compute facet counts on. | | `--highlight` | Highlight matched terms in results. | | `--page N` | Page number (default: 1). | | `--limit N` | Results per page (1-100, default: 20). | | `--public` | Use the unauthenticated `/search/public` endpoint (only public-marked fields). | | `--json` | Print the raw response JSON. | **Index lifecycle** `rehydrate` and `purge` are admin operations on the search index: - `search rehydrate` — rebuilds the index from the database (no data loss; just resyncs) - `search purge` — deletes the index (run `rehydrate` after to repopulate) Both confirm by default; pass `-y` / `--yes` to skip the prompt for automation. **`search audit` — public-search data leak check** Compares what the entity's schema *says* should be public-searchable (fields with `publicly_searchable=true` and the entity's own `is_public=true`) against what `/search/public` actually returns. Any field appearing in public results that isn't on the allowlist is reported as a leak. Exits with code 1 if a leak is detected — useful for CI/CD. **Examples** ```bash # Browse everything anythink search query "*" # Filtered search with sorting anythink search query "anythink" --filter "status=published" --sort "created_at:desc" # Compare what public visitors see vs what's in the database anythink search audit posts anythink search audit users --query "alice" --sample 10 # Reindex after a schema change anythink search rehydrate posts anythink search rehydrate --yes # everything (admin) # Geo search (radius in metres) anythink search query "*" --filter "_geoRadius(51.5074,-0.1278,5000)" ``` --- ### workflows Manage automation workflows. A workflow can have several triggers: a cron schedule, an entity event, an API route, or a manual run. ``` anythink workflows list List all workflows (--json for a compact summary) anythink workflows get Get workflow details and steps (--json for the full definition) anythink workflows create Create a new workflow anythink workflows update Rename a workflow or change its description anythink workflows enable Enable a workflow anythink workflows disable Disable a workflow anythink workflows trigger Manually trigger a workflow anythink workflows delete Delete a workflow ``` **Trigger types — `workflows create --trigger `** (not case-sensitive; default `Manual`) | Type | Fires | Required flag | Other flags | | -------- | ------------------------------------- | ---------------------- | ------------------------------------ | | `Manual` | When run by hand, on an entity | `--entity ` | | | `Event` | When an event happens, such as a record being created | `--entity ` for the `Entity...` events | `--event `, `--filter ` | | `Timed` | On a cron schedule | `--cron ` | | | `Api` | When its API route is called | `--api-route ` | | `--event` (not case-sensitive) is `EntityCreated` (default), `EntityUpdated`, `EntityDeleted`, `UserRegistered`, `UserInvited`, `SubscriptionCreated`, `SubscriptionActivated`, `SubscriptionExpired`, `PaymentCreated`, `PaymentSucceeded`, `PaymentFailed`, `PaymentMethodCaptured`, `PaymentMethodCaptureFailed`, `PaymentMethodRemoved` or `PushActionTaken`; only the three `Entity...` events need `--entity`. A trigger missing its required flag is rejected before anything is sent, and a flag that doesn't apply to the chosen type is ignored with a warning. **Other options — `workflows create`** | Flag | Description | | ----------------------- | ------------------------------------------------- | | `--description ` | Workflow description | | `--enabled` | Enable the workflow straight away | | `--filter-file ` | Read the `Event` filter JSON from a file | **Examples** ```bash anythink workflows create daily-sync --trigger Timed --cron "0 6 * * *" anythink workflows create on-post --trigger Event --entity blog_posts --event EntityUpdated anythink workflows create import-hook --trigger Api --api-route hooks/import anythink workflows create review-posts --entity blog_posts anythink workflows trigger 76 anythink workflows disable 83 ``` --- ### users Manage users in the active project. ``` anythink users list List all users anythink users me Show the currently authenticated user anythink users get Get a user by ID anythink users invite Create a user and send an invitation email anythink users delete Delete a user ``` **Options — `users invite`** | Flag | Description | | ---------------- | ----------------------------- | | `--role-id ` | Assign a role to the new user | **Examples** ```bash anythink users list anythink users invite alice@example.com Alice Smith --role-id 3 anythink users delete 42 --yes ``` --- ### files Manage uploaded files in the active project. ``` anythink files list List uploaded files anythink files get Get file metadata by ID anythink files upload Upload a file anythink files delete Delete a file ``` **Options — `files list`** | Flag | Description | | ------------- | ---------------------------- | | `--page ` | Page number | | `--limit ` | Files per page (default: 25) | **Options — `files upload`** | Flag | Description | | ---------- | --------------------------------- | | `--public` | Make the file publicly accessible | **Examples** ```bash anythink files list anythink files upload logo.png --public anythink files upload export.csv anythink files delete 12 --yes ``` --- ### email View and edit the project's transactional email templates (confirmation, invite, recovery and so on) and the HTML shell that wraps every email's body. Email commands need the project's email permissions; the API enforces them for whoever is signed in. ``` anythink email templates list List the project's email templates anythink email templates show Show a template's subject and content anythink email templates update Change a template's subject and/or content anythink email preview Render an unsaved draft and print the HTML anythink email shell show Show the shell HTML (custom or platform default) anythink email shell update Save new shell HTML, or reset it ``` **Options — `email templates show`** | Flag | Description | | ------------ | -------------------------------------------------------- | | `--rendered` | Print the rendered HTML (with sample data) instead of the source | **Options — `email templates update`** | Flag | Description | | ----------------------- | --------------------------------------------------------------------- | | `--subject ` | New subject line | | `--content ` | File with the new content (use `-` to read stdin) | | `--content-text ` | The new content, passed inline (use this or `--content`, not both) | Pass at least one of the subject or the content. Whatever you leave out keeps its current value. Empty content is refused. **Options — `email preview`** (renders on the server and saves nothing) | Flag | Description | | ----------------------- | -------------------------------------------------------- | | `--subject ` | Subject to render (default: `Preview`) | | `--content ` | File with the content (use `-` for stdin) | | `--content-text ` | The content, passed inline | | `--wrapper ` | Optional shell HTML to render against (use `-` for stdin)| | `--wrapper-text ` | Optional shell HTML, passed inline | **Options — `email shell update`** (pass exactly one) | Flag | Description | | ------------------- | ----------------------------------------------------- | | `--html ` | File with the new shell HTML (use `-` for stdin) | | `--html-text `| The new shell HTML, passed inline | | `--reset` | Go back to the platform default shell | HTML is limited to 1,000,000 characters. The shell and template commands print raw HTML, so you can redirect it to a file. Through the MCP server the file options are not offered, so agents pass the HTML inline with `content_text`, `wrapper_text` and `html_text`. **Examples** ```bash anythink email templates list anythink email templates show confirmation --rendered > confirmation.html anythink email templates update confirmation --subject "Welcome aboard" anythink email templates update confirmation --content ./confirmation.html cat confirmation.html | anythink email templates update confirmation --content - anythink email preview --subject "Hi" --content ./draft.html --wrapper ./shell.html anythink email shell show > shell.html anythink email shell update --html ./shell.html anythink email shell update --reset ``` --- ### roles Manage roles in the active project. Roles control what authenticated users can access. ``` anythink roles list List all roles anythink roles create Create a new role anythink roles delete Delete a role ``` **Options — `roles create`** | Flag | Description | | ---------------------- | -------------------------------------- | | `--description ` | Human-readable description of the role | **Examples** ```bash anythink roles list anythink roles create editor --description "Can edit content" anythink roles delete 5 --yes ``` --- ### api-keys Issue and manage API keys for non-interactive access (CI pipelines, scripts, integrations). Each key is scoped to a permission set, has an expiry, and is tied to the user that created it. The raw key is shown **once** on creation and never retrievable — save it immediately or use `--save-as` to write it directly into a CLI profile. ``` anythink api-keys list List your API keys anythink api-keys create --permissions ... Create a new key anythink api-keys revoke Revoke a key ``` **Options — `api-keys create`** | Flag | Description | | ----------------------- | ---------------------------------------------------------------------------- | | `--permissions ` | Required. Comma-separated permission names, e.g. `data:read,data:create` | | `--expires-in ` | Days until expiry (default: 90, max: 365) | | `--no-expiry-cap` | Allow `--expires-in` greater than 365 days | | `--save-as ` | Save the new key directly to a CLI profile instead of printing it | | `--json` | Print the response as JSON to stdout (the key is in this output — handle carefully) | | `-y, --yes` | Skip the confirmation prompt | **Output behaviour** By default, the success message goes to **stdout** and the raw key goes to **stderr** on its own line. This makes it easy to capture only the key: ```bash anythink api-keys create ci-deploy --permissions data:read --yes 2> key.txt ``` If the server drops any of the requested permissions because the current user does not hold them, the CLI surfaces a loud warning so you do not end up with a quietly under-scoped key. **Examples** ```bash # Create a 90-day key for CI anythink api-keys create github-actions --permissions "data:read,data:create" --yes 2> key.txt # Create a key and save it directly into a profile (key never echoes) anythink api-keys create scraper --permissions data:read --save-as scraper-bot --yes anythink --profile scraper-bot data list posts # Revoke a key anythink api-keys revoke 42 --yes ``` --- ### menus Manage dashboard sidebar menus in the active project. Menus control what entities appear in the Anythink dashboard and how they are grouped. ``` anythink menus list List all menus with tree structure anythink menus get [--json] Show one menu (and its role) with its items and child items anythink menus create Create a menu shown to a role anythink menus update [--name ] [--role ] Rename a menu or change its role anythink menus delete [--yes] Delete a menu and all of its items anythink menus add-item Add an entity to a dashboard menu anythink menus update-item [options] Change an item's name, icon, link or parent anythink menus remove-item [--yes] Remove an item, along with its child items anythink menus reorder-items Set the order of items that share a parent anythink menus reorder Set the order of menus ``` **Options — `menus add-item`** | Flag | Description | | ----------------- | ---------------------------------------------------- | | `--icon ` | Lucide icon name (e.g. `MessageCircle`, `Target`) | | `--name ` | Display name (defaults to entity name, title-cased) | | `--parent ` | Parent menu item ID for nesting under a group | **Options — `menus update-item`** (only the fields you pass change) | Flag | Description | | ----------------- | ---------------------------------------------------------- | | `--name ` | New display name | | `--icon ` | New Lucide icon name | | `--entity ` | Point the item at an entity's page (instead of `--href`) | | `--href ` | Point the item at any path (instead of `--entity`) | | `--parent ` | Parent item ID to nest under; `0` moves it to the top level | `reorder-items` and `reorder` take comma-separated IDs in the order you want them (`301,299,300`). The items you name take the first places within their group; items you leave out follow in their current order, and `reorder-items` needs all the items to share one parent. Locked items (the built-in ones) can't be changed, removed or moved; they keep their place, and the items between them reuse their own position numbers (they are only renumbered when two of them tie). `add-item` and `update-item --entity` look the entity up first (system entities count), and stop only if it doesn't exist; if the lookup itself fails (for example, no permission), the item is saved and a warning says the entity couldn't be checked. Moving an item to a new parent with `update-item --parent` puts it last among its new siblings. Removing an item also removes its direct child items. The command says so, and refuses when those children are locked or have items of their own. A role is shown only its first menu, so `create` (and `update --role`) warns when the role already has one. `delete` removes the menu's locked built-in items with it, and says when the role is left with no menu. **Examples** ```bash # List all menus and their items anythink menus list # Show menu 250 with the item IDs you need for the commands below anythink menus get 250 # Add "Check-ins" under the Profiles group (parent 168) in admin menu (250) anythink menus add-item 250 check_ins --icon MessageCircle --parent 168 # Add a top-level menu item anythink menus add-item 250 badges --icon Award # Rename an item and give it another icon anythink menus update-item 250 299 --name "Achievements" --icon Trophy # Remove an item anythink menus remove-item 250 299 --yes # Put items 301, 299 and 300 first, in that order anythink menus reorder-items 250 301,299,300 ``` --- ### charts Build and manage the charts shown on dashboards in the active project. Every command takes `--json`, which prints a compact result with the ids the next step needs. In the MCP server each command is a tool of the same name (`charts_create`, `charts_preview` and so on). ``` anythink charts list [--entity ] List charts, newest first anythink charts get Show a chart's configuration anythink charts create [options] Create a chart anythink charts update [options] Change a chart; options you leave out keep their value anythink charts delete [--yes] Delete a chart anythink charts preview [options] Show the data a configuration would draw, without saving it anythink charts platform-metrics List the usage metrics a platform chart can plot ``` **Options — `charts create`, `charts update` and `charts preview`** | Flag | Description | | ---------------------------- | -------------------------------------------------------------------------------------------- | | `--entity ` | Entity whose records the chart plots | | `--type ` | `column` (bar chart), `line`, `pie`, `area`, `stat`, `gauge` or `funnel` | | `--group-by ` | Field for the x axis, or the slices of a pie | | `--interval ` | Bucket a date `--group-by`: `hour`, `day`, `week`, `month`, `quarter` or `year` | | `--measure ` | Numeric field to aggregate (needed unless `--agg` is `count`) | | `--agg ` | `count` (default), `sum`, `avg`, `min` or `max` | | `--stack-by ` | Field that splits each bar or point into a second breakdown | | `--filter ` | Filter such as `status:eq:published`. Operators: `eq ne gt gte lt lte contains in exists not_exists`. Repeat for several fields; a chart keeps one filter per field | | `--timeframe ` | `all`, `24h`, `7d`, `30d`, `90d`, `365d` or `custom` (with `--from` and `--to`) | | `--limit `, `--sort `, `--cumulative ` | Row limit, sort order and running total | | `--target `, `--target-mode ` | A goal or warning level on a stat or gauge | | `--compare `, `--compare-days `, `--compare-overlay ` | Compare with the previous period | | `--source ` | Where the data comes from. Platform charts use `--platform-metric` (see `charts platform-metrics`), quota charts use `--quota-metric` | | `--config ` | Anything else, as a JSON object, e.g. `{"funnelStages":[{"label":"Signed up"}]}` for a funnel. Typed options win over it | | `--rows ` | `charts preview` only: most rows to show (default 50) | A missing or unknown value is refused before anything is sent, with a message naming it. Check a chart with `charts preview` before `charts create`: it takes the same options and shows what the chart would draw. **Examples** ```bash # What would a pie of orders by status show? anythink charts preview --entity orders --type pie --group-by status # Save it, then a revenue chart with a filter anythink charts create "Orders by status" --entity orders --type pie --group-by status anythink charts create "UK revenue per month" --entity orders --type column --group-by created_at \ --interval month --measure total --agg sum --filter region:eq:uk --timeframe 365d # A usage chart from the platform metrics anythink charts create "Workflow runs" --source platform --platform-metric workflow_runs --type line # Change one thing anythink charts update 12 --timeframe 30d ``` --- ### dashboards Build and manage dashboards. A dashboard is a set of widgets (charts, lists, notes and so on) laid out on a 12-column grid. Every command takes `--json`. ``` anythink dashboards list List the dashboards you can see anythink dashboards get Show a dashboard with its widgets and their positions anythink dashboards mine Show your landing dashboard, or the project default anythink dashboards create [options] Create a dashboard anythink dashboards update [options] Rename it, change who can see it, or replace its widgets and layout anythink dashboards delete [--yes] Delete a dashboard and its widgets (the charts are kept) anythink dashboards add-chart Add a chart as a new widget anythink dashboards remove-widget Remove a widget anythink dashboards data [--widget ] Show the data behind the widgets anythink dashboards widget-preview --type Show the data a widget would draw, without saving it anythink dashboards set-home Make it your landing dashboard anythink dashboards promote-to-default [--yes] Copy it over the project default (administrators only) ``` `add-chart` and `remove-widget` read the dashboard, change only that widget, and write the rest back as it was. **Options** | Command / flag | Description | | ------------------------------------------- | ------------------------------------------------------------------------------------ | | `create --chart ` | Put a chart on the new dashboard. Repeat for several | | `create --description`, `--shared`, `--allow-shared-edit`, `--home`, `--default` | Description, who can see or edit it, and whether it is your landing or the project default dashboard | | `create`/`update --config ` | Other settings as a JSON object: `widgets` (each with `type`, `title` and settings) and `layout`. On `update`, `widgets` replaces the whole list, so include every widget to keep, with its `id` | | `update --name`, `--description`, `--shared `, `--allow-shared-edit ` | The fields to change; the rest are left alone | | `add-chart --title ` | Widget title (defaults to the chart's name) | | `add-chart --column`, `--row`, `--width`, `--height` | Position and size on the grid (default width 4, height 3, placed below the existing widgets). Leave them all out and the dashboard places the widget itself | | `data --widget `, `--rows ` | Only these widgets; most rows to show per widget (default 20) | | `widget-preview --type`, `--chart`, `--config`, `--rows` | Widget type (`chart`, `list`, `markdown`, ...), the chart to show, or the widget's own settings as JSON | **Examples** ```bash # A dashboard with two charts already on it anythink dashboards create Sales --chart 12 --chart 14 # Add a third, half the width of the grid anythink dashboards add-chart 3 15 --width 6 # See what is on it, then take a widget off anythink dashboards get 3 anythink dashboards remove-widget 3 41 # The numbers behind it anythink dashboards data 3 --json ``` --- ### settings View and change project settings in the active project, including the allowed application URLs that browsers may call the API from (CORS). ``` anythink settings get [--json] Show all project settings anythink settings set [--yes] Set a single project setting anythink settings cors list List allowed application URLs anythink settings cors add [--yes] Add an allowed origin anythink settings cors remove Remove an allowed origin ``` **Keys — `settings set`** | Key | Value | | ------------------------------ | ----------------------------------------- | | `name`, `description` | Text | | `require_email_confirmation` | `true` / `false` | | `allow_registrations` | `true` / `false` | | `default_role_id` | Role ID for newly registered users | | `enable_group_rls` | `true` / `false` | | `payment_success_url`, `payment_cancel_url` | URL | | `app_engagement_trial_enabled` | `true` / `false` | | `app_engagement_trial_days` | Number of days | | `ai_mode` | `platform` or `byok` | | `ai_byok_provider`, `ai_default_model` | Text | | `google_maps_key` | Text | Origins must be `http`/`https` with a host and optional port, with no path, query or fragment; a trailing `/` is stripped. A wildcard such as `https://*.example.com` is only safe on a domain you control, so wildcards under shared hosting domains (`vercel.app`, `github.io`, …) or a bare TLD are refused unless you pass `--yes`. Some changes widen who can sign up: `default_role_id` pointing at an administrator role is refused unless you pass `--yes`, and `allow_registrations true` and `require_email_confirmation false` ask for confirmation (pass `--yes` when running non-interactively). `cors add` and `cors remove` clear the project's CORS cache, so the change applies straight away. Matching is case-insensitive and adding a URL that is already present does nothing. Anythink's own domains and `localhost` are always allowed and don't need adding. **Examples** ```bash # Allow a deployed front end to call the API anythink settings cors add https://my-app.vercel.app # Allow every subdomain of a domain you own anythink settings cors add "https://*.example.com" # Remove an origin anythink settings cors remove https://my-app.vercel.app # Let users sign up on their own anythink settings set allow_registrations true ``` --- ### integrations Manage integrations — both the catalog of available providers (Claude, OpenAI, Slack, Google, etc.) and the active connections that hold credentials for them. ``` anythink integrations list List available providers anythink integrations get Show details and operations for one provider anythink integrations connections list [--provider

] List your active connections anythink integrations connect Create an API-key connection (Claude, OpenAI, etc.) anythink integrations oauth status Show OAuth client setup status anythink integrations oauth configure Set the OAuth client ID + secret anythink integrations oauth connect Connect via the browser OAuth flow anythink integrations test Test a connection anythink integrations enable Enable a connection anythink integrations disable Disable a connection anythink integrations disconnect Delete a connection anythink integrations execute Run an operation on a connected provider ``` **API-key providers — `integrations connect`** | Flag | Description | | -------------------- | ---------------------------------------------------------------------------------------- | | `--api-key ` | API key for the provider. If omitted, you'll be prompted (input is hidden). | | `--name ` | Friendly name for this connection (default: ` connection`) | | `--user-connection` | Make this a user-scoped connection (only the current user sees it). Default: tenant-wide. | **OAuth providers — `integrations oauth connect`** The CLI starts a local HTTP listener on `http://localhost:8745/callback`, opens your browser to the provider's authorisation URL, and exchanges the returned code for a connection — no copy/paste of auth codes required. | Flag | Description | | -------------------- | ------------------------------------------------------------------------ | | `--name ` | Friendly name for this connection | | `--user-connection` | Make this a user-scoped connection | | `--port ` | Local callback port (default: `8745`) | | `--no-open` | Don't try to open the browser — just print the URL | | `--timeout ` | How long to wait for the callback (default: `300`) | OAuth credentials need to be set up once per provider before you can connect: ```bash anythink integrations oauth configure slack # prompts for client_id + secret (hidden) anythink integrations oauth connect slack --name main ``` **Running operations — `integrations execute`** | Flag | Description | | ------------------- | ----------------------------------------------------------------------------------- | | `--input ` | Input parameter as `key=value`. Repeatable. | | `--inputs ` | All inputs as a JSON object. | | `--json` | Print the full JSON response (default: just the `content` field if present). | **Examples** ```bash # Browse what's available anythink integrations list anythink integrations get claude # API-key flow (Claude, OpenAI) anythink integrations connect claude --name "main" anythink integrations execute claude generate-text --input "prompt=Tell me a haiku" # OAuth flow (Slack, Google, GitHub) anythink integrations oauth configure slack anythink integrations oauth connect slack --name main # Manage connections anythink integrations connections list anythink integrations test anythink integrations disable anythink integrations disconnect --yes ``` --- ### pay Manage **AnythinkPay** — Stripe Connect, Apple in-app purchases, payments, subscription plans, and live subscriptions. ``` anythink pay status Show Stripe Connect account status anythink pay connect Set up a Stripe Connect account and start onboarding anythink pay setup Guided setup: Stripe Connect, Apple IAP, and a first plan anythink pay payments List recent payments anythink pay methods List saved payment methods anythink pay entitlement Show the current user's access / trial entitlement anythink pay payment-options Show available payment providers for a platform/storefront anythink pay trial status|enable|disable Manage the app engagement trial anythink pay apple credentials set Set Apple IAP credentials (.p8 from a file) anythink pay apple credentials show Show Apple IAP credentials (identifiers masked) anythink pay apple credentials notification-url Print the URL to register in App Store Connect anythink pay apple verify Verify an Apple transaction (testing) anythink pay plans list|get|create|update|delete Manage subscription plans anythink pay subscriptions list|get|events Inspect subscriptions and history anythink pay subscriptions cancel|resume Standard lifecycle actions anythink pay subscriptions delete|force-expire|relink|resync Admin recovery (project admin) anythink pay offers list|get|create|update Manage promo and referral offers anythink pay offers pause|activate Change an offer's status anythink pay offers delete Permanently delete an offer, its codes and redemption records anythink pay offers codes|add-code|redemptions Inspect and extend an offer anythink pay offers user-code Look up a user's personal referral code ``` Commands that cancel, delete, expire, relink or pause (`pay plans delete`, `pay subscriptions cancel|delete|force-expire|relink`, `pay offers pause|delete`) ask for confirmation. Pass `-y`/`--yes` to skip the prompt; in a non-interactive shell they refuse to run without it. `pay plans update` only changes the fields you pass: omitted flags keep the plan's current currency, interval, type and active state. Use `--active` or `--inactive` to change availability. **Options — `pay payments`** | Flag | Description | | ------------- | ------------------------------- | | `--page ` | Page number | | `--limit ` | Payments per page (default: 25) | `pay connect` is interactive — it prompts for business type, country, and contact email, creates a Stripe Connect account, then opens the Stripe onboarding URL in your browser. `pay setup` chains Stripe Connect, Apple IAP credentials, and a first plan; each step is optional. Subscription plans can carry an `--apple-product-id` (and optional `--apple-subscription-group-id`) so one plan covers both Stripe and Apple. `pay apple credentials set` reads the App Store Connect `.p8` private key from a file and stores it encrypted — it is never printed or logged. **Required permissions** | Command surface | Permission | | --- | --- | | Plan / subscription reads, entitlement, payment-options | `anythink_subscription_plans:read` | | Plan writes | `anythink_subscription_plans:create` / `:update` / `:delete` | | Payment reads/writes | `anythink_payments:read` / `:create` | | Apple credentials, admin recovery (`delete`/`force-expire`/`relink`/`resync`) | project administrator | **Examples** ```bash anythink pay setup anythink pay plans create --plan-name monthly --name Monthly --amount 9.99 --currency gbp --interval month --apple-product-id example_monthly anythink pay apple credentials set --issuer-id --key-id --bundle-id com.example.app --private-key-file ./AuthKey.p8 anythink pay apple verify --signed-transaction anythink pay subscriptions events anythink pay entitlement ``` --- ### oauth Configure OAuth social sign-in providers for the active project. ``` anythink oauth google status Show Google OAuth configuration status anythink oauth google configure Set Google OAuth client ID and secret ``` Google OAuth lets your project's users sign in with their Google account. You'll need a Google Cloud project with the OAuth 2.0 credentials created — see the [Google Cloud Console](https://console.cloud.google.com/apis/credentials). Set the authorised redirect URI in your Google Cloud credentials to: ``` https://api.my.anythink.cloud/org//auth/v1/google/callback ``` **Examples** ```bash anythink oauth google status anythink oauth google configure ``` --- ### api List all API endpoints available for the active project — both platform routes and the dynamically generated REST routes for your entities. ``` anythink api List all endpoints anythink api --json Output as JSON (useful for AI tooling) ``` --- ### docs Print the full CLI reference. ``` anythink docs Print reference as markdown anythink docs --json Print reference as JSON (for AI/tooling consumption) ``` --- ### migrate Copy the entity schema (entities + fields) from one project profile to another. Useful for promoting a schema from staging to production. ``` anythink migrate --from --to ``` **Options** | Flag | Description | | ------------------ | -------------------------------------------------- | | `--from ` | Source profile name (required) | | `--to ` | Destination profile name (required) | | `--dry-run` | Show what would be migrated without making changes | **Examples** ```bash anythink migrate --from my-app-staging --to my-app-prod anythink migrate --from my-app-staging --to my-app-prod --dry-run ``` --- ### plans List available Anythink plans. ``` anythink plans List plans anythink plans --json Output as JSON ``` --- ## MCP server The Anythink MCP server exposes the platform to AI assistants (Claude, Cursor, etc.) via the [Model Context Protocol](https://modelcontextprotocol.io). ### Install No install needed — the recommended way is to run it on demand with `npx`: ```bash npx -y @anythink-cloud/mcp ``` Prefer a native binary on your `PATH`? Any of: ```bash # Homebrew (bundled with the CLI — see Installation above) brew install anythink-cloud/tap/anythink # .NET global tool (requires the .NET 8 SDK) dotnet tool install -g anythink-mcp # Or download the anythink-mcp- binary from the Releases page ``` ### Configure [![Add to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en/install-mcp?name=anythink&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBhbnl0aGluay1jbG91ZC9tY3AiXX0%3D) [![Install in VS Code](https://img.shields.io/badge/Install-VS_Code-007ACC?logo=visualstudiocode&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=anythink&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40anythink-cloud%2Fmcp%22%5D%7D) For **Claude Code**, register it in one command: ```bash claude mcp add anythink -- npx -y @anythink-cloud/mcp ``` Or add it to your MCP client config manually (e.g. `.mcp.json`): ```json { "mcpServers": { "anythink": { "command": "npx", "args": ["-y", "@anythink-cloud/mcp"] } } } ``` To pin a profile, add it to `args`: `["-y", "@anythink-cloud/mcp", "--profile", "my-project"]` Works in any MCP client. Most use the same `mcpServers` JSON shown above — just add it to the client's config file: | Client | Config file | | --- | --- | | Claude Code | `claude mcp add anythink -- npx -y @anythink-cloud/mcp` (or `.mcp.json`) | | Claude Desktop | `claude_desktop_config.json` (Settings → Developer → Edit Config) | | Cursor | `~/.cursor/mcp.json` (or the **Add to Cursor** button above) | | VS Code | `.vscode/mcp.json` (or the **Install in VS Code** button above) | | Cline | `cline_mcp_settings.json` (MCP Servers → Configure) | | Windsurf | `~/.codeium/windsurf/mcp_config.json` | A couple of clients use a different config shape:

Continue (YAML — mcpServers is a list) ```yaml mcpServers: - name: anythink command: npx args: - -y - "@anythink-cloud/mcp" ```
Zed (uses context_servers, not mcpServers) ```json { "context_servers": { "anythink": { "source": "custom", "command": "npx", "args": ["-y", "@anythink-cloud/mcp"] } } } ```
(Using a native binary instead of `npx`? Use `"command": "anythink-mcp"` with no `args`.) Once connected, run the `login` tool, then `accounts_use` / `projects_use` to pick your working context. ### Available tools The MCP server provides dedicated tools for authentication, account/project management, and configuration — plus a generic `cli` tool that can run any CLI command: | Tool | Description | | --- | --- | | `signup` | Create a new Anythink account | | `login` | Log in with email and password | | `login_direct` | Store credentials directly (org ID + API key or JWT) | | `logout` | Remove a saved profile | | `config_show` | List all profiles | | `config_use` | Switch active profile | | `config_remove` | Remove a profile | | `accounts_list` | List billing accounts | | `accounts_create` | Create a billing account | | `accounts_use` | Set the active billing account | | `projects_list` | List projects | | `projects_create` | Create a project | | `projects_use` | Connect to a project | | `projects_delete` | Delete a project | | `cli` | Run any CLI command (entities, data, workflows, roles, etc.) | The hosted MCP server (`anythink-mcp --hosted`) has no sign-in or profile tools. Its `accounts_list`, `accounts_create`, `plans`, `projects_create` and `projects_delete` tools run as the signed-in user and appear only when the user grants account access; see the [MCP server docs](mcp/README.md#account-tools). --- ## Contributing ### Prerequisites - [.NET 8 SDK](https://dotnet.microsoft.com/download/dotnet/8) - An Anythink account (free tier works) ### Setup ```bash git clone https://github.com/anythink-cloud/anythink-cli cd anythink-cli dotnet build ``` ### Running locally ```bash dotnet run --project src/AnythinkCli.csproj -- --help dotnet run --project src/AnythinkCli.csproj -- projects list dotnet run --project src/AnythinkCli.csproj -- entities list ``` ### Releases Releases are automated via GitHub Actions. Push a version tag to trigger a build: ```bash git tag v1.2.0 git push origin v1.2.0 ``` The workflow builds self-contained binaries for macOS (arm64, x64) and Linux (x64, arm64), computes SHA256 checksums, and publishes them as a GitHub release. ### Project structure ``` anythink-cli/ ├── src/ # CLI source │ ├── Commands/ # Command implementations (signup, login, etc) │ ├── Config/ # CliConfig.cs, Profile, ConfigService │ ├── Models/ # ApiModels.cs, BillingModels.cs │ ├── Client/ # HttpApiClient.cs, AnythinkClient.cs, BillingClient.cs │ ├── Output/ # Renderer.cs (Spectre.Console helpers) │ └── Program.cs # Application entry point & .env loader ├── mcp/ # MCP server source │ ├── Tools/ # MCP tool implementations │ ├── McpClientFactory.cs # Auth + client resolution │ └── Program.cs # MCP server entry point ├── tests/ # CLI unit tests ├── mcp-tests/ # MCP unit tests ├── AnythinkCli.sln # Solution file └── .gitignore ``` --- ## License MIT — see [LICENSE](LICENSE). This covers the Anythink CLI and MCP server source in this repository; it does not grant rights to the Anythink platform, APIs, or services, which are governed by separate terms at [anythink.cloud](https://anythink.cloud). --- Built with [Spectre.Console](https://spectreconsole.net) · Powered by [Anythink](https://anythink.cloud)