mio-cli

command module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 2, 2026 License: MIT Imports: 6 Imported by: 0

README

mio

The official command-line interface for Membership.io.

mio is agent-first: JSON output by default when piped, environment-variable auth, and stable exit codes so scripts and AI agents can branch deterministically.


Prerequisites

  • From source: Go 1.25+ (the module targets Go 1.25).
  • Released binary (once published): none — the binary is self-contained.

Install

Status: the CLI currently lives on the feat/initial-cli branch (PR #1). main has only the license, and no release tag has been cut yet. Until the first release ships, use the From source path below — the published-package installs (Homebrew, curl, go install …@latest) are not live yet.

From source (works today)

Requires Go 1.25+.

git clone -b feat/initial-cli https://github.com/Searchie-Inc/mio-cli
cd mio-cli
go build -o mio .
./mio version

Prefer it on your PATH? From the same clone:

go install ./...   # installs `mio` into $(go env GOPATH)/bin
After the first release (v0.1.0)

These become available once PR #1 merges to main and a version tag is cut. They do not work yet.

# Homebrew (macOS / Linux)
brew install searchie-inc/tap/mio

# curl one-liner (Linux / macOS)
curl -fsSL https://get.membership.io/mio/install.sh | sh

# Go install (pinned to the released tag)
go install github.com/Searchie-Inc/mio-cli@latest

After installing, verify:

mio version

First run

# 1. Install (see above) — from source today, or a released binary later.

# 2. Authenticate (pick one)
mio login                              # interactive — stores a key in your OS keychain
# …or, for scripts / CI / agents:
export MIO_API_KEY=mio_sk_live_xxxxx   # no login step needed

# 3. Set your default team so you don't repeat --team on every command
mio config set team <team-id>

# 4. You're ready
mio contacts list

Heads up: API-key auth requires the backend Team API Keys feature (mio-backend PR #128). Until that ships to production, mio login and key auth will not succeed against https://api.membership.io. You can point the CLI at a dev/staging backend in the meantime with --api-base <url> or MIO_API_BASE_URL (see Authentication).


Authentication

mio login (interactive)

Run mio login and choose one of two paths:

  1. Paste an existing API key — a mio_sk_live_… key, validated against the API and stored.
  2. Email + password — logs you in (JWT), then auto-mints an API key named mio-cli@<host> on your team and stores it. Your password is never saved — only the minted key is kept.

The key is stored in your OS keychain (with an encrypted-file fallback on headless/CI environments where no keychain is available). mio logout deletes it.

API key (CI / scripts / agents)

Skip mio login entirely — just set the environment variable:

export MIO_API_KEY=mio_sk_live_xxxxx
Resolution order

The key is read in this order (first match wins):

--api-key <key>   →   MIO_API_KEY env   →   key stored in the OS keychain
Pointing at a non-production backend
mio --api-base https://api.staging.membership.io contacts list
# or
export MIO_API_BASE_URL=https://api.staging.membership.io

Discovering commands

mio is fully self-documenting:

mio --help                          # top-level: all resources + global flags
mio <resource> --help               # e.g. mio contacts --help — actions for a resource
mio <resource> <action> --help      # e.g. mio contacts create --help — flags for an action
mio gen-docs --dir ./docs           # generate the full Markdown reference (one file per command)

When in doubt, append --help to any command.


Quickstart

# Set your default team (do this once)
mio config set team <team-id>

# Contacts  (note: name flags use underscores: --first_name / --last_name)
mio contacts list
mio contacts create --email alice@example.com --first_name Alice --last_name Smith
mio contacts retrieve <id>
mio contacts update <id> --last_name "Jones"
mio contacts delete <id> --yes

# Hubs
mio hubs list
mio hubs create --name "My Hub" --slug my-hub

# Products & prices  (the product id is a positional argument, not a flag)
mio products list
mio products create --name "Pro Plan" --description "Full access"
mio products prices list <product-id>
mio products prices create <product-id> --amount 4900 --currency usd --interval month

# Segments — preview who matches a condition tree (does not save)
mio segments search --conditions '{"version":1,"groups":[{"logic":"AND","conditions":[{"type":"email","operator":"contains","value":"@example.com"}]}]}'
mio segments members <segment-id>

segments search takes the full condition tree (matching the backend write shape), not a flat list. You can also read it from a file and paginate:

mio segments search --conditions @conditions.json --page-size 50 --page-after <cursor>

Global Flags

Every command inherits these flags.

Flag Short Default Description
--api-key env/keychain API key. Overrides MIO_API_KEY and the stored key.
--team config Team ID for team-scoped resources.
--hub config Hub ID for hub-scoped resources.
--output -o json (piped) / table (TTY) Output format: json, table, plain.
--jq Filter JSON output with a gojq expression.
--raw false Emit the raw JSON:API envelope instead of the flattened resource.
--yes -y false Skip confirmation prompts on destructive operations.
--profile default Named config profile.
--api-base config Override the API base URL (MIO_API_BASE_URL).

Output and --jq Examples

By default, mio flattens JSON:API responses into plain resource objects. Use --output to control format:

# Pipe-friendly JSON (also the auto-default when piped)
mio contacts list --output json

# Aligned table for humans
mio contacts list --output table

# key=value pairs (great for grep)
mio contacts retrieve <id> --output plain

# Raw JSON:API envelope (meta, links, included)
mio contacts list --raw

# Extract a field with jq
mio contacts retrieve <id> --jq '.email'

# Pluck IDs from a list
mio products list --jq '.[].id'

# Chain into shell variable
HUB_ID=$(mio hubs list --jq '.[0].id')
mio content list --hub "$HUB_ID"

Exit Codes

Scripts and agents can branch on these stable codes.

Code Constant Meaning
0 Success
1 ExitGeneric Unexpected / generic error
2 ExitUsage Bad flags, missing required argument, or rejected input (400/409/422)
3 ExitAuth Missing or invalid credentials (HTTP 401/403)
4 ExitNotFound Resource not found (HTTP 404)
5 ExitNeedsConfir Destructive op in a non-interactive shell — pass --yes
6 ExitRateLimited Rate limited (HTTP 429)
7 ExitServer Upstream server error (HTTP 5xx)

Command Reference (by resource)

Resource Available actions
login / logout Interactive auth
config set, get, list
api-keys create, list, retrieve, delete
teams create, list, retrieve, update, delete, switch; members list/add/remove
users me, list, retrieve, update
roles create, list, retrieve, update, delete; permissions list
hubs create, list, retrieve, update, delete
contacts create, list, retrieve, update, delete, restore
contact-attributes create/list/retrieve/update/delete defs; options sub-group; hub-config sub-group; values get/set
tags create, list, retrieve, update, delete, assign, assign-bulk, remove
segments create, list, retrieve, update, delete, search, members, count
content create, list, retrieve, children, update, delete, restore, reorder
pages create, list, retrieve, update, delete, home; sections create/list/update/delete/reorder
products create, list, retrieve, update, delete; prices create/list/retrieve/update/delete
checkout orders list/retrieve; subscriptions list/retrieve/cancel; payments list/retrieve/refund; webhooks list/retrieve/replay; accounts list/retrieve/onboarding-link; stripe-sync import/import-status/adopt-product
email drip-campaigns create/list/retrieve/update/delete/activate/pause; steps create/list/update/delete; templates create/list/retrieve/update/delete/preview; config set/get/delete/test; enrollments list/exit; stats get
access-rules rules create/list/retrieve/update/delete; overrides create/list/retrieve/update/delete
activity contact, top-engaged

Run mio <resource> --help or mio <resource> <action> --help for flag details on any command, or mio gen-docs --dir ./docs to generate the complete reference.


Config File

mio stores its config as TOML at ~/.config/mio/config.toml (or $XDG_CONFIG_HOME/mio/config.toml when XDG_CONFIG_HOME is set). It holds non-secret context only — current team/hub, API base, and named profiles. Your API key is never written here; it lives in the OS keychain (managed by mio login / mio logout).

Manage it with the config command (writable keys: team, hub, api-base):

mio config set team     <team-id>
mio config set hub      <hub-id>
mio config set api-base <url>
mio config get team
mio config list            # shows all values and the config file path

Multiple named profiles are supported via --profile.


Troubleshooting

Symptom Likely cause Fix
Exit code 3 (ExitAuth) No key, or the key is invalid/expired Run mio login, or export MIO_API_KEY=mio_sk_live_…. Remember key auth needs backend PR #128 deployed.
Exit code 2 (ExitUsage) Bad flag, missing argument, or rejected input Check your flags against mio <resource> <action> --help. Note name flags use underscores (--first_name).
Exit code 5 (ExitNeedsConfir) A destructive op (delete, cancel, refund) in a non-interactive shell Re-run with --yes / -y.
Exit code 6 (ExitRateLimited) Too many requests (HTTP 429) Back off and retry.
Exit code 7 (ExitServer) Upstream 5xx Transient — retry; if it persists, the backend is down.
Calls fail against production Key auth not deployed to prod yet Point at a dev/staging backend with --api-base <url> or MIO_API_BASE_URL.

Every error is returned as a JSON:API errors array (even on a TTY), with the exit code echoed in meta.exit_code, so you can branch on the body or the process exit code.


See Also

  • AGENTS.md — guide for AI coding agents (non-interactive auth, exit codes, command table)
  • llms.txt — machine-readable one-line-per-command index
  • mio --help — top-level help
  • mio <resource> --help — resource-level help
  • mio gen-docs --dir ./docs — generate the full Markdown reference

Documentation

Overview

Command mio is the Membership.io command-line interface.

main is intentionally tiny: it runs the cobra command tree and translates the returned error into a process exit code via the errs package. All real logic lives under cmd/ and internal/. Errors are rendered to stderr as a JSON:API error envelope so agents get a parseable failure with a stable exit code.

Directories

Path Synopsis
Package cmd holds the cobra command tree for the mio CLI.
Package cmd holds the cobra command tree for the mio CLI.
internal
client
Package client is the mio HTTP layer: a thin JSON:API v1.1 client plus the plain-JSON auth helpers.
Package client is the mio HTTP layer: a thin JSON:API v1.1 client plus the plain-JSON auth helpers.
config
Package config owns the mio CLI's persistent state: the TOML config file at $XDG_CONFIG_HOME/mio/config.toml (default ~/.config/mio/config.toml) and the OS keychain entry that stores the API key.
Package config owns the mio CLI's persistent state: the TOML config file at $XDG_CONFIG_HOME/mio/config.toml (default ~/.config/mio/config.toml) and the OS keychain entry that stores the API key.
errs
Package errs defines the mio CLI's typed error model and the stable process exit codes that AI agents and CI branch on.
Package errs defines the mio CLI's typed error model and the stable process exit codes that AI agents and CI branch on.
output
Package output renders command results in one of three formats — json, table, or plain — and applies an optional gojq post-filter.
Package output renders command results in one of three formats — json, table, or plain — and applies an optional gojq post-filter.
version
Package version exposes build metadata for the mio CLI.
Package version exposes build metadata for the mio CLI.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL