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

@flowhunt/cli

v1.0.7

Published

FlowHunt CLI — connect your local computer to FlowHunt AI Projects and run tasks through Claude Code, Cursor, or Codex.

Downloads

1,083

Readme

@flowhunt/cli

The FlowHunt CLI connects a local machine to FlowHunt AI Projects. When a task in a FlowHunt project is routed to this machine's runner, the CLI hands the task off to a local coding agent (Claude Code or Codex CLI; Cursor in a follow-up) and reports progress back as issue comments.

Install

npm install -g @flowhunt/cli

Requires Node ≥ 22 (the CLI uses the built-in fetch and node:fs features).

Quick start

# 1. Authenticate. Opens your browser for OAuth (PKCE).
flowhunt login

# 2. Start the daemon. On first run it auto-registers this machine as a
#    runner (using the current directory and your hostname as defaults)
#    and then begins polling every 5s for tasks routed here.
cd ~/code/my-repo
flowhunt runner start --workspace <your-workspace-id>

Subsequent runs only need flowhunt runner start — the runner identity is already persisted to ~/.flowhunt/config.json. The standalone flowhunt runner register command still works if you want to provision without starting the daemon.

Pick the runner from the "Runner" dropdown when creating an issue in the FlowHunt web UI. The daemon will claim the task within 5 seconds, drive the local agent, and stream output back as comments on the issue.

Threat model & sandbox

The runner executes server-supplied task prompts on your machine, so trust between FlowHunt's backend and your laptop matters. The actual boundaries the CLI enforces:

  1. OS-level sandbox on the spawned agent. Each task gets a fresh .claude/settings.json in --dir enabling Claude Code's native sandbox (Seatbelt on macOS, bubblewrap on Linux/WSL2). The sandbox:
    • Writes are confined to --dir and its subdirectories.
    • Reads are locked to --dir plus system paths outside $HOME (/usr, /etc, /var, /opt — needed for compilers, package managers, and shared libraries). Everything else under $HOME is denied: ~/.ssh, ~/.aws, browser cookie databases, colleague projects in ~/code, the user's other repos, etc. Dev tools that normally read ~/.config/<tool> or ~/.gitconfig will need per-project config (<repo>/.git/config, <repo>/.npmrc, etc.) or env vars.
    • failIfUnavailable: true is set, so a missing bubblewrap install fails the task loudly instead of silently downgrading to unsandboxed mode.
  2. Bash deny rules for remote-shell and file-transfer primitives (nc, ssh, scp, rsync) whose only purpose is moving data off the box. curl and wget are intentionally permitted — they're load-bearing for legitimate dev work, and the sandbox's denyRead above protects the credential files an exfil attempt would actually need to access.
  3. Path-traversal check on submit_issue_artefact. The local stdio MCP server resolves every artefact path via realpath and refuses anything that lands outside --dir. This stops a prompt-injected agent from uploading ~/.ssh/id_rsa as a "screenshot."
  4. Linux preflight on runner start. Verifies bubblewrap and socat are on PATH before starting the daemon; if missing, prints apt-get install bubblewrap socat (or the dnf equivalent) and exits non-zero.
  5. Codex CLI is spawned as codex exec --json --ephemeral --skip-git-repo-check --cd <dir> --sandbox workspace-write with CODEX_HOME pointed at a per-daemon runtime directory (~/.flowhunt/runtime/codex-<pid>/, mode 0700) that carries a config.toml pinning sandbox_mode = "workspace-write" and approval_policy = "never", plus the FlowHunt MCP server block with the runner-scoped bearer (mode 0600). The user's ~/.codex/auth.json is symlinked into the runtime dir so Codex's saved CLI auth still works without copying credentials, and --ephemeral keeps session rollouts off disk. The bearer never lands inside the runner's --dir.

--dir alone is not the trust boundary — Claude Code's Bash tool has no cwd jail at the model layer. The OS sandbox + deny rules are what actually contain the agent. If you change --dir to a non-git directory, the sandbox still applies.

Ubuntu 24.04+ AppArmor

bubblewrap on recent Ubuntu needs an AppArmor profile granting it user namespaces. Without this, claude exits non-zero on every task. Run once:

sudo tee /etc/apparmor.d/bwrap > /dev/null <<'EOF'
abi <abi/4.0>,
include <tunables/global>

profile bwrap /usr/bin/bwrap flags=(unconfined) {
  userns,
  include if exists <local/bwrap>
}
EOF
sudo systemctl reload apparmor

