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

@findmynew/client

v0.0.3

Published

Local agent for findmynew.work — drives the user's browser for login, verify, search and apply against a remote findmynew API.

Readme

@findmynew/client

fmwork — the local agent for findmynew.work. It drives your real Chromium profile to log into job sites, harvest vacancies, and submit applications on your behalf.

Why this exists

findmynew.work scores postings and drafts cover letters for you. It deliberately doesn't host your browser session — your LinkedIn / hh / GetMatch / Wellfound cookies stay on your machine. fmwork is what runs on your laptop, owns a persistent Chromium profile under ~/.fmwork/<source>-profile, and executes the actions the findmynew dashboard asks for.

Install

# One-shot
npx @findmynew/client <command>

# Or install globally
npm install -g @findmynew/client
fmwork <command>

Chromium is downloaded automatically by Playwright on first install (postinstall hook).

Configure

Set your API key (issued from the findmynew dashboard):

fmwork config set apiKey fmwork_xxxxxxxxxxxxxxxxxxxxxxxx

Stored at ~/.fmwork/client.json. You can also pass FMWORK_API_KEY via env.

Running from a checkout (dev)

git clone [email protected]:findmynew/client.git
cd client
npm install
# Just run the CLI:
npx tsx src/cli.ts <command>            # always forwards every flag — safest
# Or via npm (NOTE: npm STRIPS --flags from script args):
npm run dev -- search linkedin --debug   # the `--` separator preserves --debug
FMWORK_DEBUG=1 npm run dev search linkedin  # env-var path, no `--` needed
npm run search:linkedin:debug            # dedicated script with FMWORK_DEBUG baked in

If you ever see npm run dev search linkedin --debug doing nothing visible — that's npm eating --debug before it reaches the CLI. Use one of the patterns above.

Commands

| Command | What it does | |---|---| | fmwork login <source> | Opens a real Chromium window so you can sign in to one of hh / linkedin / getmatch / wellfound. | | fmwork verify <source> | Headlessly opens the persistent profile, navigates to a known signed-in URL, and reports loggedIn=true/false. | | fmwork logout <source> | Wipes the local profile dir for one source. | | fmwork status | Per-source: profile present, last-known logged-in state, last verified-at. | | fmwork start | Daemon mode. Stays connected and executes actions as they're triggered from the findmynew dashboard (verify, search, apply). Stays running until you ^C. | | fmwork run [--limit N] [--dry-run] | Batch mode. Pulls your pending apply queue (vacancies you marked "send" in the dashboard), drives each apply in turn, exits. No long-running process required. | | fmwork search <source> [-q "kw"] [--limit N] | One-shot scrape of <source>. | | fmwork restart | Stops a running start process and starts a fresh one. | | fmwork config <get\|set\|unset> [key] [value] | Manage local config at ~/.fmwork/client.json. |

Two ways to use the client

  • Daemon (fmwork start). Keep it running in a terminal. Actions you trigger in the dashboard ("re-verify my LinkedIn login", "scrape hh for 'staff frontend remote'", "apply to this one I just queued") run on your machine immediately. Best for "always-on" use.
  • Batch (fmwork run). No daemon. You queue up several applies in the dashboard, then run fmwork run once. It drains the queue, drives each apply, exits. Best for "I'll sit down once a day and process my queue."

Both modes share the same Playwright runners, so a fix in one flows to the other.

What gets reported back

Each action produces a result: login state, scraped vacancies, application outcomes. When an apply flow lands on an external corporate ATS (Greenhouse / Lever / SmartRecruiters / a custom company portal), fmwork also notes the URL plus a sanitized snapshot of the form structure — no field values you typed, just the shape — so future versions can grow a direct connector for that site.

Layout

src/
  cli.ts                      # commander entry, dispatches to commands/
  commands/                   # one file per CLI subcommand (login, verify, start, run, search, …)
  runners/
    recipe.ts                 # search recipe shape
    search.ts                 # headless: drive a recipe, return scraped rows
    apply.ts                  # headful: drive LinkedIn Easy Apply / capture external ATS
  transport/
    api.ts                    # REST helper (fetch wrapper)
    ws.ts                     # long-lived connection client with auto-reconnect
  playwright/
    runner.ts                 # shared launchPersistentContext wrapper
    profile.ts                # resolves $HOME/.fmwork/<source>-profile
  capture/
    external-sites.ts         # detects + sanitizes unknown ATS forms
  config.ts                   # read/write ~/.fmwork/client.json + env overrides
  protocol.ts                 # zod schemas for wire messages

Status

Login, verify, status, search, daemon (start), batch (run) work end-to-end. LinkedIn Easy Apply has a real submit path; hh / GetMatch / Wellfound currently fall through to external-handoff (open + capture, finish manually) until each gets its own connector.