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

@delt/claude-jev-advisor

v0.5.0

Published

Unofficial Claude Code helpers using TypeSafe Jev: compact/clear advice and an rm guard

Readme

claude-jev-advisor

Unofficial helpers for Claude Code, installed as command hooks in ~/.claude/settings.json. They use TypeSafe Jev for judgments that need to understand the conversation.

What is sent to TypeSafe's Jev API (api.typesafe.ai):

  • context: your last three requests (typed by you, or sent through a channel or from another Claude Code session), each cut to its first 1,000 characters, and Claude's last reply, cut to its first and last 1,500 characters.
  • rm: only for a delete it would otherwise ask about, and only when the target is a file this session made or a folder git ignores. It sends the path, the delete command and its description, up to three tool calls of this session that name the target (each cut to 600 characters), and for a folder up to ten of its file names.

Not affiliated with Anthropic or TypeSafe.

| Helper | What it does | Systems | |---|---|---| | context | At the end of each turn, suggests /compact or /clear when the conversation is large and the work has reached a stopping point. Shown at the end of Claude Code's bottom row. | Any | | rm | Asks before a Bash or PowerShell command deletes real files (rm, Remove-Item, del, rd, also inside sh -c, powershell -Command or cmd /c). Lets temp files through and refuses a delete whose targets it cannot work out. Jev can lift the ask for a test file this session made or a folder git ignores. | Windows |

Requirements

  • Node.js 18 or later
  • Claude Code (the bottom-row display and the advice button use Claude Code mods, an early-access feature that may change between releases)
  • A TypeSafe API key for the context helper and for the Jev check of the rm helper, in TYPESAFE_API_KEY or in a key file (--key-file). Without a key, rm asks about every real file.
  • Windows for the rm helper. On other systems install skips it and says why. It reads PowerShell commands with Windows PowerShell, which comes with Windows, or with PowerShell 7 when pwsh is on PATH, the same one Claude Code uses. It was checked with Windows PowerShell 5.1; PowerShell 7 was not tested.

Install

npm i -g @delt/claude-jev-advisor

Then register the hooks:

claude-jev-advisor install

When the context helper is installed and no key is found, install asks for your TypeSafe API key. What you type is hidden. It checks the key with one small Jev call and saves it to ~/.claude/claude-jev-advisor/jev-key.env. Press Enter to skip; claude-jev-advisor key asks again later. Instead of typing it, you can set TYPESAFE_API_KEY, or pass --key-file <path> to a file holding a line TYPESAFE_API_KEY=... (then only that path is saved). The key is never printed or logged. On Windows that file is protected by your user folder's permissions only.

Before it changes ~/.claude/settings.json, install copies it to ~/.claude/backups/settings.json.<YYYY-MM-DD-HHmmss>-before-claude-jev-advisor. If a backup from the same second already exists, it adds -2, -3 and so on instead of overwriting it. It then adds or replaces only this package's entries. Running it again with the same version changes nothing. With the mod display it also binds ctrl+x ctrl+f in ~/.claude/keybindings.json (see the context helper below), backing that file up the same way first.

After upgrading from 0.2 or earlier, run claude-jev-advisor install rm again so that the rm hook also covers the PowerShell tool. Until you do, status shows Bash only.

After upgrading from 0.3 or earlier, run claude-jev-advisor install context again so that it binds ctrl+x ctrl+f for the advice button. Until you do, status shows shortcut: none - run "claude-jev-advisor install context" ....

The hooks also reach Claude Code sessions that are already open. The bottom-row display and the advice button start with the next new session; sessions that already show the bottom-row display pick up an upgrade by themselves. Turning a helper on or off applies at once, even to open sessions.

Commands

| Command | What it does | |---|---| | claude-jev-advisor install [rm] [context] [--lang ko\|en] [--key-file <path>] [--display mod\|statusline\|message] | Registers the hooks (backs up settings.json first) and switches the helpers on | | claude-jev-advisor uninstall [rm] [context] | Removes this package's hooks and display from settings.json | | claude-jev-advisor on [rm] [context] / off [rm] [context] | Switches helpers on or off without touching settings.json | | claude-jev-advisor status | Shows what is registered and on, the display, the shortcut, whether a key is set, the thresholds and the last judgment | | claude-jev-advisor report [--days 7] | Lists the /compact and /clear advice shown and what followed it, and the deletions Jev let through | | claude-jev-advisor key | Asks for the TypeSafe API key, checks it and saves it (needs an interactive terminal) | | claude-jev-advisor help | Prints the usage |

If you leave out the helper names, the command applies to all helpers. The display is set up when context is installed; run claude-jev-advisor install context --display <mode> to switch it.

The context helper

