CLI

Run any Gutlog op from a terminal, a script or CI.

The CLI is @meterapp/gutlog on npm. It needs Node 20 or later and no install: run it with npx. It reads the op catalog from the API at runtime, so every op the API has is a command, including ones added after your version was published.

npx @meterapp/gutlog --help

Authentication

Run npx @meterapp/gutlog login. It prints a short code and opens https://getgutlog.com/activate; sign in, check the code matches and approve, and the CLI receives an organization API key. Over SSH or from an agent, open the printed URL on any device. In CI and scripts, set GUTLOG_API_KEY instead. GUTLOG_HOST overrides the API origin (default https://getgutlog.com).

Commands

CommandWhat it does
login [--no-browser]Sign in with your browser: approve the code it shows and the CLI saves a new organization API key named for your machine.
login --key gutlog_…Save an existing API key instead (scripts, machines without a browser).
logoutForget the saved key. Revoke it in the web app to stop it working.
whoamiYour account and the key in use.
opsList every op, read live from the API.
<op> [--field value…] [--json '{…}' | @file | -]Run any op. Flags map to the op's input fields; --json passes the whole input inline, from a file or from stdin.
pricing [--json]Every plan, price and allowance. Works without signing in.
accountYour plan, today's analyses against the allowance and what the next plan adds.
upgrade --plan <plan> [--yearly]A Stripe Checkout link for a person to pay. Nothing is charged by the CLI.
billing portalThe Stripe portal for invoices, the card and cancelling.
feedback …The feedback board: list, request, report (--last attaches the last failed call), upvote, comment.
mcpA stdio MCP bridge to the hosted server, for MCP hosts without HTTP support.

Examples

# Log a meal from a draft (free, never counted)npx @meterapp/gutlog log_meal --json '{"title":"Scrambled eggs on toast","meal_type":"breakfast","client":"claude","items":[{"name":"scrambled eggs","grams":120,"confidence":0.92,"portion_confidence":0.7,"cooking_method":"pan_fried","ingredients":[{"name":"egg","confidence":0.97,"visible":true},{"name":"butter","confidence":0.55,"visible":false},{"name":"milk","confidence":0.35,"visible":false}]},{"name":"sourdough toast","portion":{"quantity":1,"unit":"slice"},"confidence":0.85,"ingredients":[{"name":"wheat flour","confidence":0.9,"visible":false},{"name":"salt","confidence":0.75,"visible":false}]}]}'
# Today's meals, totals and what needs reviewnpx @meterapp/gutlog get_day
# A read-only key for a script that exports your diarynpx @meterapp/gutlog create_api_key --json '{"name":"exporter","scopes":["meals:read"]}'
# Prices and a checkout link for a personnpx @meterapp/gutlog pricingnpx @meterapp/gutlog upgrade --plan plus --yearly

Output is JSON: pretty in a terminal, one line when piped, so it composes with jq. A failed call exits non-zero and prints the problem's code and request_id (see Errors).

In scripts and CI

.github/workflows/diary.yml
- run: npx @meterapp/gutlog get_day  env:    GUTLOG_API_KEY: ${{ secrets.GUTLOG_API_KEY }}