# Formanator 🤖 > [!NOTE] > 🦀 Formanator is now built with Rust and distributed through Homebrew and Crates.io! [v2.x](https://github.com/timrogers/formanator/releases/tag/v2.2.0), built in TypeScript and distributed through npm, is [still available](https://github.com/timrogers/formanator/releases/tag/v2.2.0). Formanator allows you to: * **Submit benefit claims to [Forma](https://www.joinforma.com/) and track progress from the command line**, either one-by-one or in bulk * **Understand your Forma benefits and track and submit claims from any Model Context Protocol (MCP) client**, for example [Copilot CLI](https://github.com/features/copilot/cli), [Visual Studio Code](https://code.visualstudio.com/) or [Claude Code](https://code.claude.com/docs/en/overview) With the power of large language models 🧠👀 - via the [GitHub Copilot CLI](https://github.com/features/copilot/cli) (free, no extra configuration needed) or [OpenAI](https://openai.com/) - it can even **analyse your receipts and generate your claims automatically**. ![Screenshot of running `formanator` from a terminal](https://github.com/user-attachments/assets/e053efc8-f4cb-4ea1-8850-6c82d668bf29) ## Installation ### macOS or Linux via [Homebrew](https://brew.sh/) ```bash brew tap timrogers/tap && brew install formanator ``` ### macOS, Linux, or Windows via [Cargo](https://doc.rust-lang.org/cargo/), Rust's package manager 1. Install [Rust](https://www.rust-lang.org/tools/install) on your machine, if it isn't already installed. 1. Install the `formanator` crate by running `cargo install formanator`. 1. Run `formanator --help` to check that everything is working and see the available commands. ### macOS, Linux, or Windows via direct binary download 1. Download the [latest release](https://github.com/timrogers/formanator/releases/latest) for your platform. macOS, Linux, and Windows devices are supported. 1. Add the binary to your `PATH` (or `$PATH` on Unix-like systems), so you can execute it from your shell/terminal. For the best experience, call it `formanator` (or `formanator.exe` on Windows). 1. Run `formanator --help` to check that everything is working. ### From source ```bash git clone https://github.com/timrogers/formanator cd formanator cargo install --path . ``` ### Optional: PDF receipt support To infer claim details for PDF receipts, you need to have [GraphicsMagick](http://www.graphicsmagick.org/) and [Ghostscript](https://www.ghostscript.com/) installed. ```bash # macOS brew install graphicsmagick ghostscript ``` ## Usage ### Connecting to your Forma account To get started, you'll need to connect Formanator to your Forma account: 1. Run `formanator login`. 2. Press Enter to open your browser to the Forma login page. 3. Enter your email address and request a magic link. 4. Copy the magic link from your email and paste it into the terminal. Formanator accepts either the full `joinforma.page.link` URL or its decoded `client.joinforma.com/auth/magic` target. 5. You're logged in 🥳 The access token is securely stored in the system Keychain on macOS. On other platforms, it's stored in `~/.formanator.toml`. ### Automatic update checks Once a day, Formanator checks GitHub for a newer release. When one is available, it prints a yellow notice to stderr before running your command. The check is throttled by recording the last check timestamp in `~/.formanator.toml`, only considers releases that are at least 72 hours old, and times out after 2 seconds so it can't slow the CLI down. To disable the check entirely, set the `FORMANATOR_DISABLE_UPDATE_CHECK` environment variable to any value. ### Configuring inference providers (optional, but recommended) When submitting a claim you can either provide every detail manually or let an LLM infer them. Three providers are supported: - **GitHub Copilot CLI** — _the default._ If you don't configure an OpenAI-compatible API key, Formanator uses the [GitHub Copilot CLI](https://github.com/features/copilot/cli) for inference. Formanator detects the `copilot` binary on your `PATH` automatically; if it lives elsewhere, set the `COPILOT_CLI_PATH` environment variable or pass `--copilot-cli-path` with the path to the binary. - **OpenAI** — billed to your OpenAI account. Set the `OPENAI_API_KEY` environment variable, or pass `--openai-api-key`. You can also customise the model with `OPENAI_MODEL` / `--openai-model` (default: `gpt-5.4-mini`). - **Other OpenAI-compatible inference providers** — any provider with an OpenAI-compatible API (e.g. Azure OpenAI, Ollama, or a local model server). Set `OPENAI_API_KEY` / `--openai-api-key` to your API key and `OPENAI_BASE_URL` / `--openai-base-url` to the provider's base URL (default: `https://api.openai.com/v1`). Set the model with `OPENAI_MODEL` / `--openai-model`. If both an OpenAI-compatible API key and the GitHub Copilot CLI are available, Formanator prefers the OpenAI-compatible API. #### Using Jev for benefit and category selection [Jev](https://docs.typesafe.ai/introduction) is TypeSafe's System One decision model. Instead of generating free-form text, it answers narrowly defined questions with typed choices and calibrated probabilities that application code can validate and act on. When you provide the amount, merchant, purchase date and description yourself, Jev can select the most appropriate benefit and category instead of using the configured LLM: ```bash export TYPESAFE_API_KEY="..." formanator submit-claim \ --amount 1000 \ --merchant "Open University" \ --description "MBA tuition fee" \ --purchase-date 2026-09-20 \ --receipt-path receipt.pdf \ --category-provider jev ``` You can also pass the key with `--typesafe-api-key`, or set `FORMANATOR_CATEGORY_PROVIDER=jev` instead of passing `--category-provider` each time. Jev receives only the merchant, description and the valid benefit/category pairs returned by Forma. It does not receive receipt images. If Jev's confidence is below 0.5 or it determines that none of the available categories match, Formanator visibly falls back to the configured OpenAI-compatible provider or GitHub Copilot CLI. TypeSafe authentication and API errors are reported directly rather than silently falling back. Full inference from a receipt, including benefit and category selection, continues to use the configured vision-capable LLM. ### Submitting claims in bulk #### Automatically submitting all receipts in a directory (recommended) ```bash formanator submit-claims-from-directory --directory input/ ``` All `.jpg`, `.jpeg`, `.png`, `.pdf` and `.heic` receipts in the directory will be analysed by the LLM. You'll be asked to confirm the inferred claim details for each receipt before it's submitted, and successfully-submitted receipts are moved into a `processed/` subdirectory. Every receipt is analysed up front, with a progress bar, so you can walk away while that runs and then confirm all of them back to back. If the LLM provider itself can't be reached — bad API key, missing model, Copilot CLI that won't start — Formanator stops straight away instead of failing its way through the rest of the directory. If you trust the LLM and don't want to confirm anything, add `--yolo` to submit every receipt as soon as it's been analysed: ```bash formanator submit-claims-from-directory --directory input/ --yolo ``` #### Manually submitting receipts using a CSV template 1. Generate a template: `formanator generate-template-csv` (writes `claims.csv`). 2. Fill in one row per claim. You can leave `benefit` and `category` blank to have them inferred from the other fields, optionally using `--category-provider jev`, or leave every column except `receiptPath` blank to have all claim details inferred from the receipt using the configured LLM. Comma-separate paths in the `receiptPath` column to attach multiple receipts. 3. Optionally validate up-front: `formanator validate-csv --input-path claims.csv`. 4. Submit: `formanator submit-claims-from-csv --input-path claims.csv`. ### Submitting a single claim #### Option 1: Infer all claim details from the receipt (recommended) ```bash formanator submit-claim --receipt-path receipt.jpg ``` Formanator will ask the LLM to extract the amount, merchant, purchase date, description, benefit and category, show you the result and ask you to confirm before submitting. Pass `--yolo` to skip the confirmation and submit straight away. #### Option 2: Provide details manually, infer benefit and category ```bash formanator submit-claim \ --amount 2.28 \ --merchant Amazon \ --description "USB cable" \ --purchase-date 2024-01-15 \ --receipt-path USB.pdf ``` #### Option 3: Provide every detail manually ```bash formanator submit-claim \ --amount 2.28 \ --merchant Amazon \ --description "USB cable" \ --purchase-date 2024-01-15 \ --receipt-path USB.pdf \ --benefit "Remote Life" \ --category "Cables & Cords" ``` Use `formanator benefits` and `formanator categories --benefit ` to discover the valid values. ### Listing claims ```bash formanator list-claims formanator list-claims --filter in_progress ``` ## Model Context Protocol (MCP) usage Formanator can run as an MCP server over stdio so AI assistants can interact with your Forma account programmatically. ```jsonc { "mcpServers": { "formanator": { "command": "/path/to/formanator", "args": ["mcp"] } } } ``` The server exposes six tools: - `auth_status` — check whether Formanator is logged in to Forma. - `login_start` — request a Forma magic link by email. - `login_complete` — complete login by pasting the emailed magic link. - `list_benefits_with_categories` — list all benefits with their categories and remaining balances. - `list_claims` — list claims, with optional filtering (currently only `in_progress`). - `create_claim` — create a new claim. If you are not already logged in, use `login_start` and `login_complete` from your MCP client. You can still log in ahead of time with `formanator login`. To build a binary without MCP support (smaller binary, fewer dependencies): ```bash cargo install formanator --no-default-features ``` ## Development ```bash cargo build # build with default features (CLI + MCP) cargo test --all-features cargo clippy --all-features --all-targets -- -D warnings cargo fmt --all ```