When a turn ends, a Stop hook reads the size of the conversation from the session transcript. If the turn's last reply is not in the transcript yet, it waits up to 3 seconds for it. From 250k tokens it asks Jev two questions about the last three requests and the last reply:

  • has Claude finished or handed back the work asked for, so this is a natural break?
  • does the reply close a whole stage of the work (a plan carried out and pushed, a release, a finished investigation, a design or plan saved as a document), so the next stage can start from the saved results?

The answer is saved for the display. Nothing is added to what Claude sees, so it costs no Claude tokens. If Jev does not answer within 8 seconds, only the size is shown. While a subagent or a workflow runs in the background, the turn counts as work in progress and Jev is not asked; background shells and monitors do not count.

With the mod display (the default):

| Situation | Bottom row | Above the prompt | |---|---|---| | Under 250k, or no judgment (no key, Jev unreachable) | 52k +12k | | | Work in progress | 🟢 312k +38k | | | A whole stage closed (from 250k) | 312k +38k | 🟡 312k +38k 새롭게 시작하는 건 어떠세요? and a /clear button | | Work finished, stage goes on (from 250k) | 312k +38k | 🟡 312k +38k 지금까지 정리하고 이어가는 건 어떠세요? and a /compact button | | Within 20% of auto-compact, with one of the two above | 790k +38k | 🔴 790k +38k 18%, the advice and its button | | Within 20% of auto-compact otherwise | 🔴 790k +38k 18%, then · 작업이 끝나면 정리하고 이어가는 건 어떠세요? /compact while the work is still going | |

+38k is how much the conversation grew in the last request, counted from when it was sent. It is left out when the conversation did not grow, for example after a /compact. The band repeats the size so you need not look down for it while it is up; the bottom row keeps it too, so it never moves. The statusline and message displays show the whole advice on one line instead, without the increase: 🟡 312k 새롭게 시작하는 건 어떠세요? /clear and so on.

The button runs /compact or /clear at once; a /clear can be undone with /resume. Click it, press ctrl+x ctrl+f, or press ctrl+x tab and then Enter. It is not drawn while a request runs or while Claude Code waits for your answer to a question, and once pressed it stays away until Jev judges a newer reply. A refused /compact (too few messages, for example) shows the reason in a toast.

install writes the shortcut to ~/.claude/keybindings.json as "ctrl+x ctrl+f": "diff:back" in the DiffDialog block. Claude Code lets a mod's button take the key of one of its own actions while that action is not in use; diff:back has no key of its own and works only inside the diff dialog, where ctrl+x ctrl+f keeps doing that. If ctrl+x ctrl+f is already bound in your file, or the file cannot be read, install leaves the file alone and says so, and the button is pressed with a click or ctrl+x tab. Both keys are pressed with ctrl on purpose: with a Korean or other input method on, a plain letter after ctrl+x arrives as another character and the chord would not match. uninstall context and switching to another display take the line out again if it is still ours. To keep install from binding it, set "ctrl+x ctrl+f": null in any block of that file.

With --lang en the advice reads Start fresh? /clear, Wrap up what you have and continue? /compact and When this work is done, wrap up and continue? /compact.

Judging starts at 250k because a conversation passes 100k after a request or two, and compacting a small conversation costs more than it saves. If you set compactMinTokens above minTokens, finished work between the two stays green. The suggestion is hidden while a new request runs, and a judgment made before a /compact is dropped.

| --display | Where | |---|---| | mod (default) | At the end of the bottom row, after ⏵⏵ … mode on, and advice that can be acted on in a band above the prompt with a button. A small Claude Code mod in the package's mod/ folder draws both. The mod is listed in env.CLAUDE_CODE_PLUGIN_DIRS and told the data folder through pluginConfigs. | | statusline | Claude Code's status line, the row above the bottom row. An existing status line of yours keeps running first, with our text after it, and is put back when you switch away or uninstall. On Windows that command runs in Git Bash when it is installed and in PowerShell otherwise, as Claude Code runs it; it gets 2 seconds. No red zone, because the auto-compact threshold is not known there. | | message | A Stop says: … line in the transcript when there is advice. Claude does not see it. No red zone. |

With the mod display the band's advice is also written to advice/<session>.json in the data folder, as { "kind": "compact" | "clear" | null, "at": … }, when it changes. claude-alarm 1.9 or later reads it to highlight the matching /compact or /clear button on its dashboard. A session that never had advice gets no file.

claude-jev-advisor report shows each piece of advice with the time, the session, the size, Jev's answers, the start of the last request and what followed: compacted or cleared within the next three requests, auto-compacted, or kept going.

The rm helper

