Appearance
Command-line interface (CLI)
dynm.link manages your links from the terminal and runs an MCP server for agents. It talks to the /v1 REST API with your API key.
Installation
bash
npm install -g @dynm.link/cliOr run it without installing: npx @dynm.link/cli <args>. @dynm.link/cli on npm
Authentication
bash
dynm.link login # opens your browser to authorize, then stores the key
dynm.link login --key dynm_... # headless: pass a key (or pipe it: echo dynm_... | dynm.link login)
dynm.link whoami # user, plan, folders, API URL
dynm.link logout # forget the stored keydynm.link login opens the dashboard with a one-time localhost callback; approve while signed in and the new key comes straight back. On a remote or headless machine, create a key on the dashboard's API keys page and pass it with --key. Either way the key is checked against the API before it is stored.
The key lives in ~/.config/dynm.link/config.json ($XDG_CONFIG_HOME/dynm.link/config.json when set), readable only by you. A config file that isn't valid fails every command, naming the file, and is never overwritten: fix it, or delete it and log in again.
Environment variables
These override the stored config:
DYNM_API_KEY— the API key.DYNM_API_URL— the API's origin (defaulthttps://api.dynm.link).DYNM_SPA_URL— the dashboardloginopens (default:dash.beside the API, sohttps://dash.dynm.link).
Links
bash
dynm.link link list [--type redirect|text|bio|file] [--domain <host>] [--limit <n>] [--json] # alias: ls
dynm.link link get <slug> [--domain <host>] [--json]
dynm.link link edit <slug> [--title …] [--description …] [--expires …] [--web <url>]
[--preview follow|custom] [--content '<json>'] [--domain <host>] [--json]
dynm.link link remove <slug> [--domain <host>] [--yes] # alias: rmlist shows every folder, newest first; --type and --domain filter it. edit --content replaces the content with the link's own type's, whole (the shapes are in Link types); --web and --preview change one field of it.
Create
One subcommand per type:
bash
dynm.link link create redirect [slug] --web <url> [--ios <url>] [--android <url>] [--rule '<json>']… [--preview follow|custom]
dynm.link link create text [slug] --body "Some text" [--markdown] # --body - reads stdin
dynm.link link create bio [slug] --name "Jason" [--headline …] [--avatar <url>] --link "Site=https://…" --link "GitHub=https://…"
dynm.link link create file [slug] --file ./brand-kit.zipEvery create also takes --title, --description, --expires, --domain and --json, and generates the slug when it's omitted. --expires is 30d, 12h, 45m, a date (YYYY-MM-DD) or never; without it a link expires in 30 days. create file uploads the file, then creates the link.
--rule takes a full routing rule, e.g. --rule '{"when":[{"op":"in","field":"country","values":["US","CA"]}],"to":"https://…/na"}'; --ios / --android add platform rules ahead of them.
A redirect's share preview follows its destination by default (a share unfurls the destination's own card); --title / --description on a redirect need --preview custom. dynm.link link edit <slug> --preview follow switches back and clears the title, description and card image.
Folders: --domain
--domain picks the folder. It's optional while your account has only its username.dynm.link subdomain, and required once you have an active custom domain, so create, get, edit and remove are never ambiguous. On list it's only a filter.
Errors
A failed command prints one line to stderr and exits 1. An API error prints as its code and message, e.g. SlugTakenError: alice.dynm.link/launch is taken.