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

openboard-cli

v2.4.2

Published

AI-powered analytics dashboard generator TUI — https://openboard-site.vercel.app

Readme

[>_] OpenBoardCLI

Website: openboard-site.vercel.app · Agent contract: Agent.md / llms.txt

OpenBoardCLI is a terminal UI for generating and deploying one authenticated React analytics app from CSV, Excel (.xlsx), or JSON data. The first dashboard creates the shared app. Every later dashboard is added as another tab in that same UI, and a master Overview tab aggregates spending and insights across all of them.

The user-facing app is generated by an LLM, but OpenBoardCLI itself stays as a CLI/TUI utility that owns setup, data parsing, prompt history, build, GitHub push, and Vercel deployment.

Modes — pick your privacy level first

The very first choice in setup is the app mode, so you know from the beginning exactly what you get at the end and what leaves your machine:

A mode is a point on two independent axes — where the LLM runs, and where the dashboard ends up — so there are four:

| # | Mode | You get | What leaves your machine | |---|------|---------|--------------------------| | 1 | Local only | Local LLM (Ollama or LM Studio) + local preview | Nothing — no cloud LLM, no GitHub, no Vercel | | 2 | Hybrid (local LLM) | Local LLM + GitHub + live Vercel web app | The built dashboard and its data only — no prompts to an LLM vendor | | 3 | Hybrid (cloud LLM) | Cloud LLM (Codex/Claude/GPT/…) + local preview | Prompts + data summaries to your LLM provider only | | 4 | All remote | Cloud LLM + GitHub + live Vercel web app | LLM traffic, code to GitHub, data + app to Vercel |

Pick Hybrid (local LLM) when you want a live web app you can open on your phone, but your data must never reach an LLM vendor.

The mode shapes everything downstream: the setup wizard skips GitHub/Vercel in the preview-only modes, the chat hides /deploy and /push, the agent pipeline ends at the local build, and openboard agent setup refuses tokens that the mode never uses. Each mode also fixes the provider list — the two local-LLM modes offer Ollama and LM Studio, the two cloud modes offer the cloud providers. Change it any time in Settings > App mode or with openboard agent setup mode --mode <local|hybrid-local|hybrid|remote>.

Architecture At A Glance

OpenBoardCLI architecture: the CLI/TUI and its services turn data into a shared React app that ships to GitHub and Vercel

OpenBoardCLI stays a CLI/TUI utility; the user-facing dashboard app is generated by the LLM and shipped to GitHub + Vercel.

Diagram source: docs/architecture.mmd (rendered to SVG so it displays on both GitHub and the npm package page).

Current Flow

OpenBoardCLI flow: open the TUI, configure providers, add a dashboard to the UI, iterate in the internal chat, then deploy

Existing dashboards are opened from the Dashboards menu. Opening an existing dashboard does not regenerate from scratch. It opens the internal chat for follow-up changes.

Install And Run

npm install -g openboard-cli
openboard

The npm package is openboard-cli; the installed command is openboard.

From source:

npm install
npm run build
node dist/index.js start

The command with no arguments also launches the TUI:

openboard

Onboarding

On a fresh install (no LLM configured), openboard opens onboarding automatically; afterwards it starts at the main menu, whose options are Onboarding, Integrations, Dashboards, Settings, Exit in that order. OpenBoardCLI needs these configured once:

  • App mode: Local only / Hybrid (local LLM) / Hybrid (cloud LLM) / All remote (asked first — see Modes).
  • LLM provider: OpenAI API, OpenAI Codex via ChatGPT subscription, Anthropic, Google Gemini, Moonshot, xAI, Mistral AI, OpenRouter, local Ollama, or local LM Studio.
  • Ollama and LM Studio show your actual installed/loaded models (live discovery against the local server), falling back to a static catalog spanning Qwen, Gemma, Mistral/Devstral, OpenAI GPT-OSS, DeepSeek R1, Llama, and Phi only if the local server can't be reached. LM Studio can also automatically select the first model its local server exposes.
  • Model and execution effort (low / medium / high / max) — picked from lists in the wizard; effort maps to each provider's reasoning knob (OpenAI reasoning_effort, Anthropic extended thinking, Codex model_reasoning_effort).
  • GitHub token or authenticated GitHub CLI (the two deploying modes only).
  • Vercel token or Vercel Git integration (the two deploying modes only).
  • Dashboard login credentials.