It runs before every Bash and PowerShell tool call (PreToolUse, matcher Bash|PowerShell, 15-second timeout) and looks at:

  • Bash: rm, rmdir and xargs
  • PowerShell: Remove-Item and its aliases ri, rm, del, erase, rd and rmdir, and [System.IO.File]::Delete and [System.IO.Directory]::Delete. PowerShell's own parser and parameter binder read the command, so aliases, shortened parameter names, positional paths and nested blocks count as PowerShell reads them. PowerShell is started only when the command holds one of these words or a shell name, and takes about 0.3 seconds.
  • shells started inside a command, up to three levels deep: sh -c and bash -c, powershell -Command, pwsh -c and -EncodedCommand, and del, erase, rd and rmdir in cmd /c

| Target | Result | |---|---| | Inside %TEMP%/%TMP% or /tmp | No decision. Claude Code's normal permission handling applies. | | A path with a .superpowers folder in it | No decision | | A path that does not exist | No decision | | A git-ignored path inside a build folder (target, build, dist, out, node_modules, coverage, __pycache__, .pytest_cache, .gradle, .next, .nuxt, .turbo, .cache, bin, obj) | No decision | | A PowerShell path on a drive that is not a file system (Env:, Alias:, Function:, Variable:, HKCU:, HKLM:, Cert:, WSMan:, Registry::) | No decision | | Remove-Item … -WhatIf | No decision | | A network path (\\server\share\…) | ask, without looking the path up | | Any other existing file or folder | ask, with the reason 실제 파일 삭제: <paths> ("deleting real files"), unless Jev lifts it (below) | | A PowerShell command its parser cannot read (a syntax error, PowerShell not answering within 3 seconds, a nested PowerShell command left when the hook has spent 9 seconds reading, an answer it does not expect), or one that deletes and runs code it cannot follow (& $name, Invoke-Expression, Start-Process or Set-Alias with an argument it cannot work out, [scriptblock]::Create, .Invoke(), a Delete() method in a command that gets file objects from Get-Item, Get-ChildItem, New-Item or -PassThru), or makes a drive with New-PSDrive | ask, with the reason 삭제 명령을 분석하지 못함: <start of the command> ("could not read the delete command"). Jev is not asked. | | A target it cannot work out | deny, with a hint to rewrite the command using literal paths |

A target cannot be worked out when it uses:

  • in Bash, shell variables other than literal assignments in the same command and TEMP, TMP, TMPDIR, HOME, USERPROFILE and PWD; in PowerShell, variables other than one plain top-level assignment in the same command (a variable written any other way, such as +=, a loop, a function parameter, Set-Variable, $script:, -OutVariable, or its name handed to a command as text, is unknown), $env:TEMP, $env:TMP, $env:TMPDIR, $env:HOME, $env:USERPROFILE, $HOME and $PWD (unless the command assigns it); in cmd, variables other than %TEMP%, %TMP%, %USERPROFILE% and %CD%
  • command substitution, or in PowerShell any expression such as (Join-Path …), $(…) or @splat
  • xargs feeding rm or a shell that deletes, PowerShell pipeline input feeding Remove-Item (Get-ChildItem … | Remove-Item), or a shell given no script of its own, which reads one from a pipe, a heredoc or a here-string (… | bash, bash <<EOF, powershell -), in a command that holds a delete word
  • brace expansion
  • a wildcard in a folder name
  • a cd, pushd, Set-Location or Push-Location to such a path earlier in the command, a popd or Pop-Location, or a location change inside a PowerShell block; in PowerShell also a relative path inside a loop, a function or a script block when the command changes location anywhere
  • a PowerShell drive other than a drive letter and the non-file drives above, such as one made with New-PSDrive
  • a nested shell whose script is not fixed text and holds a delete word, or shells nested more than three deep that delete
  • in cmd, a delete on a line that uses if, else, for, call, start or unquoted parentheses, or starts a command with a name it cannot read: write plain del or rd lines instead, with names that hold parentheses in double quotes

It does not see deletions made any other way:

  • in PowerShell, Remove-ItemProperty, Clear-RecycleBin, an object's Delete() in a command that gets no file objects, COM file objects (Scripting.FileSystemObject's DeleteFile and DeleteFolder), provider methods such as $ExecutionContext.InvokeProvider.Item.Remove, and code that builds a command's name or text from pieces while it runs ([char] codes, joined strings); the reader is not a sandbox
  • script files: powershell -File, pwsh script.ps1, bash script.sh, a .bat file
  • other commands or programs, such as find -delete, git clean, or Node or Python code that deletes files

What its decisions do depends on Claude Code's permission mode:

| Mode | ask | deny | No decision | |---|---|---|---| | auto | A prompt. The auto mode classifier can still block the call but cannot approve it on its own (Claude Code 2.1.211 or later). | Blocked | The classifier decides | | bypassPermissions | A prompt. Claude Code's documentation does not say this; it was seen in a test on 2026-10-03. | Blocked | Runs | | Other modes | A prompt (dontAsk refuses the call instead) | Blocked | Claude Code's normal permission handling |

