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

@dhisana-ai/cli

v0.2.0

Published

Agent-friendly CLI for Dhisana APIs.

Readme

Dhisana CLI

Agent-friendly command line access to Dhisana lead, account, campaign, signal monitoring, and Agentic Flow workflow APIs. The CLI is intentionally dependency-light so tools such as OpenClaw, Codex, or other agent harnesses can shell out to deterministic JSON commands.

Install locally

cd dhisana-cli
npm link

Or run without linking:

node bin/dhisana.js --help

Requires Node.js 18+ for built-in fetch.

Configuration

Every command accepts flags or environment variables:

| Flag | Environment variable | Default | | ----------------------- | ----------------------------- | ------------------------------ | | --base-url | DHISANA_API_BASE_URL | https://api-agent.dhisana.ai | | --api-key | DHISANA_API_KEY | none | | --token | DHISANA_API_TOKEN | none | | --agent-instance-id | DHISANA_AGENT_INSTANCE_ID | none | | --agent-instance-name | DHISANA_AGENT_INSTANCE_NAME | none |

API key auth is preferred and is sent as X-API-Key: <key>. --token is still supported for legacy bearer-token flows and is sent as Authorization: Bearer <token>.

The API key can be supplied in raw or pasted-header formats:

dhisana lead lookup --api-key dhisana_key_id.secret --agent-instance-id <uuid> --email [email protected]
dhisana lead lookup --api-key "X-API-Key: dhisana_key_id.secret" --agent-instance-id <uuid> --email [email protected]
dhisana lead lookup --api-key "Authorization: ApiKey dhisana_key_id.secret" --agent-instance-id <uuid> --email [email protected]

Agent instance selection can use an id or an exact name:

dhisana signal review-inbox --agent-instance-id <uuid>
dhisana signal review-inbox --agent-instance-name "Service Cloud RFP"

If neither is provided, the CLI calls GET /v1/agent-instances and automatically uses the only available agent instance. If the API key can access multiple agent instances, pass --agent-instance-id or --agent-instance-name.

Environment variable aliases are also accepted for agent harnesses:

  • DHISANA_API_KEY
  • DHISANA_CLI_API_KEY
  • AGENTOPS_API_KEY

Bearer-token aliases remain:

  • DHISANA_API_TOKEN
  • DHISANA_ACCESS_TOKEN
  • AGENTOPS_API_TOKEN

Commands

Lookup leads

dhisana lead lookup --agent-instance-id <uuid> --id <lead_uuid>
dhisana lead lookup --agent-instance-id <uuid> --email [email protected]
dhisana lead lookup --agent-instance-id <uuid> --linkedin-url https://www.linkedin.com/in/example
dhisana lead lookup --agent-instance-id <uuid> --lead-list-id <list_uuid> --search "Jane"

This maps to AgentOps endpoints:

  • GET /v1/agent-instances/{agent_instance_id}/leads/{lead_id}
  • GET /v1/agent-instances/{agent_instance_id}/leads
  • GET /v1/agent-instances/{agent_instance_id}/lead-lists/{lead_list_id}/leads

Add leads to a list

Add existing leads:

dhisana lead add-to-list --agent-instance-id <uuid> --lead-list-id <list_uuid> --lead-ids <lead1>,<lead2>

Create new leads in the list:

dhisana lead add-to-list \
  --agent-instance-id <uuid> \
  --lead-list-id <list_uuid> \
  --name "Jane Buyer" \
  --email [email protected] \
  --linkedin-url https://www.linkedin.com/in/jane-buyer \
  --title "VP Sales" \
  --company "Acme"

Bulk import from a JSON file:

dhisana lead add-to-list --agent-instance-id <uuid> --lead-list-id <list_uuid> --file leads.json --ignore-duplicates

This maps to:

  • POST /v1/agent-instances/{agent_instance_id}/lead-lists/{lead_list_id}/add-leads
  • POST /v1/agent-instances/{agent_instance_id}/lead-lists/{lead_list_id}/leads/bulk
  • Optional --from-extension uses /leads/bulk_from_extension

Update leads

Update selected lead fields:

dhisana lead update \
  --agent-instance-id <uuid> \
  --id <lead_uuid> \
  --name "Jane Buyer" \
  --title "VP Sales" \
  --company "Acme"

Update from JSON, without overwriting populated fields:

dhisana lead update --agent-instance-id <uuid> --id <lead_uuid> --file lead-update.json --only-if-empty

This maps to:

  • PUT /v1/agent-instances/{agent_instance_id}/leads/{lead_id}

Manage lead tags and notes

dhisana lead add-tag --agent-instance-id <uuid> --id <lead_uuid> --tags hot,enterprise
dhisana lead remove-tag --agent-instance-id <uuid> --lead-ids <lead1>,<lead2> --tags stale