Settings can be re-entered later from the Settings menu, and the model/effort can be switched any time from the internal chat with /model. Data sources — Gmail invoice fetching today — live under Integrations, not Settings.

Headless setup (for agents)

You can configure everything without the TUI — useful when an agent drives OpenBoardCLI. Each credential is validated before it is saved (encrypted at rest):

openboard agent setup all \
  --provider openai --api-key "sk-..." --effort medium \
  --github-token "ghp_..." --vercel-token "..." \
  --username admin --password "min-8-chars" --json

openboard agent setup status --json

OpenAI Codex can be signed in headlessly too — --codex-access-token, --api-key, or device-auth (codex prints a URL+code on stderr for the agent to relay). Secrets may also come from OPENBOARD_* env vars (preferred over flags). See Agent.md for the full reference.

Dashboards

OpenBoardCLI uses one master generated React app.

  • Add a dashboard: Dashboards -> Add new dashboard to UI. Data sources: .csv, .xlsx, or .json — the path can be typed or pasted with or without surrounding quotes (e.g. Windows Explorer's "Copy as path").
  • Category presets (--type for agents): health, finance, grocery, travel, food, shopping, subscriptions, utilities, invoices, custom — each ships a tuned default prompt (rides/bookings, food delivery, e-commerce orders, recurring SaaS/OTT bills, telecom/society bills, mixed invoice ledgers, ...).
  • UI complexity (--quality for agents): High (default — full KPI row, Top Insights, trend chart, sortable/searchable records table) or Low (lightweight — 1-3 KPI cards and one chart; shorter prompt and smaller completion budget). Low is pre-selected when your configured provider is Ollama or LM Studio, since small/local models often can't finish a full high-quality generation without exhausting their reasoning budget — but either quality can be chosen with any provider.
  • Modify a dashboard: Dashboards -> Modify: <dashboard title>.
  • Remove a dashboard: Dashboards -> Remove: <dashboard title>.

Dashboard tabs are product-owned and deterministic: OpenBoardCLI regenerates src/generated/dashboardManifest.tsx (tab list, imports, and routing) from its registry before every build, preview, and deploy — one model response can never drop or overwrite another dashboard's tab. Removing a dashboard deterministically drops its tab from the manifest, deletes its orphaned components and protected data, and rebuilds; removing the last dashboard restores the blank Welcome shell (no LLM call).

Master Overview tab

As soon as the app has at least one dashboard, a master Overview tab is generated as the first/landing tab. It aggregates every dashboard's data (via the protected ?dashboard=__all__ API): cross-app spend KPIs (total, past 7 days, this month), a Weekly/Monthly/Quarterly cross-app spend trend, a per-app breakdown, and 2 spending + 2 saving insights. It is refreshed automatically whenever dashboards are added, updated, or removed (skipped when nothing changed), and clicking the OpenBoardCLI logo in the header always returns to it.

Default UI contract

Every High quality generated tab includes by default (until you ask the chat to change it):

  • A row of equal-sized KPI cards.
  • A "Top Insights" block of exactly 4 tiles: top 2 spending + top 2 saving insights.
  • A time-trend chart with a Weekly/Monthly/Quarterly toggle (when dates exist).
  • A "Recent Records" table at the bottom — newest first, 10 most recent visible by default, with pagination, sorting, and search.

Low quality tabs only require a header, 1-3 KPI cards, and exactly one chart — everything else above is optional, traded for a shorter prompt and smaller completion budget so small/local models are more likely to finish valid code instead of exhausting their token budget on reasoning.

Each dashboard tab is wrapped in its own error boundary, so a runtime crash in one tab shows a "failed to load" card instead of blanking the whole app; switching tabs (or regenerating via /update) gives it a fresh render attempt.

The generated app header shows the OpenBoardCLI website/GitHub/npm icon links on the left and the clickable OpenBoardCLI brand in the center.

Invoice Fetchers (per-biller)

Turn invoice emails into per-biller spending dashboards, automatically. OpenBoardCLI ships two ready-made fetchers — Amazon and Uber — and drives any fetch_<biller>.py you write yourself. Everything else is yours to add: describe one sample email and Biller Studio writes the fetcher for it. Billers can be switched off temporarily, or removed for good with r, which deletes the fetcher and leaves the invoices it already collected on disk:

  • Start with one keypress: Integrations → Gmail → Install bundled fetchers. They land in the canonical folder, already configured. A fetcher you have edited is never overwritten by a later install.

  • One canonical home, pre-filled for you: ~/.openboard/billers/scripts/invoice_fetchers/ for the scripts, with billers/data/invoices/ and billers/secrets/ alongside. The scripts find their own data two folders up, so this layout works with them unmodified.

  • Point OpenBoardCLI at the folder once: Integrations → Gmail. It scans for fetch_*.py files, reads each script's own KEY/DISPLAY_NAME constants, and lists every biller it finds. Nothing is hardcoded, so dropping in a new fetcher and choosing "Rescan folder" picks it up.

  • Credentials, in a sensible order: you're asked for the folder, then the Gmail address, then that account's App Password — you always know which account you're authorizing before typing a secret for it.

  • Enable exactly the billers you want: the list is a live toggle ([x]/[ ]) you can revisit and change any time. Only enabled billers ever run.

  • Runs on a visible schedule: one shared interval for all enabled billers, shown and editable in the same screen (default every 360 min). Like the Gmail sync it is in-process — it runs while OpenBoardCLI is open, with no daemon — but the last run time is remembered, so reopening the TUI doesn't re-fetch everything and an overdue run fires on launch.

  • Invoices become dashboards automatically: after each fetch OpenBoardCLI hashes the biller's CSV. New rows refresh that biller's dashboard — using the matching category preset, e.g. Zomato → Food, Uber → Travel, Amazon → Shopping. If a biller has data but no dashboard yet (common when you bring an existing CSV with you), the first run builds one from the data already on disk rather than waiting for new mail that may never come.

  • Live fetch log: scheduled runs happen with no screen open, so their output goes to a shared activity log. Open Integrations → Gmail later and the recent history is still there, scrollable with PgUp/PgDn.

  • Headless: openboard agent setup billers --scripts-dir ... --biller-email ... --biller-app-password ... configures it, openboard agent billers status|sync [--biller <key>] inspects or runs it once. The recurring schedule itself is TUI-only.

Biller Studio — create your own fetcher

The eight bundled fetchers will not cover your billers. Billers are regional and personal, and no shipped list ever will. So OpenBoardCLI can write one for you:

Integrations → Gmail → ✚ Add a biller

  1. Give it the sender address those receipts come from, and a bit of the subject line to separate receipts from marketing mail (- matches everything from that sender).
  2. It finds one real matching email and shows you the exact text it wants to send to your LLM provider. Nothing is transmitted until you type yes.
  3. It proposes the fields it can extract, with the value it found for each, so you can check them against the email in front of you.
  4. On confirmation it writes a fetch_<key>.py, compiles it, checks how much it actually extracts, and dry-runs it against your mailbox before saving. Failures are fed back and retried up to twice.
  5. The new biller appears beside the bundled ones, already enabled.

PDF billers work too — if the receipt is in an attachment, the probe reads it with pdfplumber and the generated fetcher is built from the PDF-reading skeleton.

Generated code is scanned before it is written. A fetcher reads mail and writes a CSV; anything reaching for the network, a subprocess, eval, or the wider environment is refused, because the sample email is text somebody else wrote and could contain instructions aimed at the model.

Commands inside the Studio: /probe /fields /script /restart /cancel /help.

Security

Your Gmail App Password is stored AES-256-GCM-encrypted in ~/.openboard/config.json and handed to each fetcher through its process environment at run time — it is never written to disk. (Versions up to 1.9.0 wrote it to secrets/gmail_app_credentials.json; that file is deleted automatically and fetchers installed before the change are upgraded in place on the next run, keeping any edits you have made to them.)

An App Password grants full mailbox read access — broader than the OAuth integration's read-only scope — so revoke it in your Google account when you want to cut access off.

OpenBoardCLI only ever executes python/python3/py on .py files directly inside the folder you configured, never through a shell. Fetches are serialised by a lock, so a scheduled run and a manual "Fetch now" cannot write the same CSV at once.

Fetchers need Python 3 with beautifulsoup4 (plus pdfplumber for PDF billers).

Internal Chat Commands

Internal chat commands start with /.

| Command | Action | |---|---| | /deploy | Build, push to GitHub, and deploy to Vercel | | /push | Commit and push to GitHub only | | /preview | Start or restart local preview | | /build | Run the generated app build | | /update | Regenerate from latest linked data using prompt history, then build/push/deploy | | /data | Show linked data source summary | | /billers | Invoice fetcher status; /billers sync runs the enabled ones; /billers enable\|disable <key> toggles one | | /history | Show prompt history for the dashboard | | /logs | Show latest operation log | | /doctor | Check LLM/GitHub/Vercel/project readiness | | /model | Show or switch the LLM model and effort (/model <model> [effort], /model effort <level>) | | /stop | Cancel the current in-flight operation (generation, build, push, or deploy) | | /resume | Resume the latest interrupted/failed run for this dashboard from where it left off | | /status | Show dashboard/project status | | /config | Open settings | | /commands | Show command palette | | /help | Show command help |

When typing /, the TUI shows matching command suggestions with color coding. The chat labels are fixed-width: You, LLM, Sys (cyan, informational), and Err (red — reserved for real failures). Provider failures are summarized in plain, actionable language (invalid key, unreachable local server, unsupported model settings, quota) instead of raw provider error text, and successful /build//push runs end with the suggested next command. The chat header shows the configured LLM, model, effort, and app mode.

Agent Automation

Agents and scheduled jobs should use non-interactive commands. Progress streams live in both modes so the run never looks wedged: plain mode prints [step/8]-labelled lines on stdout (with periodic "still generating… Ns elapsed" heartbeats during LLM calls), and --json mode emits NDJSON events on stderr carrying phase, pct, step, and totalSteps.

Create a dashboard from a data source (.csv, .xlsx, or .json):

openboard agent create --data ./data/uber.xlsx --name "Uber Data"

Update an existing dashboard with a user prompt:

openboard agent update --dashboard uber-data --prompt "Add weekday vs weekend trends"

Refresh from the latest linked data using saved prompt history:

openboard update --dashboard uber-data

Machine-readable mode:

openboard agent update --dashboard uber-data --prompt "Add trends" --json

See Agent.md for the full automation contract.

CLI Commands

openboard start
openboard update --dashboard <id-or-name-or-title>
openboard update --all
openboard rollback --dashboard <id-or-name-or-title>
openboard agent create --data <file.csv|.xlsx|.json> --name <title> [--type custom] [--quality high|low] [--prompt "..."] [--json]
openboard agent update --dashboard <selector> --prompt "..." [--data <file>] [--json]
openboard agent setup llm --provider <name> [--model <model>] [--effort low|medium|high|max]
openboard agent setup billers --scripts-dir <dir> --biller-email <address> --biller-app-password <pw> [--biller-key <key>]... [--biller-sync-interval 360]
openboard agent billers <sync|status> [--biller <key>] [--json]
openboard agent list | status | runs | resume <run-id> | rollback [--json]
openboard --version
openboard --help

Generated App

Generated dashboards live under:

projects/openboard-app-workspace-<id>/

The generated app uses:

  • React 19
  • Vite 7
  • Recharts 3
  • Tailwind CSS 4
  • AuthProvider/LoginPage from the template
  • Vercel environment variables for dashboard credentials

Shell-owned files (App.tsx, App.css, header components, api handlers, hooks) are re-synced from the template on every deploy, so template fixes reach existing projects. Tab composition lives in the product-owned src/generated/dashboardManifest.tsx; the LLM owns only the per-dashboard components (components/*.tsx) — App.tsx, the manifest, and MasterDashboard.tsx in model responses are ignored.

Data Privacy & Security

  • Your parsed dashboard rows live in api/_data/ inside the generated project. They are uploaded to your Vercel deployment (served only through the authenticated /api/dashboard-data endpoint) but are never committed or pushed to GitHub: OpenBoardCLI excludes them via .git/info/exclude and untracks them in projects created before this protection existed.
  • Because the raw data is not in the GitHub repo, deploys must go through OpenBoardCLI (Vercel CLI upload). A Vercel Git-integration build from the GitHub repo will not contain your data.
  • Data pushed to GitHub before this protection existed remains in old commits; rewrite history or recreate the repo if that matters to you.
  • Generated repos are created private by default. Anyone you grant repo access to can see everything that is committed.
  • Your data is sent to the LLM provider you choose. Generating or updating a dashboard puts a summary of your dataset and a sample of real rows into the prompt, which is transmitted to whichever provider is configured (Anthropic, OpenAI, Google, Moonshot). The prompts instruct the model never to embed that data in the generated code, but the transmission itself is inherent to how generation works. If your invoices or financial records must not leave your machine, use local mode (Ollama) — no dashboard content is sent anywhere in that mode.
  • Your Gmail App Password for the invoice fetchers is stored AES-256-GCM-encrypted alongside the other secrets and is handed to each fetcher through its process environment at run time. It is never written to disk. Versions up to 1.8.0 wrote it in plaintext to <scripts>/../../secrets/gmail_app_credentials.json; that file is deleted automatically on the next fetch or password save. If you are on 1.9.0 and your fetchers stopped working, upgrade — 1.9.0 removed that file without updating fetchers installed before it, so they failed trying to read it (reported misleadingly as a missing Python). 2.0.0 and later repair installed fetchers in place on the next run, keeping any edits you have made to them. 1.9.0 is deprecated on npm for this reason. If you have stopped using the fetchers, delete it by hand — and treat the App Password as exposed if that file was ever backed up or synced, revoking it at myaccount.google.com/apppasswords.
  • Provider keys and tokens are stored AES-256-GCM-encrypted in ~/.openboard/config.json. The encryption key is derived from OPENBOARD_ENCRYPTION_SECRET, or from a generated per-machine secret stored at ~/.openboard/.encryption-secret (file mode 0600). Note: an attacker with full access to your home directory can read both files — set OPENBOARD_ENCRYPTION_SECRET (e.g. from an OS keychain) if you need stronger protection. Legacy plaintext secrets are re-encrypted automatically on first read.
  • Dashboard login rate limiting in the deployed app is per serverless instance (best-effort). For a hard global limit, put the deployment behind Vercel's attack challenge / a WAF, or back the limiter with Vercel KV.

Development

npm install
npm run lint
npm run test:unit         # fast, deterministic suite (CI gate)
npm run test:integration  # real npm install + vite build lifecycle
npm run build

Focused command parser test:

npm run test:run -- tests\phase4\command-parsing.test.ts

Docs

| File | Purpose | |---|---| | user-manual.md | Human usage guide | | Agent.md | Non-interactive agent command contract | | arch.md | Current architecture and data flow |

Notes

  • openboard requires an interactive terminal.
  • openboard agent ... is for automation and should not open the TUI.
  • Prompt history is stored locally per dashboard and powers /update and openboard update.
  • Vercel Git-integration deploys from the pushed GitHub commit will not include your raw dashboard data (see Data Privacy & Security) — deploy through OpenBoardCLI so the Vercel CLI uploads the data files.

Configuration

Provider keys and GitHub/Vercel tokens are entered interactively and stored encrypted in ~/.openboard/config.json. Optional environment variables are documented in .env.example.

Contributing

Issues and pull requests are welcome. Please run npm run lint and npm run test:run before opening a PR.

License

Apache 2.0 © Syed Ateebul Islam

Versions 1.8.0 and earlier were released under the MIT License. Versions 1.9.0 and later are licensed under Apache-2.0.