The Firmfact CLI
Your firm's single source of fact, from the command line. Send invoices and contracts to be read, look up what they say and ask about renewals, from a prompt or a script.
Firmfact reads the documents behind every licence, from the vendor and from inside the firm, matches invoices to contracts, explains what changed and allocates each cost to the cost centres and people that use it. The Firmfact CLI puts those facts in your terminal: send invoices, contracts and spreadsheets for it to read, look up vendors, contracts and allocations, see how your spend with Bloomberg, LSEG or FactSet moves, and ask about renewals in plain English, from a prompt or from a script.
The program is called firmfact. It runs on macOS, Windows and Linux, and it is open source under the Apache License 2.0.
Its look-up and analysis commands are the tools of the MCP connector, which Claude and other AI assistants use to reach Firmfact over MCP (Model Context Protocol, the open standard AI assistants use to reach other software). The CLI signs in the same way and sees exactly what you see in the web app, with your permissions and legal-entity scope, and nothing beyond it. It also uploads documents, which the connector does not. It is not a market data feed and returns no prices, quotes or reference data; everything it returns comes from your own workspace.
Install
macOS
brew install firmfact/tap/firmfact
Linux
curl -fsSL https://firmfact.com/install.sh | sh
Windows
In PowerShell:
irm https://firmfact.com/install.ps1 | iex
This command needs Windows 11 or Windows Server 2022 or later. On any version of Windows, Windows 10 included, use Scoop:
scoop bucket add firmfact https://github.com/firmfact/scoop-bucket
scoop install firmfact
Any platform, with Go
With Go 1.27 or newer:
go install github.com/firmfact/cli/cmd/firmfact@latest
What the install scripts check
Both scripts check that the release is signed by firmfact and matches its checksum before they install anything, and stop if they cannot. The Linux script puts firmfact in ~/.local/bin and never uses sudo; the Windows script puts firmfact.exe in your user profile and adds it to your Path, without administrator rights. You can read each one first (read the script for Linux, read the script for Windows); its settings, such as a version to pin, are at the top.
On Linux, the signature check needs OpenSSL 3. Without it, the script has the GitHub CLI, signed in, confirm that our release workflow built the archive instead, and stops if neither is there. The same line works on a Mac that has either; otherwise use Homebrew.
Homebrew and Scoop keep firmfact up to date with the rest of your software. Homebrew also sets up tab completion for bash, zsh and fish, and the manual pages (man firmfact); Scoop prints the line that loads tab completion from your PowerShell profile.
By hand
Download the archive for your platform from the releases page: .tar.gz for Linux and macOS, .zip for Windows, each for amd64 and arm64. Check with the GitHub CLI that our release workflow built it, then put firmfact on your PATH:
gh attestation verify firmfact_<version>_linux_amd64.tar.gz --repo firmfact/cli --cert-identity https://github.com/firmfact/cli/.github/workflows/release.yml@refs/tags/v<version>
Each archive also carries the tab completion scripts and the manual pages. On a Mac, Homebrew is the simpler route.
firmfact version confirms the install, and shows the version and how it was installed.
Get started
New to Firmfact? Sign up from the terminal:
firmfact signup
Signup asks for your work email address, your name and your organisation, and emails you a 6-digit code. A signup from a domain we do not know yet is reviewed by a person first, and we email you once it is approved. Once you enter the code, the CLI is signed in and your account has two workspaces:
- your own workspace, for your firm's real contracts, invoices and allocations;
- a Demo workspace with clearly marked sample data, set up while the CLI shows its progress, so you can try every command before you load anything of your own.
Already have an account? Sign in through your browser:
firmfact login
You sign in to Firmfact as you normally do and approve the CLI. The consent page lets you choose the default workspace and whether the CLI may reach your other workspaces. If your organisation signs in with SSO, or you use two-factor authentication, firmfact signup confirms your email address and you finish with firmfact login.
firmfact workspaces list shows the workspaces you can reach, and firmfact workspaces use <name or id> picks the default. Every command also takes --workspace to aim at another one. A script can sign up in two runs, with the emailed code in FIRMFACT_SIGNUP_CODE; firmfact signup --help shows how.
What you can do
firmfact vendors list # who you pay
firmfact contracts list # the contracts behind each licence
firmfact analyze cost-trends --entity-type vendor --entity-name Bloomberg --monthly
firmfact analyze utilization # how much of what you pay for is used
firmfact ask "Which contracts renew in the next 90 days?"
firmfact ask --continue "Which of those are with LSEG?"
firmfact ask "Who holds Bloomberg subscriptions, and does anyone hold more than one?"
-
Look things up. There is a list command for vendors, contracts, contract items, products, allocations, cost centres, applications, platforms and projects, and
--querynarrows any of them by name. -
See how spend moves.
analyze cost-trendsgives the spend on a vendor, contract, product or cost centre over time, with an optional forecast;analyze allocationsshows who holds what;analyze utilizationshows what is used and what is not. -
Ask.
askputs a question in plain English to your workspace, which answers from its contracts, invoices, allocations and cost centres the way the in-app assistant does.--continuefollows up in the same thread, and the thread is saved in the workspace so the exchange can be reviewed in the web app. The look-up and analysis commands only read. -
Send documents.
firmfact uploadsends invoices, contracts, order forms and spreadsheets for Firmfact to read (below). -
Always current. The workspace commands come from Firmfact itself, so new ones appear without a new CLI release, and
--helpon any command lists its flags and the values each one takes. After each command, the CLI suggests the next step worth taking.
In scripts
--json prints the result on standard output with the same three keys whichever workspace it runs against: data, meta and notes. Progress and notes go to standard error. --format csv or --format tsv prints a list's rows for a spreadsheet, --columns picks the columns, and --all fetches every page. With --all, --json prints one row per line instead, ready for jq.
firmfact contract-items list --all --format csv --columns name,userdef_id,monthly_cost > items.csv
firmfact vendors list --all --json | jq -r .name
Each exit status means one kind of failure, so a script or CI job can tell a typo from an ended session:
| Exit status | Meaning |
|---|---|
| 0 | Success |
| 1 | Any other failure, such as an error the workspace reported |
| 2 | The command line is wrong: an unknown command or flag, or a missing argument |
| 3 | Not signed in, or the session has ended; run firmfact login
|
| 4 | No such workspace, profile, tool or record |
| 5 | Unavailable for now; worth retrying later |
| 6 | This CLI is too old for the server, or the host cannot serve it; upgrade |
With --json, an error is one line of JSON on standard error, with the exit status as code and a name for it as status. The README has the full list.
Upload documents
firmfact upload LSEG-2026-09.pdf --workspace Acme
firmfact upload ~/Invoices/2026-09 --recursive --workspace Acme
firmfact upload invoice.pdf usage-report.xlsx --related --workspace Acme
firmfact upload sends invoices, contracts, order forms and spreadsheets, such as an HR list of people, to a workspace through the same intake as the upload page in the web app. Name files, folders with --recursive, or - with --name to read one file from standard input. Before it sends anything it shows what is new and what is already in the workspace, so running it again over the same folder sends nothing twice. Once Firmfact has read the documents, the CLI shows what was read, the contract an invoice matches, a preview of the variance against that contract, what needs a person and the link to the review page, where nothing is booked until someone on your team publishes it:
Uploading to Acme: 1 new
LSEG-2026-09.pdf: invoice, ready for review
Vendor Refinitiv Limited, linked to LSEG
Invoice INV-8841207, 1 Sep 2026, due 1 Oct 2026; EUR 12,450.00
Contract LSEG Workspace 2026 (C-0042), linked automatically (99%)
Variance EUR 1,550.00 (14.2%) above the contract (preview)
1 Unit price 1,150.00 against 1,030.00 (+11.7%): +1,200.00
3 Not in the contract: +350.00
To review Line 3 (Exchange fees): choose a contract item or skip it.
Review https://firmfact.com/accounts/.../documents/...
Nothing is booked until someone publishes it there.
For a spreadsheet, such as an HR list of people, the CLI shows a line for each kind of entry it found (people, cost centres, products): how many rows publishing would add, change (and in which fields) or leave as they are, and how many need a person to match.
--related sends files that belong together, such as an invoice and its usage report, as one group. --no-wait stops once the files are sent, and firmfact upload status shows them later. With --json, a script gets a result for each file, the contract match and the variance preview included. The exit status is 1 when a file was refused or could not be read, and 5 when the wait ran out, which a later run picks up. A few kinds of file can only be uploaded in the web app for now; the CLI says so when it refuses one.
To upload, you need to be an admin or editor of the workspace. After firmfact signup your default workspace is Demo, whose sample data is rebuilt from time to time, so name your own workspace with --workspace; without it, the CLI asks before it uploads to Demo.
Plans
The CLI works on every plan:
- Uploading documents works on every plan, Starter included, and so does seeing what Firmfact read from your own uploads. Uploads count towards your plan's incoming documents per month, as they do in the web app.
- The Demo workspace works on every plan, so you can try every command on sample data first. Its answers are marked as sample data.
-
Your own workspace's data needs the Professional plan or above for look-ups, analyses and
ask: the plans that include API and MCP access.
Starter, the free plan, has no trial clock: its limits are on volume, not time. Pricing is published in full on the pricing page.
Security and your data
-
You sign in through your browser.
firmfact loginsigns you in on the Firmfact sign-in page, with OAuth 2.1 and PKCE as the API authentication guide sets out. -
Signing out ends the session on the server.
firmfact logoutrevokes the sign-in and removes it from your machine. A workspace admin can also revoke it under Settings → MCP in the workspace chosen at sign-in (afterfirmfact signup, the Demo workspace). -
Your data. Answers to
askare prepared with the AI sub-processor named in the privacy notice, the same way the in-app assistant prepares them, and documents you upload are checked, read and stored as those uploaded in the web app are. Firmfact does not use your workspace data to train or improve any AI model, and does not authorise any sub-processor to do so. - Open source. The code is on GitHub under the Apache License 2.0, so you and your security team can read exactly what it does. Its README sets out how it stores your sign-in and checks its releases.
Report a security issue privately to security@firmfact.com, not in a public issue.
Staying up to date
Once a day the CLI checks in the background for a newer release, without slowing your command down. On a terminal it then prints one line with the command that upgrades it:
- Homebrew:
brew upgrade firmfact - Scoop:
scoop update firmfact - Installed with a script, with Go or by hand:
firmfact update, which replaces itself with the new release.
firmfact update --pre takes the newest release, pre-releases included, and firmfact update --version <version> installs the release you name.
When Firmfact stops supporting an old version, the CLI says so and shows how to upgrade. firmfact version shows the version you have and how it was installed; FIRMFACT_NO_UPDATE_CHECK=1 turns the daily check off.
A shorter name: ff
firmfact claim
ff vendors list
firmfact claim makes ff (fast forward) run the CLI. If your shell already has an ff, as many fzf setups do, it shows the change it would make to your shell's startup file and waits for you to confirm; your previous ff stays available as ff-previous. firmfact claim --undo removes exactly what it added.
Help
-
firmfact doctorchecks the installation, the connection, your clock and your sign-in, and says what to fix. -
firmfact <command> --helplists a command's flags;man firmfacthas a page for each command where the manual pages are installed. - Found a bug, or missing a command? Open an issue on GitHub with the output of
firmfact version. - Anything else: support@firmfact.com.
More ways in
- App, API, MCP and CLI: every way to work with Firmfact, side by side.
- MCP connector: connect Claude or another AI assistant to your workspace.
- API authentication: OAuth and API tokens for your own integrations.
- Pricing: every plan, published in full.