Skip to content

CLI Overview

src/index.ts CLI entry (commander), registers all commands
src/commands/ One file per subcommand
src/linkedin/auth/
playwright-auth.ts Headed Chromium login, captures cookies
src/linkedin/api/
client.ts Axios client with LinkedIn headers + cookie management
cookies.ts Cookie jar loading, CSRF token extraction
session.ts Session loading
endpoints/
conversations.ts List conversations, find by recipient
messages.ts Fetch messages, send messages
profiles.ts Resolve profile slug and URN
src/linkedin/realtime/
sse-client.ts SSE stream with reconnect + heartbeat
src/store/
index.ts Store class (init, git, accounts, conversations)
conversations.ts RECORD.json, JSONL messages, symlinks
git.ts Debounced git auto-commit
search.ts Fuzzy name search with confidence scoring
src/utils/
rate-limiter.ts Per-account message rate limiter
slug.ts Extract slug from LinkedIn URL

All commands accept these flags:

FlagDescription
-a, --account <slug>Account to use (default: $ALLMAN_ACCOUNT, or the only account)
-s, --store <path>Store directory (default: $ALLMAN_STORE, or ./.allman)
--jsonMachine-readable JSON output to stdout
--debugVerbose debug output to stderr

Slugs are LinkedIn publicIdentifier values (e.g. jamie-rivera from linkedin.com/in/jamie-rivera). They are always fetched from the LinkedIn profile API, never guessed from names.

Resolved slugs are cached in RECORD.json and enable O(1) lookups via filesystem symlinks.

Outbound messages are rate-limited per account. Default: 3000ms minimum between sends. State is persisted to rate-state.json across process restarts.

Before sending, allman send fetches the 10 most recent messages. If new inbound messages arrived since your last reply, the send is aborted and the new messages are shown. This prevents sending without context.

allman listen writes NDJSON events to stdout. All informational output, warnings, errors, and debug messages go to stderr. This separation is intentional — agents and pipes read stdout without log noise.