npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@series-a/cli

v1.9.0

Published

AdvisorPro command-line interface — drive leads, campaigns, sequences and agents from your terminal.

Readme

@series-a/cli

A command-line interface to the AdvisorPro platform — drive leads, campaigns, sequences and agents from your terminal. Built on top of the /agent-api M2M router, so anything the CLI does is auditable and workspace-scoped.


Install

# Run without installing — always fetches latest
npx @series-a/cli@latest --help

# Pin a version (recommended for CI)
npx @series-a/[email protected] --help

# Or install globally
npm i -g @series-a/cli
advisoros --help

Requires Node.js ≥ 20.

Releases are tagged cli-vX.Y.Z in the repo and published to npm with provenance. See CHANGELOG.md.

1. Get an API key

  1. Sign in to AdvisorPro.
  2. Open Settings → API Keys.
  3. Click New key → choose Workspace scope (recommended).
  4. Copy the key — you won't see it again.

The CLI quickstart card on that page shows a copy-paste npx command pre-filled with your workspace ID.

Admin keys (cross-workspace) also work but are intentionally restricted. Default to workspace keys.

2. Log in

npx @series-a/cli@latest login
# Prompts for API key + workspace ID (the 6-char slug, e.g. dmw9wj)

Admin login

Admin keys (advos_admin_…) are detected automatically — no workspace prompt:

advisoros login --admin
# ✓ Logged in as admin profile "default" — N workspaces reachable

advisoros workspaces list                       # admin-only, no workspace needed
advisoros campaigns list --workspace dmw9wj     # pass workspace per command
advisoros whoami                                # shows scope: admin (cross-workspace)

Multiple workspaces?

advisoros login --profile acme        # save as "acme"
advisoros leads list --profile acme   # use the named profile

Config is stored at ~/.advisoros/config.json with mode 0600. You can also use env vars: ADVISOROS_API_KEY, ADVISOROS_WORKSPACE_ID, ADVISOROS_PROFILE, ADVISOROS_BASE_URL.

advisoros whoami
advisoros profiles
advisoros logout --profile acme

3. Command reference

Global flags (work on every subcommand):

| Flag | Description | |---|---| | --json | Emit raw JSON instead of formatted tables. | | -w, --workspace <id> | Override the workspace from your profile. | | -p, --profile <name> | Pick a saved profile. | | --api-key <key> | Override the saved API key. |

User-made knowledge categories (CLI 1.9.0)

These groups are separate from the automatic topic tag set by knowledge add --category.

| Command | Purpose | |---|---| | knowledge categories list [--limit 50] [--offset 0] | List workspace categories. | | knowledge categories create --name "Accounting" [--description "CPA and accounting insights"] | Create a category. | | knowledge categories show <categoryId> [--limit 50] [--offset 0] | Read the category and its knowledge items. | | knowledge categories update <categoryId> [--name ...] [--description ...] | Rename or describe a category. | | knowledge categories add-items <categoryId> <itemId...> | Bulk add up to 200 existing workspace items; repeat safely. | | knowledge categories remove-items <categoryId> <itemId...> | Remove memberships, keeping the knowledge items. | | knowledge categories delete <categoryId> | Preview deletion; --confirm --yes executes and keeps all knowledge items. | | knowledge categories settings show | Read the workspace's manual-choice setting. | | knowledge categories settings set auto\|manual | Automatic by default; manual requires an explicit category. | | content generate --angle "..." --format linkedin_post --knowledge-category <categoryId-or-auto> | Generate a draft using that category or automatic best fit. |

One item may belong to several categories. A selected category uses only its knowledge; reference IDs outside it are rejected. Empty selected categories fail before a paid job starts. Automatic selection with no match, and workspaces with no categories, retain existing grounding. --knowledge-category defaults to auto; manual mode rejects that default until you supply an ID. Category management uses the existing knowledge:* API scope, stays workspace-scoped and does not spend AI credits. Generation uses content:generate and normal generation credits. Nothing is published automatically.

Example (use full IDs from JSON output):

advisoros knowledge categories list --workspace <workspace> --as-agent my-agent --json
advisoros knowledge categories create --name "Accounting" --description "CPA and accounting insights" --json
advisoros knowledge categories add-items <categoryId> <itemId1> <itemId2> --json
advisoros content generate --angle "Accounting trends" --format linkedin_post --knowledge-category <categoryId> --wait --json

Leads

