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

@ar-llm/pi-dir-providers

v0.1.5

Published

Pi extension that scopes the providers visible in /model based on the working directory.

Downloads

792

Readme

@ar-llm/pi-dir-providers

npm Unlicense

Pi extension that scopes which providers are visible in /model based on the working directory. In ~/git you may only want anthropic and openroutergithub-copilot and everything else disappear from model selection entirely.

Install

pi install 'npm:@ar-llm/pi-dir-providers'

Or try without installing:

pi -e 'npm:@ar-llm/pi-dir-providers'

Config

Create <agentDir>/ar-llm/dir-providers.json (same convention as pi-custom-compaction; <agentDir> is $PI_CODING_AGENT_DIR or ~/.config/pi/agent):

{
  "rules": [
    {
      "dirs": ["~/git"],
      "allowedProviders": ["anthropic", "openrouter"],
      "defaultModel": "anthropic/claude-sonnet-4-5"
    },
    {
      "dirs": ["~/git/acme-corp", "~/work/acme-corp"],
      "allowedProviders": ["anthropic"],
      "providers": {
        "anthropic": { "baseUrl": "https://anthropic-proxy.acme.com/v1" }
      }
    }
  ]
}

Rule ordering (important!)

Rules are applied strictly in array order — not by specificity. Every rule whose dirs match the current working directory applies; for allowedProviders and defaultModel, the last matching rule wins (its value replaces any earlier rule's value). The providers field is different: overrides from all matching rules are merged together per provider id.

You must order rules from least specific to most specific. Put the broadest directory rules first and the narrowest (most specific) directory rules last. If you reverse this order, a generic rule will silently override a specific one. For example, with rules [{dirs: ["~/git/managing-construction"], allowedProviders: ["github-copilot"]}, {dirs: ["~/git"], allowedProviders: ["openrouter"]}], running in ~/git/managing-construction/gossamer matches both rules, and the second rule's openrouter wins — github-copilot gets hidden. The correct order is to swap them so ~/git comes first and ~/git/managing-construction comes second.

  • dirs: list of directory subtrees. A leading ~ is expanded; a directory matches when the cwd equals it or is inside it (subdirectories inherit their ancestor's rules; a more-specific rule then overrides on top). Directory paths are symlink-resolved, so /tmp on macOS (which resolves to /private/tmp) matches the physical cwd. Nonexistent or inaccessible directories warn at startup and match as-is; point the rule at the real resolved path.
  • allowedProviders: replaces the effective set of visible providers. Providers outside the set are hidden from /model (their models are removed for the session; auth//login state is untouched).
  • defaultModel: "provider/model-id" applied to fresh sessions when the current model differs. Skipped when --model/--provider was passed on the command line. Note that switching the model persists the choice to settings.json, exactly like picking a model manually in /model.
  • providers: per-provider overrides with models.json override semantics (e.g. baseUrl, headers), merged across matching rules per provider id.

If no rule matches, the extension does nothing.

How it works

Hiding happens at extension-factory time — before pi selects the initial model — by registering a models: [] overlay on each disallowed provider via pi.registerProvider(). This goes through pi's normal provider-composition path and is in-memory only: nothing on disk is touched, and /reload or a new pi process restores the default provider set.

Provider overrides (baseUrl, headers, extra fields, models) are applied the same way — as a registerProvider overlay — and are therefore also in-memory and reversible. A models field in an override replaces the provider's model set (like models.json), whereas an override object without models only tweaks connection fields and keeps the provider's existing models.

Validation

  • Missing config file, invalid JSON, or a missing rules array disable the extension (it stays a no-op).
  • Per-rule problems (empty dirs, relative dirs, duplicate dirs across rules, nonexistent dirs, malformed defaultModel, defaultModel provider not in the rule's allowedProviders) produce warnings and skip the offending part.
  • Unknown provider ids in allowedProviders warn at startup; check actual ids with pi --list-models.
  • If a later rule's directory is a parent of an earlier rule's directory (i.e. the broad rule appears after the narrow one), a warning is emitted at startup: the parent rule's allowedProviders/defaultModel will silently override the child rule's, and reordering is needed to fix it.

Commands

  • /dir-providers — print the effective profile for the current directory: matched rule indices, allowed providers, default model, and merged provider overrides. The TUI status bar also shows the active provider set (dir-providers: providers: ...) whenever the extension is active.

    Config-loading warnings (nonexistent/inaccessible dirs, unknown providers, rule shadowing) are not printed to stderr by default — they would only appear before the TUI starts, where they're invisible. Instead they are captured and surfaced as a Warning: notification in the TUI at session_start, so they are always visible when running interactively.

    For headless or non-TUI runs (or to debug startup behavior), set PI_DIR_PROVIDERS_DEBUG=1: diagnostics are written to $TMPDIR/ar-llm/dir-providers.log (never stderr).

Debug

The extension is quiet on stderr by default — diagnostics are routed to the TUI instead. To inspect raw startup behavior (e.g. for headless runs or to confirm which rules/providers resolved), enable verbose logging:

PI_DIR_PROVIDERS_DEBUG=1 pi ...

Diagnostics are written to $TMPDIR/ar-llm/dir-providers.log, including:

  • The [dir-providers] Active in <cwd>: rules ..., allowed [...], hid N providers status line.
  • All captured config warnings (EPERM, unknown providers, rule shadowing).

Development

make typecheck   # type-check source + tests
make test        # run unit tests (26 checks across match.ts and config.ts)
make test-watch  # same as `make test` but re-runs on file changes

Tests use Node.js's built-in node:test runtime — no external test runner is required (Node ≥ 22.6). The test/ directory contains a small ESM loader (loader.mjs + register.mjs) that maps NodeNext-style .js imports to their .ts source files so they can be imported without a build step.

Limitations

  • Providers registered by other extensions are not enumerated and cannot be hidden.
  • Directory globs are not supported; use explicit directory subtrees.
  • The profile is computed once per pi process from the startup cwd.

License

The Unlicense — public domain. Original work.