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

@404labs/portguard

v0.1.0

Published

Stable per-project localhost port assignment for AI-built apps. Prevents 3000/3001 drift, checks occupancy, and ships as an agent skill plus CLI.

Readme

portguard

Stable localhost ports for AI-built apps. Assign one durable port per project, skip the crowded 3000/3001 defaults, check occupancy, and stop framework auto-fallback from scrambling local accounts and password-manager entries.

AI coding agents often start every web app on localhost:3000, then drift to 3001, 3002, or a random framework fallback when something is already running. That makes browser profiles, OAuth callbacks, cookies, and password managers point at the wrong project. portguard gives each project a stable local URL and stores the assignment in a shared registry.


What it does

portguard keeps a local registry at ~/.404labs/portguard/registry.json:

  1. Assigns once per project - uses the git root when present, otherwise the current directory.
  2. Avoids common defaults - skips 3000 and 3001 by default.
  3. Checks occupancy - newly assigned ports must be bindable on 127.0.0.1.
  4. Prevents silent reuse - a port that belonged to one project is not given to another project just because the first server is stopped.
  5. Refuses silent drift - an occupied existing assignment is reported; the URL changes only when you explicitly run --reassign.

Install

As an agent skill

Recommended - global install via the Vercel Labs skills CLI (supports 55+ agent CLIs and keeps this behavior available in every repo):

npx skills add SpectreMercury/404labs --skill portguard -g

Install to the current detected agent instead:

npx skills add SpectreMercury/404labs --skill portguard

Install to all detected/supported agents:

npx skills add SpectreMercury/404labs --skill portguard --all

As a CLI

Install globally so all projects and agents share one command and one registry:

npm i -g @404labs/portguard

Or use it through npx:

npx @404labs/portguard assign --json

Built-in agent installer

The package can also copy the skill into common local agent folders:

npx @404labs/portguard install                      # auto-detect
npx @404labs/portguard install --target all         # install for all 4 supported
npx @404labs/portguard install --target claude,codex
npx @404labs/portguard install --list-targets

| Built-in target | CLI | Path | |---|---|---| | claude | Claude Code | ~/.claude/skills/portguard/ | | codex | OpenAI Codex CLI | ~/.agents/skills/portguard/ | | antigravity | Google Antigravity | ~/.gemini/antigravity/skills/portguard/ | | kimi | Moonshot Kimi CLI | ~/.kimi/skills/portguard/ |

Restart your CLI after installing the skill so its index refreshes.


Usage

Assign or read the current project's stable port:

portguard assign

Machine-readable output:

portguard assign --json

Print only the port for scripts:

PORT=$(portguard assign --print) npm run dev

Check whether a port is currently occupied:

portguard check 3124

List active assignments:

portguard list

Retire the current project's assignment without making the port reusable:

portguard release

Reassign only when you intentionally accept a new local URL:

portguard assign --reassign

Fail if the assigned port is occupied:

portguard assign --strict

Example output

portguard assignment

  project:  /Users/me/work/acme-dashboard
  name:     acme-dashboard
  port:     3104
  url:      http://localhost:3104
  source:   new
  status:   free
  registry: /Users/me/.404labs/portguard/registry.json

Use: PORT=3104 npm run dev

If the assigned port is occupied, portguard does not silently switch to a new URL:

status: occupied

The assigned port is occupied. If that is this project already running, keep
using it. If it is a different process, stop the conflict or run
`portguard assign --reassign` intentionally.

Wire it into common frameworks

Next.js:

{
  "scripts": {
    "dev": "next dev -p 3104"
  }
}

Vite:

{
  "scripts": {
    "dev": "vite --host 127.0.0.1 --port 3104 --strictPort"
  }
}

Astro:

{
  "scripts": {
    "dev": "astro dev --host 127.0.0.1 --port 3104"
  }
}

More examples are in references/frameworks.md.


Configuration

Flags:

--project <path>      Project path. Default: current working directory.
--name <name>         Display name stored in the registry.
--range <start-end>   Search range. Default: 3100-3999.
--reserved <ports>    Comma list to skip. Default: 3000,3001.
--host <host>         Bind-check host. Default: 127.0.0.1.
--registry <path>     Registry file. Default: ~/.404labs/portguard/registry.json.
--json                Machine-readable output.
--print               Print only the assigned port.
--strict              Exit 1 if the existing assigned port is occupied.
--reassign            Explicitly move to a new never-used free port.
--no-git-root         Key the exact path instead of the git root.

Environment:

PORTGUARD_REGISTRY=/custom/registry.json portguard list
PORTGUARD_RANGE=4100-4999 portguard assign
PORTGUARD_RESERVED=3000,3001,5173 portguard assign

Exit codes

| Code | Meaning | |---|---| | 0 | Command succeeded; check found the port free | | 1 | Occupied port, no available port, no assignment to release, or partial install failure | | 2 | Usage/configuration error |


License

MIT - see LICENSE.