advisoros leads list [--status new] [--persona founder] [--search acme] [--limit 50]
advisoros leads get <id>
advisoros leads set-status <id> <new|engaged|won|lost>
advisoros leads import --file leads.csv [--persona founder]
advisoros leads import-from <source> [--query ...] [--post <url>] [--file <path>] [--audience <name>] [--campaign <id>] [--limit 50] [--no-enrich]
advisoros leads import-status <jobId>
advisoros leads update <id> [--name ...] [--title ...] [--company ...] [--email ...] [--linkedin ...] [--persona ...] [--score ...] [--status ...] [--notes ...]
advisoros leads delete <id>
advisoros leads verify <id>

leads import accepts CSV (header row), JSON array, or JSONL. Upserts on (workspace_id, linkedin_url). Bulk requests are auto-chunked at 200/call (server cap: 500/call).

leads import-from runs any of the import sources in Get Leads → Import Leads:

| source | required params | what it does | |---|---|---| | linkedin_search | --query | keyword / title / company people search via the AdvisorOS engine | | company_search | --query | LinkedIn company search | | post_reactors | --post <url> | everyone who reacted to a LinkedIn post | | paste_profiles | --file <path> | name + LinkedIn URL lines; rest is enriched | | csv | --file <path> | same CSV parser the UI uses | | heyreach | --file <path> --campaign <id> | HeyReach campaign CSV, statuses preserved | | sales_nav_url | --url <sales-nav-search-url> | queues a background Sales Navigator import, drip-fed inside the LinkedIn read limits | | sales_nav_keywords | --query | same background queue, from Sales Navigator keywords |

All sources accept --audience to attach leads to a segment (created if missing). LinkedIn-backed sources run at bulk read priority so live campaigns are not starved. Long-running imports return a job_id; poll with advisoros leads import-status <jobId>.

Sales Navigator sources do not run inline — they create a scheduled import that the cap-aware scheduler drip-feeds over hours or days:

advisoros leads import-from sales_nav_url --url "https://www.linkedin.com/sales/search/people?..." \
  --limit 500 --audience "Q3 ICP" --priority high
advisoros leads import-schedules
advisoros leads import-schedule pause|resume|cancel <id>

Cancelling keeps the leads already imported.

Campaigns

advisoros campaigns list [--status active]
advisoros campaigns show <id>
advisoros campaigns create --name "Founder Pitch Club" \
                           --sequence <sequenceId> \
                           --senders acc_a,acc_b \
                           --daily-limit 25
advisoros campaigns add-leads <campaignId> --lead-ids id1,id2,id3
advisoros campaigns add-leads <campaignId> --file lead-ids.txt
advisoros campaigns launch <id>
advisoros campaigns pause  <id>
advisoros campaigns resume <id>
advisoros campaigns rename <id> "New name"   # rename without touching other settings

launch flips status to active — the enforce_campaign_char_limits trigger validates every step's copy against LinkedIn limits before allowing the transition.

Sequences / Inbox / Content / Agents / Meetings / Newsletter / Integrations

advisoros sequences list
advisoros sequences show <id>

advisoros inbox threads [--campaign <id>] [--lead <id>] [--needs-attention] [--limit 50]

advisoros content list [--status published] [--type post] [--search ...]
advisoros content show <id>
advisoros content publish <id>

advisoros agents list
advisoros agents run <name> --input '{"foo":"bar"}'
advisoros agents trigger <name> --input '{"foo":"bar"}'
advisoros agents history [--agent <name>] [--days 30] [--limit 50]
advisoros agents job <jobId>

advisoros meetings list [--limit 50]
advisoros meetings transcripts [--provider fireflies|roam] [--since 2026-01-01] [--limit 50]
advisoros meetings transcript <transcriptId> [--original | --mode anonymised|original]

advisoros newsletter list
advisoros newsletter create --subject "Weekly roundup" --body "<html>..." [--preview-text "..."]
advisoros newsletter edit <id> [--subject ...] [--body ...] [--preview-text ...] [--status draft|scheduled]
advisoros newsletter delete <id>

advisoros integrations status
advisoros integrations check <platform>

Heads-up: inbox send/reply are intentionally not in v1. Outbound goes through campaigns launch (sender resolution + char limits + per-sender daily budget). For one-off DMs, use the web inbox.

meetings transcript returns anonymised text by default, once anonymisation is ready; otherwise metadata is returned with an explicit reason. Add --original to get the original text and speaker identities — your key needs this permission (all unrestricted keys already have it) and every original read is audited.

integrations status is read-only and never returns credentials. integrations check <platform> runs a live health probe for the requested platform (e.g. linkedin_tool).

Obsidian vault mirror (kb) — one-way

advisoros kb link ./client-vault --workspace dmw9wj
advisoros kb status ./client-vault           # dry-run preview
advisoros kb pull ./client-vault             # mirror notes + graph entities
advisoros kb pull ./client-vault --preserve-local

