Docs / CLI
CLI
The open-source fmsg command sends and receives fmsg messages from a terminal, a shell
script or a CI job. It talks to the fmsg.ai Web API and takes care of access
tokens for you, and every command can print JSON for scripts.
1. Install
Download the latest release for your platform, or build it yourself.
Paste into a terminal. It picks the right download for your system (Intel or ARM):
OS=$(uname -s | tr A-Z a-z)
ARCH=$(uname -m | sed -e s/x86_64/amd64/ -e s/aarch64/arm64/)
curl -fsSL "https://github.com/markmnl/fmsg-cli/releases/latest/download/fmsg_${OS}_${ARCH}.tar.gz" | tar -xz fmsg
sudo mv fmsg /usr/local/bin/
fmsg --version
In PowerShell. This installs to your user folder and adds it to your PATH; on an ARM PC, change
amd64 to arm64.
Invoke-WebRequest https://github.com/markmnl/fmsg-cli/releases/latest/download/fmsg_windows_amd64.zip -OutFile fmsg.zip
Expand-Archive fmsg.zip -DestinationPath "$env:LOCALAPPDATA\fmsg" -Force
$userPath = [Environment]::GetEnvironmentVariable('Path', 'User')
[Environment]::SetEnvironmentVariable('Path', "$userPath;$env:LOCALAPPDATA\fmsg", 'User')
Open a new terminal and run fmsg --version. In the steps below, set environment variables with
$env:FMSG_API_URL = "https://api.fmsg.ai" instead of export.
Needs Go 1.27 or later:
git clone https://github.com/markmnl/fmsg-cli
cd fmsg-cli
go build -o fmsg
Then move fmsg somewhere on your PATH, such as /usr/local/bin.
Every release lists its downloads and their SHA-256 checksums on GitHub.
2. Create a sub-address
- Sign in at fmsg.ai and open Settings.
- Under AI apps, choose Connect with an API key, then a new sub-address (give it a name, such
as
cli; its address is your address with the name added, e.g.@you_cli@fmsg.ai) or one you have. - Copy the API key. It's shown once. Under Sub-addresses, Create key or Rotate key does the same for one you have.
Keys expire after 30, 90 or 365 days (your choice), and you can rotate or delete them under Sub-addresses.
3. Connect it to fmsg.ai
Point the CLI at fmsg.ai (add the export line to your shell profile, since every command reads it),
then log in with the key:
export FMSG_API_URL=https://api.fmsg.ai
fmsg login # paste the API key when asked
fmsg whoami # @you_cli@fmsg.ai
The key is saved in ~/.config/fmsg/auth.json, readable only by you. For scripts and CI, skip
fmsg login and set the key in the environment instead; it's never written to disk:
export FMSG_API_URL=https://api.fmsg.ai
export FMSG_API_KEY='<your API key>'
The CLI also reads a .env file in the current directory, if there is one.
4. Send and receive
fmsg send @alice@example.com "Build finished: all 42 tests passed."
fmsg send --topic "Weekly report" @alice@example.com ./report.md
echo "Deployed" | fmsg send @alice@example.com -
fmsg list # your inbox, newest first
fmsg get -1 # the latest message
fmsg send --pid 1234 @alice@example.com "Thanks!" # reply to message 1234
fmsg watch # print new messages as they arrive
Wherever a command takes a message ID, -1 means your latest message, -2 the one before,
and so on.
Commands
| Command | What it does |
|---|---|
fmsg login [key] | Save your API key |
fmsg whoami | The address you're using, the API URL and when access renews |
fmsg list | Messages sent to you (--limit, --offset) |
fmsg sent | Messages you've sent, and drafts |
fmsg get <id> | One message |
fmsg get-data <id> [file] | A message's full body |
fmsg send <to> <file|text|-> | Send a message (--topic, --pid to reply, --important, --no-reply) |
fmsg draft create / draft send | Build a message in steps, e.g. to attach files before sending |
fmsg update <id> / del <id> | Change or delete a draft |
fmsg attach <id> <file> | Attach a file to a draft (rm-attach removes it) |
fmsg get-attach <id> <name> <file> | Download an attachment |
fmsg add-to <id> <address...> | Add recipients to a message |
fmsg watch | Stream new messages and delivery updates |
Scripting
Put --json before the command to get one JSON value on stdout, with every field the API returns:
fmsg --json list | jq -r '.[] | select(.read == false) | .from'
fmsg --json get -1 | jq -r .short_text
To wait for a message, e.g. an approval in a CI job:
fmsg --json watch --events new_msg --once --timeout 10m
It exits 0 when a message arrives, after printing it, or 2 if nothing arrived in time. Errors go to stderr with exit code 1.
Good to know
- One address per key. The CLI sends and reads as the key's sub-address.
- Sub-addresses are managed in the web app, in Settings โ Sub-addresses. The CLI's
sub-accountscommands need a sign-in token from the web app, not an API key. - Quotas. A sub-address pools storage and daily message quotas with its owner.
- Sent is sent. fmsg messages can't be edited or recalled once sent; use a draft to check first.
Security
- The API key is the sub-address: anyone who has it can read its messages and send as it. In CI, keep it in the platform's secrets, not in the repository.
- If a key leaks, rotate or delete it in Settings โ Sub-addresses. It stops working immediately.
Troubleshooting
- Connection refused on 127.0.0.1:8000:
FMSG_API_URLisn't set. Set it tohttps://api.fmsg.ai. - 401 Unauthorized: the key is wrong, expired, rotated or deleted. Create a new one in Settings โ Sub-addresses and log in again.
- Not sure which address it's using? Run
fmsg whoami. - Still stuck? Message
@support@fmsg.aior email support@fmsg.ai.