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

@apexstack/agent

v0.5.1

Published

PJT Agent — runs PJT workspace tasks on your own computer (Claude Code primary, OpenAI Codex failover).

Readme

PJT Agent

Run your PJT workspace tasks on your own machine.

Claude Code first, OpenAI Codex as automatic failover — with human-in-the-loop decisions and secret redaction built in.

npm version node install size license website


What it is

PJT Agent is a small CLI that connects a PJT workspace to the coding agents already installed on your computer.

You press Run with PJT Agent on a task in the web app. The agent — running on your machine, in your repository, with your credentials — picks the task up, executes it, and reports the result back to the task.

Nothing runs on our servers. The server only holds a queue. Your source code, your API keys and your model credentials never leave your machine.

   PJT web app                    your computer
  ┌───────────────┐              ┌──────────────────────────┐
  │  Task #128    │   long poll  │  pjt-agent start         │
  │  [Run ▶]      │◄─────────────┤    └─ claude / codex     │
  │               │   result     │        in ~/code/my-repo │
  └───────────────┘─────────────►└──────────────────────────┘

Quick start

1 — Install

npm install -g @apexstack/agent

2 — Log in with the token from the web app (Workspace → AI Integrations → PJT Agent → Install Agent; the wizard prints the full command)

pjt-agent login --token pjta_xxxxxxxx

3 — Start it inside the repository the tasks should run in

cd ~/code/my-backend
pjt-agent start

That's it. Leave it running and dispatch tasks from the web app.

npx @apexstack/agent@latest start

Requirements

| | | |---|---| | Node.js | 18 or newer | | Primary runner | Anthropic claude CLI, installed and signed in | | Failover runner | OpenAI codex CLI, installed and signed in (optional — see below) |

Without codex, a Claude failure ends the task with an explicit failover error instead of silently retrying.

Commands

| Command | What it does | |---|---| | pjt-agent login --token <t> | Save token + runner policy to ~/.pjt/agent.json | | pjt-agent start | Long-poll the queue and execute tasks | | pjt-agent status | Verify the token and print the active configuration | | pjt-agent mcp | Run a stdio MCP server exposing workspace context (legacy) | | pjt-agent logout | Delete the local configuration |

Common options

pjt-agent login  --token pjta_xxx --api https://api.pjt.ai \
                 --runner claude --fallback-runner codex

pjt-agent start  --cwd ~/code/my-backend \
                 --runner claude --fallback-runner none

--runner accepts claude or codex; --fallback-runner also accepts none.

How it works

1  pjt-agent start
2  GET  /api/v1/agent/tasks/next?wait=20      ← long poll
3  task received  →  run `claude -p "<prompt>"`  in the task's working directory
4  on failure, if eligible  →  `codex exec --sandbox workspace-write`
5  POST /api/v1/agent/tasks/{id}/complete     → status, summary, changed files
6  back to 2

Failover rules

Failover exists to survive a broken CLI, not to re-run work. A second runner starts only when all of these hold:

  • the primary runner failed, and
  • the failure was not a policy refusal or a user cancellation, and
  • the git fingerprint of the working tree is byte-for-byte unchanged since the run began.

If Claude modified files or created a commit and then failed, the failure is reported as-is. Nothing is executed twice.

Human-in-the-loop decisions

Some choices are not the agent's to make — a schema migration, a dependency swap, a destructive command. Instead of guessing, the agent can stop and ask.

When the runner emits a fenced pjt-decision block, the agent posts the question to the task, shuts the runner down, and returns to polling. The task moves to WAITING_USER:

```pjt-decision
{
  "type": "SINGLE_CHOICE",
  "severity": "HIGH",
  "question": "The users table needs a new unique index. Apply it now?",
  "options": ["Apply in this task", "Defer to a migration PR"]
}
```

| Field | Values | |---|---| | type | SINGLE_CHOICE (default) · TEXT · CONFIRMATION | | severity | HIGH (default) · CRITICAL | | question | required, non-empty |

You answer in the web app. The agent picks the task back up and resumes with the previous context plus your answer, so completed work is not repeated.

Free-form text is never interpreted as a question. Only the exact fenced block counts — otherwise ordinary output would halt runs.

Secret redaction

Agent output routinely contains credentials — an echoed header, a printed env var, a stack trace. Everything sent to the server is masked first, by key name and by value shape:

| Detected by key | Detected by value | |---|---| | authorization, api_key, client_secret, password, private_key, cookie, access_token, refresh_token, … | Bearer …, JWTs, pjta_…, glpat-…, ghp_…, sk-…, sk_live_…, xoxb-…, AKIA…, PEM private key blocks |

Values are masked together with their scheme, so Authorization: Bearer eyJ… is redacted whole rather than leaving the token behind.

MCP server

Use the remote HTTP MCP instead. The tool cards under AI Integrations give you a https://mcp.pjt.ai URL and an Authorization: Bearer header — no install, no local process. The stdio server below is kept for offline and restricted environments.

# after `pjt-agent login`
claude mcp add pjt-workspace -- pjt-agent-mcp

# or inject the token directly, without logging in
claude mcp add pjt-workspace \
  --env PJT_AGENT_TOKEN=pjta_xxx \
  --env PJT_API_URL=https://api.pjt.ai \
  -- pjt-agent-mcp

Seven read-only tools are exposed:

| Tool | Input | |---|---| | list_workspaces | — | | get_project | projectId (numeric or p_xxx) | | list_project_tasks | projectId, status? | | get_task | taskId | | get_document | documentId | | list_workspace_documents | workspaceId, limit? (1–50) | | get_workspace_snapshot | workspaceId |

Authorization is enforced server-side. stdout carries JSON-RPC only — all logging goes to stderr.

Configuration

Resolution order is environment variable → ~/.pjt/agent.json → default.

| Variable | Default | |---|---| | PJT_AGENT_TOKEN | from config file | | PJT_API_URL | https://api.pjt.ai | | PJT_AGENT_RUNNER | claude | | PJT_AGENT_FALLBACK_RUNNER | codex |

Security

  • The token is stored at ~/.pjt/agent.json with mode 0600.
  • The server keeps only a SHA-256 hash — a lost token cannot be recovered, only reissued.
  • If a task's workingDir does not exist locally, the agent falls back to --cwd or the current directory rather than creating paths.
  • The agent holds no model credentials of its own; it invokes the CLIs you have already authenticated.

Troubleshooting

| Symptom | Cause | |---|---| | No output at all, exit code 0 | Version 0.3.0 only — upgrade: npm install -g @apexstack/agent@latest | | ✗ Not authenticated | Token revoked or expired — reissue under AI Integrations and login again | | Tasks stay queued | The agent is not running, or it is polling a different account's token — check pjt-agent status | | Failover never triggers | Expected when the working tree changed before the failure, or on a policy refusal |

Development

git clone [email protected]:pjt-ai/pjt-agent.git
cd pjt-agent
npm ci
npm run build
npm link                       # registers the global `pjt-agent` command
node --test test/*.test.mjs

Before publishing, verify the tarball through a global install — npm pack && npm install -g ./<tgz> && pjt-agent --version. Running node dist/index.js directly does not exercise the bin symlink.


pjt.ai · © 2026 ApexStack · Apache-2.0