Median

CLI

Install the median command, sign in once, then set up and run your workspace from a terminal or a script.

Updated Oct 4, 20265 minute read
npm install -g mediansh
median login

Every command and flag is in the CLI reference.

Install

Package managerInstallRun without installing
npmnpm install -g medianshnpx mediansh
pnpmpnpm add -g medianshpnpm dlx mediansh
Bunbun add -g medianshbunx mediansh

The package is mediansh. It installs a prebuilt binary for your platform. The command is median. median --version prints the installed version.

Sign in

median login
Sign in at https://median.sh/cli
Your code is ZFTT-B9CP

Any device with a browser works. Waiting for you to approve.

Open the address

Use any device with a browser. The CLI opens one for you when it can, with the code filled in. Over SSH or in a container, open it on your own machine.

Sign in to Median

A new account signs up on this page.

Approve the code

Check that the code matches your terminal and click Allow. The terminal prints Signed in as <you>, working in <organization>.

FactValue
Code8 characters, shown as XXXX-XXXX
Code lifetime15 minutes. After that, login fails with login_timed_out
Don't allowLogin fails with login_refused
OrganizationThe one you have open in the dashboard when you click Allow

Pick the organization

CommandEffect
median loginBinds the session to the organization open in the dashboard
median orgs use <slug>Moves this session to another of your organizations. The dashboard stays where it is
median orgs create <name>Creates an organization, makes you its owner, and moves both this session and the dashboard into it
median whoamiPrints the account, the bound organization and your role

New accounts

A new account can approve the code before it belongs to any organization. Create one next:

median orgs create "Acme"

Until then, only whoami, orgs list, orgs create, orgs use and logout work. Everything else fails with no_organization.

First setup

From a signed in session with no organization:

median orgs create "Acme"
median keys create --name production
median agent set --name "Acme Support" --personality "Friendly, brief."
median knowledge write --title "Refund policy" --file ./docs/refunds.md
median webhooks add https://acme.com/median/events
median tools endpoint add https://acme.com/api/median/tools
median tools test orderStatus --input '{"orderNumber":"ORD-1042"}'
LineResult
1The organization, with you as owner
2Prints MEDIAN_KEY and the publishable widget key. They are shown once. Webhooks and tool endpoints need a key to exist
3The agent's name and personality
4A knowledge document from a markdown file
5A webhook endpoint for every event
6Connects your tool route and syncs its manifest
7Calls the tool the way the agent would and prints the answer. It needs no conversation

tools test runs a tool at any risk level with no approval, so a write tool performs a real write. Give it --conversation <id> to use a stored visitor from that thread instead of --as <user id>. The two cannot be combined.

Scripting

median conversations list --waiting --json | jq -r '.[].id'
BehaviorDetail
--jsonOne JSON value on stdout. login prints the sign in lines before it
Always JSONanalytics charts and explore, billing limits, billing usage, call <method>, api
Refusalscode: message on stderr, for example forbidden: Only admins and owners can edit the agent.
Usage errorsError: <message> on stderr, for a missing required flag or a value outside its choices
Unexpected errorserror: <message> on stderr
Exit code0 on success, 1 on any failure
tools testExits 1 when the tool reports a failure, even though the API call succeeded
Paginglogs list and billing invoices end a partial page with more: --cursor .... With --json, read isDone and continueCursor
CodeMeaning
not_signed_inNo session on this machine. Run median login
session_expiredThe session stopped refreshing and was cleared. Run median login
no_organizationThe session is not bound to an organization. Run median orgs create or median orgs use
invalid_tokenYou are no longer in the bound organization. Run median orgs use <slug> or median login
forbiddenYour role cannot do this. See roles
rate_limitedWait and retry. See rate limits
unreachableLogin or a token refresh could not reach the API. Check your connection. Other commands print error: <message> when offline
no_apimedian login could not reach https://api.median.sh. Check your connection. Login never falls back to another address

Paste a page instead of finding its id:

median read https://median.sh/signal/q5776nawkbmazaj4qv4p26y3v98d83qc
Pagemedian read prints
/signal/<id>The signal, every report, and commits that claim to fix it
/inbox/<id>The conversation with every message
/customers/<id>The person, their learned facts and their conversations
/knowledge/<id>The document in full

Only the path is read, so the host does not matter. Any other link fails with not_a_link.

A link also works in place of the id argument of conversations, customers, knowledge, signals, tools run and tasks adopt commands:

median signals status https://median.sh/signal/<id> planned
median conversations reply https://median.sh/inbox/<id> --body "On it."

--conversation on tools approvals, tools test and logs list takes the bare id.

Sessions and config

FactValue
Credentials file~/.median/credentials.json. On macOS and Linux only you can read it
Access token8 hours. Refreshed 60 seconds before it expires, and once after a 401
RefreshEach refresh replaces both tokens and retires the old pair
Session expiry30 days after the last refresh
Failed refreshDeletes the credentials file and prints session_expired
API addresshttps://api.median.sh. Set another at login with --api <url> or MEDIAN_API_URL. It is stored in the credentials file
median logoutRevokes the session on the server and deletes the credentials file

The CLI signs in only through median login. It never reads MEDIAN_KEY.

Where sessions show

Each session appears in Settings → API under MCP as Median CLI, with who approved it and when it was last used. Admins and owners see this section and can Disconnect a session. Its next command fails with session_expired.

CI and other machines

Run median login on each machine. A copied credentials file stops working on one machine as soon as the other refreshes, because each refresh retires the old tokens. A credentials file stored as a CI secret fails the same way, after the first run that refreshes it.

WhereUse
A laptop or a long lived servermedian login once. The session lasts while it is used at least every 30 days
CI or a short lived containerThe REST API with MEDIAN_KEY. See authentication

What stays in the dashboard

These have no CLI command:

  • Creating your account. median login sends you to sign up in the browser.
  • Connecting Slack, Discord, Linear, Notion and GitHub. Each connection is an install in the browser. After that, median integrations configures it.
  • Choosing Notion pages, adding a docs site and uploading files to the knowledge base.
  • A public link on a single document. A repository's link is median integrations repos published.
  • The organization's picture and the agent's picture.
  • Editing a customer.
  • Buying a plan, credits or add-ons. median billing reads them.
  • The help site. See Site.
  • Resending an invitation.
  • Linking your Slack or Discord account. See Work from Slack and Discord.
  • Disconnecting a CLI or MCP session. See Where sessions show.
  • Leaving or deleting the organization.

Member role changes are not on this list. Use median members role <userId> <owner|admin|member>.

Still need help?

    Esc