dhisana lead add-note --agent-instance-id <uuid> --id <lead_uuid> --content "Follow up next week"
dhisana lead update-note --agent-instance-id <uuid> --id <lead_uuid> --note-id <note_uuid> --content "Updated note"
dhisana lead remove-note --agent-instance-id <uuid> --id <lead_uuid> --note-id <note_uuid>

Note content can also be supplied with --file <path> or --stdin.

This maps to:

  • POST /v1/agent-instances/{agent_instance_id}/leads/bulk-tags
  • POST /v1/agent-instances/{agent_instance_id}/leads/{lead_id}/notes
  • PUT /v1/agent-instances/{agent_instance_id}/leads/{lead_id}/notes/{note_id}
  • DELETE /v1/agent-instances/{agent_instance_id}/leads/{lead_id}/notes/{note_id}

Lookup accounts

dhisana account lookup --agent-instance-id <uuid> --id <account_uuid>
dhisana account lookup --agent-instance-id <uuid> --domain snowflake.com
dhisana account lookup --agent-instance-id <uuid> --name "Snowflake"
dhisana account lookup --agent-instance-id <uuid> --ai --prompt "the cloud data platform company that IPO'd in 2020"

This maps to:

  • GET /v1/agent-instances/{agent_instance_id}/accounts/{account_id}
  • GET /v1/agent-instances/{agent_instance_id}/accounts/search
  • POST /v1/agent-instances/{agent_instance_id}/accounts/ai-lookup

Add accounts

dhisana account add \
  --agent-instance-id <uuid> \
  --name "Acme" \
  --domain acme.com \
  --website https://www.acme.com \
  --industry "Software"

Bulk import:

dhisana account add --agent-instance-id <uuid> --file accounts.json --bulk --ignore-duplicates

This maps to:

  • POST /v1/agent-instances/{agent_instance_id}/accounts
  • POST /v1/agent-instances/{agent_instance_id}/accounts/bulk

Update accounts

Update selected account fields:

dhisana account update \
  --agent-instance-id <uuid> \
  --id <account_uuid> \
  --name "Acme" \
  --domain acme.com \
  --industry "Software"

Update from JSON, without overwriting populated fields:

dhisana account update --agent-instance-id <uuid> --id <account_uuid> --file account-update.json --only-if-empty

This maps to:

  • PUT /v1/agent-instances/{agent_instance_id}/accounts/{account_id}

Manage account tags and notes

dhisana account add-tag --agent-instance-id <uuid> --id <account_uuid> --tags target,enterprise
dhisana account remove-tag --agent-instance-id <uuid> --account-ids <account1>,<account2> --tags stale

dhisana account add-note --agent-instance-id <uuid> --id <account_uuid> --content "Procurement team owns this account"
dhisana account update-note --agent-instance-id <uuid> --id <account_uuid> --note-id <note_uuid> --content "Updated note"
dhisana account remove-note --agent-instance-id <uuid> --id <account_uuid> --note-id <note_uuid>

Note content can also be supplied with --file <path> or --stdin.

This maps to:

  • POST /v1/agent-instances/{agent_instance_id}/accounts/bulk-tags
  • POST /v1/agent-instances/{agent_instance_id}/accounts/{account_id}/notes
  • PUT /v1/agent-instances/{agent_instance_id}/accounts/{account_id}/notes/{note_id}
  • DELETE /v1/agent-instances/{agent_instance_id}/accounts/{account_id}/notes/{note_id}

Add tasks

Create a task for selected leads:

dhisana task add \
  --agent-instance-id <uuid> \
  --name "Validate emails" \
  --task-type validate_email \
  --lead-ids <lead1>,<lead2>

Create a task for a filtered selection:

dhisana task add \
  --agent-instance-id <uuid> \
  --name "Research target accounts" \
  --task-type research \
  --select-all \
  --filter '{"status":"new"}' \
  --lead-list-id <list_uuid>

Look up tasks:

dhisana task lookup --agent-instance-id <uuid> --id <task_uuid>
dhisana task lookup --agent-instance-id <uuid> --limit 25

This maps to:

  • POST /v1/agent-instances/{agent_instance_id}/tasks/
  • GET /v1/agent-instances/{agent_instance_id}/tasks/
  • GET /v1/agent-instances/{agent_instance_id}/tasks/{task_id}

List campaigns

dhisana campaign list --agent-instance-id <uuid>
dhisana campaign list --agent-instance-id <uuid> --active
dhisana campaign list --agent-instance-id <uuid> --status PAUSED --limit 100

This maps to:

  • GET /v1/agent-instances/{agent_instance_id}/campaigns/

