Skip to Content
Apps & PortalsCLILeadmetrics CLI (lm)

Leadmetrics CLI (lm)

App: apps/cli · Audience: Internal Leadmetrics / DM team · Status: [To Build]

lm is an interactive REPL for the Leadmetrics internal team — a terminal interface for managing tenants, running agents, reviewing and approving content, monitoring queues, and interacting with the platform without opening a browser. Modelled on the Claude Code / Gemini CLI experience: natural language + slash commands, streaming agent output, rich terminal UI.


Design Principles

PrincipleWhat it means
Interactive firstEvery session is a REPL, not a one-shot command runner. Context persists between commands.
Natural language + slash commandsYou can type commands (/approve 1234) or describe intent in plain English (“approve all low-risk blog posts for Acme today”)
Streaming outputAgent runs stream token-by-token to the terminal, just like watching Claude Code work
Tenant contextOne active tenant at a time. Commands apply to it automatically. Switch with /use <tenant>
API-backedAll operations go through the same Fastify API the DM Portal uses (/dm/v1, /admin/v1) — no direct DB access
Offline-awareGraceful degradation when the API is unreachable; reconnect with /reconnect

Tech Stack

LayerChoiceWhy
RuntimeNode.js 22 + TypeScriptSame runtime as the rest of the monorepo
REPL / inputreadline + custom prompt loopFull control over input history, multiline, keybindings
UI renderingInk  (React for CLIs)Tables, spinners, progress bars, streaming text — declarative
StreamingNative EventSource / fetch with streaming bodySSE from /dm/v1/activities/:id/stream
AuthAPI key stored in ~/.lm/config.json (encrypted at rest)No OAuth flow required for internal tools
HTTP clientofetchSame client used in the monorepo
Syntax highlightingchalk + cli-highlightColour-codes Markdown, JSON, code in output
Config~/.lm/config.jsonPer-user, not per-repo

Monorepo placement

apps/ cli/ src/ index.ts # Entry point — starts the REPL repl.ts # Main REPL loop context.ts # Session context (current tenant, auth, history) commands/ # One file per slash command nl/ # Natural language query handler ui/ # Ink components (tables, spinners, stream view) api/ # Typed API client (wraps /dm/v1 and /admin/v1) config.ts # ~/.lm/config.json read/write package.json tsconfig.json

Installation

# From the monorepo root pnpm --filter cli build pnpm --filter cli link # makes `lm` available globally # Or install from the private npm registry npm install -g @leadmetrics/cli # Verify lm --version

First-Time Setup

$ lm Welcome to Leadmetrics CLI v1.0.0 No config found. Running first-time setup. API URL › https://api.leadmetrics.io API Key › lm_live_•••••••••••••••••••••• Authenticating... ✅ Logged in as moble@leadmetrics.io (super_admin) Config saved to ~/.lm/config.json Type /help to see available commands, or just describe what you want to do. lm ›

The REPL

lm ›

The prompt shows your current tenant context when one is active:

lm [Acme Corp] ›

Input modes

ModeHow to activateExample
Slash commandStart with //queue, /approve 1234
Natural languageJust typeshow pending approvals for Acme
MultilineEnd line with \approve 1234 \reason: looks good
Pipe / stdinecho "..." | lmecho "/status" | lm --no-interactive

Keyboard shortcuts

KeyAction
/ Navigate command history
Ctrl+CCancel current command / interrupt streaming
Ctrl+DExit
Ctrl+LClear screen
TabAutocomplete slash commands and tenant names
Ctrl+RReverse search command history

Session Context

The CLI maintains a session context for the duration of your REPL session:

interface SessionContext { user: AuthUser; // who is logged in currentTenant: Tenant | null; // active tenant (/use sets this) history: CommandEntry[]; // command history (persisted to ~/.lm/history) streaming: boolean; // whether a stream is currently active }

When currentTenant is set, all tenant-scoped commands (queue, approve, agents, cost, etc.) default to it without requiring --tenant.


Auth

# Login / set API key lm auth login # Show current auth lm auth whoami # Logout / clear config lm auth logout

API keys are stored in ~/.lm/config.json encrypted with the machine’s unique hardware ID (same pattern as VS Code credential storage). The config file is never committed to source control.

{ "apiUrl": "https://api.leadmetrics.io", "apiKey": "<encrypted>", "defaultTenant": null, "theme": "dark" }

Non-Interactive Mode

For scripting and CI use:

# Run a single command and exit lm --run "/status" # Pipe commands echo "/queue --status pending" | lm --no-interactive # Output as JSON (for scripting) lm --run "/tenants" --output json # Quiet mode (no colour, no spinners) lm --run "/approve 1234" --quiet

Configuration

# Set default tenant (skips /use on every session) lm config set defaultTenant acme-corp # Switch API environment lm config set apiUrl https://staging.api.leadmetrics.io # Set colour theme lm config set theme dark|light|none # Show current config lm config show

© 2026 Leadmetrics — Internal use only