See the Claude Code sandboxing docs for the full setup.

Commands

flowhunt login

Opens the system browser to FlowHunt's OAuth consent screen. After approval the browser redirects to a http://localhost:<port>/callback URL the CLI listens on, captures the authorization code, exchanges it for tokens, and persists them to ~/.flowhunt/config.json (mode 0600).

flowhunt logout

Best-effort revoke of the current token, then wipes the local config.

flowhunt runner register

Most users can skip this — flowhunt runner start --workspace <id> auto-registers on first run. Use this command when you need to provision a runner ahead of time (e.g. in a CI image build).

| Flag | Required | Description | |---|---|---| | --workspace <id> | yes | Workspace ID to register under. Find it in the FlowHunt URL. | | --name <name> | no | Friendly label (e.g. "laptop", "CI box"). Defaults to the machine hostname. | | --dir <path> | no | Path tasks should execute in. Defaults to the current directory. | | --kind <kind> | no | Override the auto-detected agent: claude_code, cursor, codex, other. |

Internally this calls POST /v2/runners/register. FlowHunt creates the runner row, issues a fresh runner-scoped OAuth token pair tagged with the new runner_id, revokes the original user-scoped token, and returns the new pair. The CLI overwrites ~/.flowhunt/config.json with the runner-scoped tokens.

flowhunt runner list --workspace <id>

Pretty-prints every runner in the workspace.

flowhunt runner remove <runner_id> --workspace <id>

Revokes the runner. The matching oauth2_token row is marked revoked server-side; if this machine was acting as the removed runner, the local config is cleared too.

flowhunt runner start

The main daemon loop. If this machine isn't registered yet and you pass --workspace <id>, it auto-registers before entering the polling loop. Two independent timers run after that:

  1. Claim/poll (every 5s): POST /v2/runners/{id}/claim. If a task comes back, run it through the adapter and post the result.
  2. Heartbeat (every 30s): POST /v2/runners/{id}/heartbeat with status online (or busy while a task is in flight).

| Flag | Required | Description | |---|---|---| | --dir <path> | no | Path tasks should execute in. Defaults to the current directory. | | --workspace <id> | no | Workspace ID — required only on first run, to auto-register. | | --name <name> | no | Friendly name used at auto-register time. Defaults to the machine hostname. | | --kind <kind> | no | Override the auto-detected agent kind at auto-register time. | | --poll-ms <ms> | no | Poll interval in ms (default: 5000). | | --heartbeat-ms <ms> | no | Heartbeat interval in ms (default: 30000). |

SIGINT / SIGTERM finish the current task gracefully then exit; a second signal hard-kills.

On start the daemon writes its PID to ~/.flowhunt/runner.pid and removes the file on clean exit. If the file already exists when you run runner start, the command refuses to start a second daemon.

flowhunt runner stop

Reads ~/.flowhunt/runner.pid, sends SIGTERM, waits up to 10s for a graceful shutdown, then escalates to SIGKILL. Cleans up the pid file. Safe to run when no daemon is up — it just reports nothing to stop.

flowhunt runner status

Prints the API URL, runner ID, runner kind, and whether the local daemon process is alive (by pid-file lookup). A stale pid file (PID gone) is auto-cleaned.

On-disk config

Lives at ~/.flowhunt/config.json with mode 0600:

{
  "apiUrl": "https://api.flowhunt.io",
  "runnerId": "uuid",
  "runnerKind": "claude_code",
  "accessToken": "<jwt>",
  "refreshToken": "<uuid>",
  "expiresAt": 1737000000000
}

The CLI never writes a long-lived API key here — accessToken is a short-lived JWT and refreshToken is an opaque server-issued string, both rotatable via revoke from FlowHunt's runners page.

Self-hosted FlowHunt

Set FLOWHUNT_API_URL or pass --api-url to point at your instance:

flowhunt --api-url https://flowhunt.example.com login

The CLI requires https:// for non-loopback hosts so a typo or phishing-shaped --api-url can't silently exfiltrate your tokens. http://localhost and http://127.0.0.1 are accepted without further flags for local development. For self-hosted FlowHunt behind a private VPN where you can't terminate TLS, pass --allow-insecure:

flowhunt --api-url http://flowhunt.internal --allow-insecure login

Use that flag only when the network path between you and the self-hosted instance is fully trusted.

Development

cd cli
yarn install
yarn build
node dist/index.js --help

yarn dev runs tsc --watch.