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

@anyforge/control

v0.9.2

Published

AnyForge CLI — hosted Oracle conversations, a governed LLM proxy, and a scriptable client for approvals, crews, work items and workflows.

Readme

@anyforge/control

Three interfaces in one binary:

  1. A governed LLM proxy for any agent — Claude Code, Cursor, Cline, Continue, or your own SDK. Route their calls through AnyForge for cost analytics, audit log, and policy enforcement.
  2. A scriptable AnyForge client — approvals, crews, work items and workflows from a shell, with no browser and no agent in the loop.
  3. The hosted Oracle in your terminal — persistent conversations, streamed answers, workspace context, questions, explicit attachments and generated-file downloads.

The second half is what makes AnyForge usable from CI. Every command speaks the same /api/v1/control/* API the MCP server does, but without needing a language model to drive it.

Install

npx @anyforge/control init

Sign in to the workspace you want to connect. Issuing a Control key requires an Owner, Operator or Editor role in that workspace. If approval says Editor or higher required, ask a workspace owner to check your membership and role, then rerun init with a new browser approval code. Reinstalling the CLI does not change your permissions.

Owners and Operators can receive read, write and approve scopes. Editors can receive read and write for planning, but cannot run crews or approve gates. A role change does not add scopes to an existing key; rerun init if the new role needs scopes your key lacks.

The CLI:

  1. Issues a one-time auth code, opens your browser to authorise it.
  2. Stores the resulting API key at ~/.anyforge/credentials (chmod 600).
  3. Asks whether to install globally (~/.claude/settings.json) or per-repo (the per-repo option only appears when you run the command at the root of a git working tree).
  4. Patches the chosen target so Claude Code routes through https://crew.anyforge.ai/v1/anthropic and …/v1/openai. The actual API key is inlined into the patched config — no ${ANYFORGE_API_KEY} indirection, no shell restart required.

After that, your next LLM call shows up under Control on /usage within seconds.

Install scope

| Choice | Files written | Effect | |---|---|---| | global | ~/.claude/settings.json (+ optional shell-rc hints for Cursor / Cline if installed) | Every Claude Code session on this machine routes through AnyForge | | repo | <repo>/.claude/settings.local.json and <repo>/.env | Only Claude Code sessions inside this repo are routed; no global side effects |

Pick whichever suits the moment — the choices aren't mutually exclusive over time:

  • Want to add a second repo? Re-run npx @anyforge/control init from that repo's root and pick repo again.
  • Want to switch to a system-wide install later? Re-run from anywhere and pick global.
  • Want to undo a per-repo install? Run anyforge logout — it now reverts the patched configs (~/.claude/settings.json, <repo>/.claude/settings.local.json, the # === AnyForge Control === block in .env / your shell rc) and restores any previously-shadowed login.

The .env written in per-repo mode contains a live ANYFORGE_API_KEY. The CLI warns if your repo's .gitignore doesn't already exclude .env. Add it before committing.

Claude Pro / Max subscription users

The inference proxy is BYOK-only: it routes Claude Code through your own Anthropic API key for metering and governance. It is incompatible with a Claude Pro/Max (subscription) login — the ANTHROPIC_AUTH_TOKEN it patches out-ranks (Claude Code auth precedence #2) and therefore disables the subscription login (#6), and the proxy has no upstream API key for a subscription user, so Claude Code falls back to "please login".

anyforge init detects a subscription login and skips patching, steering you to the AnyForge MCP server instead — which keeps your subscription for inference and adds AnyForge control (HIL approvals, work items, crews) on top, with no auth conflict:

claude mcp add anyforge -- npx -y @anyforge/mcp-server

Run this after init: the MCP server reads the credential and endpoint from ~/.anyforge/credentials, so no secret belongs in the command. If your MCP client runs on another machine, configure its secret store with ANYFORGE_API_TOKEN and ANYFORGE_API_URL; ANYFORGE_API_KEY is not the MCP server's credential variable. Restart the client and check claude mcp list.

If you really want the metered BYOK proxy, re-run anyforge init --force (you'll need an Anthropic API key configured on your company; this disables your subscription in Claude Code until you anyforge logout).

Why ANTHROPIC_AUTH_TOKEN, not ANTHROPIC_API_KEY?

Claude Code recognises both, but they behave differently. ANTHROPIC_API_KEY is sent as X-Api-Key and — when an OAuth Console login is also present — surfaces an "Auth conflict: Using ANTHROPIC_API_KEY instead of Anthropic Console key" warning, and can cascade into a "selected model may not exist" error. ANTHROPIC_AUTH_TOKEN is sent as Authorization: Bearer …, is documented for "routing through an LLM gateway or proxy", and matches the bearer-token shape AnyForge expects. We patch the token form, and on every install we explicitly delete any stale ANTHROPIC_API_KEY left behind by older versions. Note that it out-ranks a subscription login (see above) — which is exactly why init refuses to patch over a Pro/Max login by default.

Commands

Oracle

Requires Node.js 22.19 or later. Sign in with a separate Oracle credential, then start a conversation or submit a read-only turn from a script:

anyforge oracle login
anyforge oracle
anyforge oracle -p "Summarize current risks"
anyforge oracle --program prog_123
anyforge oracle exec "Summarize current risks" --json
cat incident.log | anyforge oracle exec "Explain this log" --stream-json
anyforge oracle sessions
anyforge oracle resume <session-id>
anyforge oracle download <session-id> <file-id> --output ./downloads

Oracle login uses browser authorization with PKCE and stores its credential in ~/.anyforge/oracle. It leaves your inference proxy and MCP setup unchanged. For unattended use, an attributable API key in ANYFORGE_API_TOKEN takes precedence over saved Oracle logins.

Credential changes are serialized across CLI processes. Version 0.9.1 adds a non-expiring admission guard before recovering an older refresh lock. Ordinary completion, errors and process signal exit release both locks. A SIGKILL or OS crash can leave ~/.anyforge/oracle.refresh-admission behind; the CLI waits for a bounded period and reports that exact path instead of risking reuse of a rotated token. Stop all AnyForge CLI commands, then remove that directory and retry. Do not remove it while another command is running. Older CLI versions do not honor this guard: upgrade every concurrently used installation to 0.9.1 or later.

Each login belongs to one workspace, and you can keep one per workspace. The workspace name shows in the welcome card, the bottom line, /status and the login message.

anyforge oracle login --workspace "Beta Labs"   # add a workspace; it becomes active
anyforge oracle workspaces                      # list saved workspaces (--json)
anyforge oracle use "Acme Engineering"          # change the active workspace
anyforge oracle exec "..." --workspace company-2  # one command only
anyforge oracle logout                          # the active workspace (--workspace <name>, --all)

--workspace on login only pre-selects the workspace on the consent page; the CLI reports the one you actually connected. In a conversation, /workspace switches to another saved workspace and starts a new conversation there. With ANYFORGE_API_TOKEN set, the key's workspace is used and switching is refused with an explanation.

Interactive conversations are read only by default. Use oracle login --write and start with oracle --write to enable workspace edits. Consequential edits require a later explicit confirmation of the proposed action. Operator actions and external MCP writes additionally require --approve. oracle exec and oracle -p always remain read only.

Use Shift+Enter for multiline input. Type / for the command palette: /help, /status (session, workspace, access, model, last turn, usage and limits), /new, /clear, /resume, /workspace, /context, /attach, /copy, /files, /usage, /model and /exit. /design [topic], /catchup and /remember [what] are answered by the Oracle itself, as in the web widget; acting on /catchup decisions needs a session started with --write --approve.

While Oracle works, an indicator appears under its name immediately. A status line shows elapsed time and the current step, and each tool appears as it runs. Enter queues one follow-up message. Esc or Ctrl+C cancels the current run and keeps the conversation open; press Ctrl+C twice, or Ctrl+D on an empty line, to exit. Ctrl+O shows or hides finished tool activity; Ctrl+Shift+F searches the conversation. A disconnect leaves the hosted run active.

Only files explicitly named with --file or /attach are uploaded: at most 10 files, 10 MiB each and 20 MiB total. Piped input is limited to 1 MiB; free-text --context to 8 KiB. Download destinations must already exist, and downloads never overwrite files. Oracle does not discover local files or run local tools. The server also checks saved conversation size; use a new session or an attachment when a turn exceeds the remaining conversation limit.

anyforge ask keeps its existing stateless read-only API and JSON output. See the CLI guide for the full command contract.

Oracle in ACP clients

anyforge acp exposes the hosted Oracle over Agent Client Protocol v1 stdio. Sign in once with anyforge oracle login, then add a local ACP provider in T3 Code with executable anyforge and argument acp. For an editor that accepts command configuration:

{
  "command": "anyforge",
  "args": ["acp"]
}

Editors that install agents from the ACP Registry run npx -y @anyforge/control acp and sign in through the agent: in the browser, or with --login as terminal auth.

The adapter supports saved conversations, streaming answers, tool activity, questions, cancellation and recovery after a stream disconnect. Read access is the default. Add --workspace <name-or-id> to select a saved workspace, or --program, --initiative or --codebase to select Oracle context. Workspace changes need a suitable grant and --write; operator actions also need --approve and your current role. The same Oracle confirmation rules apply.

This is a hosted Oracle integration: local files are never opened or changed, and client-supplied MCP tools are omitted with a visible notice. T3's injected tools are handled this way too. Your workspace's server-side tools remain available within your access. This deliberately limited ACP profile does not claim full protocol conformance. See the ACP setup guide for limits and setup details. ACP v2 is not supported.

Setup

| | | |---|---| | anyforge init | Authorise this device and patch local agent configs | | anyforge whoami | Show the company, scopes and endpoint this key acts as (asks the server) | | anyforge status | Check server identity, local configuration and personal recorded activity (--json supported) | | anyforge logout | Clear the local credential file and revert patched configs (does not revoke server-side) | | anyforge apply-patch | Apply a unified diff from a file or stdin via git apply |

Scriptable

| | | Scope | |---|---|---| | anyforge approvals | List HIL approvals awaiting a decision | read | | anyforge approve <id> | Approve one (--notes is recorded in the audit trail) | approve | | anyforge reject <id> | Reject one | approve | | anyforge crews | List crews (--active for non-terminal only) | read | | anyforge crew <id> | Show one crew, its status and recent output | read | | anyforge crew start <item> | Dispatch a crew on a work item (--profile, --follow) | write + a role that can dispatch | | anyforge crew follow <id> | Watch a run until it needs a person or ends (--interval) | read | | anyforge halt <id> / resume <id> | Stop or restart a crew | approve | | anyforge work | List work items (--status, --type, --priority, --search, …) | read | | anyforge workflows | List operator workflows | read | | anyforge run <id> | Dispatch a run (--input '{"repo":"acme/web"}') | write | | anyforge ask <question> | Ask the Oracle one question | read | | anyforge audit | Page through the hash-chained audit trail (--event, --actor, --from, --to, --cursor, --all); --verify checks every hash and link across the pages read | audit:read + owner | | anyforge people invite <email> --role <role> | Invite one person as operator, editor, viewer or filer on a verified company domain (--team <ids>, --no-email); people invitations lists the invitations the key could have written and people withdraw <email> withdraws a pending one | people:invite + owner |

Every command takes --json, which prints the API payload verbatim:

anyforge approvals --json | jq 'length'
anyforge crews --active --json | jq -r '.[].id' | xargs -n1 anyforge halt

Exit codes

CI gates on these, so they are a contract:

| | | |---|---| | 0 | Success — an empty list included | | 1 | Network or unexpected failure (retryable) — and a crew follow whose run ended HALTED / REJECTED / CANCELLED, which is not | | 2 | Usage error | | 3 | Not authenticated — run init, or set ANYFORGE_API_TOKEN | | 4 | The API refused; its error code, and any details the API sent with it, print to stderr | | 5 | audit --verify found a broken link or an entry that no longer matches its hash | | 130 | An Oracle run was interrupted: exec was cancelled with Ctrl+C, or you left an interactive session whose last answer you cancelled |

Errors and progress go to stderr, so a --json pipe stays parseable under a failure.

crew follow is the one command whose exit code carries an OUTCOME rather than a transport result, which is what makes it usable as the last step of a job:

# Hand a ticket to a crew and fail the build if the work didn't land.
anyforge crew start "$ITEM" --follow

It exits 0 when the run finishes or stops at a gate that needs a person, and 1 when the run ended badly or was still going after 30 minutes. Under --json its final line is { crewId, status, waiting, url }, so a script can tell those two 0s apart.

Unattended use

Set ANYFORGE_API_TOKEN (and optionally ANYFORGE_API_URL) instead of running init — no browser, no credential file. Mint the key under Settings → API keys with the narrowest scope the job needs.

Endpoints

The CLI defaults to https://crew.anyforge.ai. Override per-invocation with --endpoint, or globally with the ANYFORGE_ENDPOINT environment variable.

The proxy exposes:

  • POST /v1/anthropic/v1/messages — drop-in for https://api.anthropic.com/v1/messages. Use Authorization: Bearer sk_anyforge_… instead of x-api-key. The /v1 repeats because you set ANTHROPIC_BASE_URL to https://crew.anyforge.ai/v1/anthropic and the Anthropic SDK appends /v1/messages to it.
  • POST /v1/openai/v1/chat/completions — drop-in for https://api.openai.com/v1/chat/completions.

Both validate your AnyForge API key, look up your company's BYOK provider key, forward the request, and stream the response back unchanged. Token counts and cost are logged to your usage dashboard.

What you get

  • Cost analytics — per-call, per-company, per-model spend on /usage.
  • Audit log — hash-chained record of every prompt + response.
  • BYOK — your provider keys live in your AnyForge company; the CLI never holds raw provider keys on the local machine.
  • One key, every agent — the same sk_anyforge_… works for any agent that talks OpenAI- or Anthropic-shape APIs.

Coming soon

  • anyforge proxy — local proxy mode for OPA-enforced redaction before requests leave your network.
  • Intent-based routing (rules / regex / embeddings).
  • Portable memory injection.
  • Ollama support for local models.

License

Apache-2.0

Check a Control installation

Run anyforge status after setup and after making a real request in your agent. It authenticates against the saved endpoint (or the explicit endpoint override), shows the current user, company and granted scopes, and reads the latest recorded Control proxy usage and optional Claude Code subscription telemetry for that user in that company, across devices. Role checks still apply to individual actions. A successful check verifies the Control API used by MCP; confirm the actual MCP connection in your agent client. It does not send an inference request or charge for a test call.

If you used an older CLI, run npx @anyforge/control@latest status to use the current diagnostics. Confirm the displayed workspace and user before checking activity. In Settings → API keys, the last-used time shows credential use; in Traces, My activity filters attributable traces to your user. Older traces labelled Unknown cannot establish who made the request.

The three connections are separate:

  • MCP provides access to AnyForge work and tools. It does not route inference or capture every local conversation.
  • Inference proxy routes supported requests through the company's BYOK key. Configured settings and historical usage do not prove forwarding works now.
  • Subscription telemetry is optional. Subscription inference stays with the provider; exported token counts and estimated cost appear at /usage, not as full conversation traces at /traces. No prompts are exported by this setup.

Status inspects the current shell, Claude Code user/project settings and the standard stdio MCP configuration written by init. Matching settings are local observations, not proof of the client's effective configuration: managed settings, other clients and hosted MCP need checking in the client itself. “Not detected” does not mean disabled. Missing activity, unavailable history, and an older key without user attribution are reported separately. An unavailable history read exits 1; authentication failures use the normal Control API error exit code 4.

If telemetry has no recorded activity, restart Claude Code after setup, use it, allow its exporter interval to complete and rerun status. If inference fails, check the company's BYOK provider key and the agent's endpoint. If the displayed company or user is wrong, reconnect with anyforge init rather than editing an ID. The server route and its Firestore indexes must be deployed before a newly built CLI can use this diagnostic command; a 404 is not an authentication verdict.

Code Studio

Studio commands require @anyforge/control 0.9.0 or later and a deployed Studio API. Install with npm install -g @anyforge/control@^0.9.0 after its npm release; a repository build or application deployment does not update an installed CLI. Run anyforge --version to check the installed version.

Use a dedicated Studio key from Settings → API keys. Standard write and legacy keys do not authorize Studio execution or publication. Owners and operators, plus editors explicitly enabled by their company owner, can use these commands; service accounts cannot own interactive Studio sessions.

anyforge studio list --json
anyforge studio usage SESSION --json
anyforge studio create --repo acme/app --branch feature/fix --context "Fix the form" --json
anyforge studio continue SESSION --file src/form.ts --context "Review this local reference"
anyforge studio open SESSION
anyforge studio run SESSION --context "Implement and test the fix" --input '{"maxTotalTokens":40000}'
anyforge studio events RUN --cursor 12 --json
anyforge studio answer RUN --context "Use option A" --input '{"questionId":"QUESTION"}'
anyforge studio cancel RUN
anyforge studio changes SESSION
anyforge studio commit SESSION --input '{"message":"Fix form","expectedRevision":"REVISION"}'
anyforge studio push SESSION --input '{"expectedHeadSha":"SHA"}'

create and continue prepare context without running code. --file sends only that file (20 KB maximum), labels its local branch/commit and uncommitted state, and does not copy local edits into the remote checkout. --initiative ID assigns a new session to an existing initiative; omission starts direct work. Keep the returned session/run IDs and event cursor to reconnect. Reuse an explicit idempotencyKey in --input when retrying a create or run request.

studio usage SESSION reads the owned session's recorded billing subtotal, limited to the newest 200 rows, grouped by actual model, product, run and leg. It preserves the API's truncated, coverage and pending fields. Historical coverage may be incomplete; missing attribution is unavailable cost, not zero. Provider cost and platform fee remain separate fields. This read never starts a run or calculates prices locally.

Read access requires studio:read; preparation requires studio:write; runs and local Git operations require studio:execute; pushing and PR lifecycle actions require studio:publish. External runs use audited local coding, reads and reviews. Hosted shell, browser, connectors, Oracle, crew dispatch, workflows and approvals require browser Studio with its separate role and confirmation gates; publish scope does not unlock them. Opted-in editors can edit, review, commit and publish with their own GitHub identity, but cannot dispatch crews or approve work. Review changes before committing, prefer draft PRs, and confirm ready/merge in browser Studio only for a specific PR and exact head after checks and review pass.