One-way push, AdvisorPro → Obsidian. Markdown notes with frontmatter, [[wikilinks]] and an ## Entities block, plus Entities/<Type>/*.md for graph nodes. Local edits are overwritten unless --preserve-local is used (remote copy lands as <slug>.remote.md). Nothing is pushed back.

Examples

Spin up a campaign from a fresh CSV:

advisoros leads import --file ./prospects.csv --persona founder
advisoros leads list --persona founder --limit 200 --json \
  | jq -r '.leads[].id' > lead-ids.txt

advisoros campaigns create --name "Q3 Founder Outreach" \
  --sequence 1a2b3c4d-... --senders acc_milan --daily-limit 25
# → ✓ Created campaign 8297f04d-...

advisoros campaigns add-leads 8297f04d-... --file lead-ids.txt
advisoros campaigns launch    8297f04d-...

Tail a long-running agent job:

JOB=$(advisoros agents run lead-intelligence --input '{}' --json | jq -r '.run.job_id')
watch -n 5 "advisoros agents job $JOB --json | jq '{status,progress}'"

Safety rails

Anything that stops sending, un-enrols leads or deletes data now asks first.

# Launch is a dry run until you confirm — preflight runs server-side.
advisoros campaigns preflight 9884b9ec
advisoros campaigns launch 9884b9ec            # shows blockers, changes nothing
advisoros campaigns launch 9884b9ec --confirm  # actually launches

# Destructive commands prompt; scripts must pass --yes.
advisoros campaigns delete 9884b9ec --dry-run
advisoros campaigns delete 9884b9ec --yes
advisoros sequences delete-step 6b60d6ad --yes

A campaign with no leads, no sequence, no steps or no sender account is refused, not silently activated. --force overrides once you know why.

New commands: campaigns preflight|archive|clone|delete|remove-leads, sequences delete|update-step|delete-step.

Reading more than 200 rows

List commands accept --limit up to 1000 and every list response carries pagination (total, limit, offset, next_cursor, has_more). If you ask for more than the maximum, the response says it was clamped instead of quietly truncating.

Exit codes

| Code | Meaning | |---|---| | 0 | Success | | 1 | Generic failure (error in JSON response or thrown). Stderr contains the message. |

Programmatic use

import { call } from "@series-a/cli/src/api.mjs";

const { campaigns } = await call("campaigns", "list", { status: "active" }, {
  apiKey: process.env.ADVISOROS_API_KEY,
  workspaceId: "dmw9wj",
});

Troubleshooting

  • 401 Unauthorized — key wrong / revoked / wrong base URL. Re-run advisoros login.
  • 403 not authorized for the requested workspace_id — workspace-scoped key + --workspace to a different workspace. Use the matching key.
  • CHAR_LIMIT_EXCEEDED on launch — a sequence step exceeds LinkedIn limits (200 invitations / 8000 DMs / 1250 comments). Fix in web app.
  • Network error — check ADVISOROS_BASE_URL if you're pointing at a non-default deployment.

Releasing (maintainers)

cd tools/cli
npx changeset                                            # describe the change
npm run version-packages                                 # bump package.json + CHANGELOG.md
git commit -am "chore(cli): release v$(node -p "require('./package.json').version")"
git tag "cli-v$(node -p "require('./package.json').version")"
git push --follow-tags
# → .github/workflows/cli-release.yml publishes to npm with provenance

NPM_TOKEN must be set in the repo's GitHub Actions secrets (automation token with publish access to the @series-a org).

Roadmap (v1.1)

  • inbox send / inbox reply with explicit --confirm + per-sender budget enforcement.
  • agents tail <jobId> (SSE).
  • admin workspaces … (admin keys only).
  • Single-binary builds via pkg.

Full API reference

See docs/agent-api.md for the underlying /agent-api envelope.

Admin keys

Admin keys (advos_admin_…) are authorised by the key itself — they do not need an agent_workspace_bindings row. agent_name is an audit label only.

advisoros login --admin --profile ops     # no workspace prompt; prints reachable workspace count
advisoros whoami --profile ops            # scope: admin (cross-workspace) + reachable count
advisoros workspaces list --profile ops   # every reachable workspace (paginated, up to 1000)
advisoros analytics overview --workspace dmw9wj --profile ops

Caller identity is overridable: --as-agent <name> on any command, ADVISOROS_AGENT_NAME in the environment, or the agentName stored on the profile at login (default advisoros-cli).

Workspace-scoped keys are unchanged: they can only reach their own workspace (403 otherwise) and cannot use the workspaces resource. An agent without bindings now gets a typed 403 explaining to use an admin key, instead of a 500.