The AgentOps campaign list API is paginated and does not currently expose a server-side status filter, so --active and --status filter the returned page locally. Increase --limit when an agent needs to scan more campaigns.

Get campaign performance

Fetch one campaign by ID:

dhisana campaign performance --agent-instance-id <uuid> --campaign-id <campaign_uuid>

Fetch performance for active campaigns in the current page:

dhisana campaign performance --agent-instance-id <uuid> --active --limit 100

The response includes:

  • summary: compact campaign health for agent harnesses, including send counts, unique leads contacted, engagement KPIs, link click rates, and historical daily rows
  • campaign: raw campaign metadata
  • counter: raw campaign counter from AgentOps
  • link_tracking: raw link tracking summary, unless --skip-link-tracking is provided

Useful options:

dhisana campaign performance --agent-instance-id <uuid> --campaign-id <campaign_uuid> --include-bots
dhisana campaign performance --agent-instance-id <uuid> --active --skip-link-tracking

This maps to:

  • GET /v1/agent-instances/{agent_instance_id}/campaigns/{campaign_id}
  • GET /v1/agent-instances/{agent_instance_id}/campaigns/{campaign_id}/counter
  • GET /v1/agent-instances/{agent_instance_id}/campaigns/{campaign_id}/link-tracking/summary

Invoke an Agentic Flow workflow

Run a workflow once by ID:

dhisana workflow run --agent-instance-id <uuid> --workflow-id <workflow_uuid>

Run a workflow once by exact name, with parameters:

dhisana workflow run \
  --agent-instance-id <uuid> \
  --workflow-name "Test Workflow" \
  --parameters '{"company":"Acme"}'

Start from scratch instead of resuming saved offsets:

dhisana workflow run --agent-instance-id <uuid> --workflow-name "Test Workflow" --from-scratch

Useful options:

dhisana workflow run --agent-instance-id <uuid> --workflow-name "Test Workflow" --record-limit 10
dhisana workflow run --agent-instance-id <uuid> --workflow-name "Test Workflow" --run-as-user-id <user_uuid>
dhisana workflow run --agent-instance-id <uuid> --workflow-id <workflow_uuid> --parameters-file params.json
dhisana workflow run --agent-instance-id <uuid> --workflow-id <workflow_uuid> --offset-overrides '{"apollo-source":0}'

The response includes:

  • summary: workflow id, name, returned status, whether the start was accepted, from-scratch flag, record limit, run-as user, and whether parameters/offset overrides were sent
  • workflow: raw Agentic Flow payload returned by AgentOps

This maps to:

  • GET /v1/agent-instances/{agent_instance_id}/smart-lists/{workflow_id}
  • GET /v1/agent-instances/{agent_instance_id}/smart-lists/ when resolving by name
  • PUT /v1/agent-instances/{agent_instance_id}/smart-lists/{workflow_id} when persisting --record-limit or --run-as-user-id
  • POST /v1/agent-instances/{agent_instance_id}/smart-lists/{workflow_id}/start?clear_offset=<true|false>

List Signal Monitoring Review inbox items

dhisana signal review-inbox --agent-instance-id <uuid>
dhisana signal review-inbox --agent-instance-id <uuid> --limit 100 --sort-by priority_score
dhisana signal review-inbox --agent-instance-id <uuid> --item-type candidate --review-status OPEN --routing-status OPEN
dhisana signal review-inbox --agent-instance-id <uuid> --assigned-scope my_groups --reviewer-group-id <group_uuid>

Common filters:

dhisana signal review-inbox --agent-instance-id <uuid> --signal-type rfp_watch --object-type account
dhisana signal review-inbox --agent-instance-id <uuid> --policy-id <policy_uuid>
dhisana signal review-inbox --agent-instance-id <uuid> --source-provider opengov --rfp-status active

The response includes:

  • summary: compact Review inbox counts and item summaries for agent harnesses
  • raw items, by_review_status, by_routing_status, and by_policy from AgentOps

Get one Signal Monitoring Review inbox item

dhisana signal review-item --agent-instance-id <uuid> --item-id <item_uuid> --item-type candidate
dhisana signal review-item --agent-instance-id <uuid> --review-assignment-id <assignment_uuid>

Use --item-type signal, --item-type candidate, or --item-type opportunity_rollup when the item type is known. If omitted, the backend searches all Review inbox item types.

This maps to:

  • GET /v1/agent-instances/{agent_instance_id}/signal-review-queue

Extending

Add a command by creating a module under src/commands/ and registering it in src/cli.js.

Each command receives:

{
  (options, config, fetchImpl);
}

Use DhisanaApiClient from src/apiClient.js so auth, base URL normalization, JSON parsing, and errors stay consistent.