When Jev can lift the ask

The facts are checked by code; Jev only judges what the target is for. Jev is asked only when every target of the command is one of these (at most five):

| Target | Checked first | Jev is asked | |---|---|---| | A file or folder this session made | Not tracked by git; the first call of this session that names it created it: a Write that made a new file, or a shell command whose > redirect, touch, mkdir or curl -o makes it (deletes do not count, and a Read, an Edit or any other shell command first means it was already there; PowerShell's New-Item, Set-Content and Out-File are not recognized yet, so a file made with them keeps the ask); a folder holding a git repository never counts; made after the session started; for a folder, every file inside too, and at most 50 files | Is it a throwaway made only to try something out? | | A folder git ignores, outside the build folders above | It is a folder (a single ignored file such as .env still asks) | Is it generated output or a cache that is made again? |

When Jev answers 0.8 or more for every target, the hook makes no decision (the last column of the table above), and a line like [jev-advisor] Jev가 이 세션의 시험 파일로 판단해 묻지 않고 지웁니다: out.json (0.93) is shown. Otherwise the ask stays, with Jev's answer added: 실제 파일 삭제: …\out.json · Jev: 시험용 파일일 확률 0.42. Without a key, when Jev fails, or with "jev": false, every real file asks as before. A deny is never sent to Jev.

install rm also replaces an older personal hook at ~/.claude/hooks/rm-guard/rm-guard.mjs if one is registered. Its files are left in place.

If a hook of this package fails in any way, it prints nothing and exits 0, so it never blocks Claude Code. A failure during the Jev check of rm leaves the ask in place.

Uninstall

npm does not run uninstall scripts, so remove the hooks before removing the package:

claude-jev-advisor uninstall
npm rm -g @delt/claude-jev-advisor

If the package is removed first, the hook entries point to a missing file. Claude Code keeps running, but the helpers are off. To clean up, reinstall the package and run claude-jev-advisor uninstall, or delete the entries from settings.json by hand.

A key saved by install or key stays in ~/.claude/claude-jev-advisor/jev-key.env; delete that file if you no longer need it.

Files

| Path | Contents | |---|---| | ~/.claude/claude-jev-advisor/config.json | Switches and settings that differ from the defaults. A missing or broken file reads as the defaults. A value of the wrong type falls back to its default, so only "enabled": false turns a helper off. | | ~/.claude/claude-jev-advisor/state/<session>.json | The last judgment of each open session, read by the display. Removed when the session ends. | | ~/.claude/claude-jev-advisor/advice/<session>.json | The advice the band shows (mod display), for claude-alarm's dashboard. Removed when the session ends. | | ~/.claude/claude-jev-advisor/log/YYYY-MM.jsonl | One line per context judgment and per rm Jev check: the size, or the tool (Bash or PowerShell) and the command, what was sent to Jev (parts of your conversation), the answers and the result. Never the key. | | ~/.claude/claude-jev-advisor/statusline-before.json | Your own status line while --display statusline is in use | | ~/.claude/claude-jev-advisor/jev-key.env | Your TypeSafe API key, when you typed it in install or key | | ~/.claude/backups/settings.json.*-before-claude-jev-advisor | Copies of settings.json from before each change | | ~/.claude/keybindings.json | The ctrl+x ctrl+f line, with the mod display | | ~/.claude/backups/keybindings.json.*-before-claude-jev-advisor | Copies of keybindings.json from before each change |

Defaults:

{
  "lang": "ko",
  "keyFile": null,
  "display": "mod",
  "shortcut": null,
  "context": { "enabled": true, "minTokens": 250000, "compactMinTokens": 250000, "redRemainingPct": 20, "unitDoneYes": 0.6, "phaseDoneYes": 0.6 },
  "rm": { "enabled": true, "jev": true, "throwawayYes": 0.8, "maxDirFiles": 50 }
}

minTokens is where judging starts, compactMinTokens where /compact is suggested, redRemainingPct where the red zone starts, and unitDoneYes / phaseDoneYes are the Jev probabilities needed for "work finished" (/compact) and "stage closed" (/clear). For rm, jev switches the Jev check, throwawayYes is the probability needed to lift an ask, and maxDirFiles the most files a folder of this session may hold. shortcut is set by install: the key it bound, or null when it bound none.

config.json keeps only the values you changed, with "version": 2. A config written by 0.1.x, which saved every value, has its old default thresholds (minTokens 100000, compactMinTokens 200000, unitDoneYes 0.7) read as unset, so the new defaults apply.

Development

git clone https://github.com/delt96/claude-jev-advisor.git
cd claude-jev-advisor
npm ci
npm test          # node:test via tsx; tests use temporary home folders and never call Jev
npm run typecheck
npm run build     # dist/*.js and mod/hooks/register.js

License

MIT