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

@imenam/claude-session-tracker-mcp

v1.7.0

Published

MCP server letting a Claude Code agent publish its own status (running, done, waiting, error) to the Claude Session Watcher dashboard.

Readme

@imenam/claude-session-tracker-mcp

Publie l'état des sessions Claude Code — en cours, question en attente, terminé — dans le tableau de bord Claude Session Watcher.

Le cycle de vie est mesuré par des hooks, pas raconté par le modèle : un hook se déclenche toujours, un outil seulement si l'agent y pense. L'outil MCP ne lui laisse donc qu'une seule nuance, celle qu'aucun événement ne porte — « la question que je viens de poser attend une réponse ».

Features

  • Aucun identifiant à fournir. La session est résolue depuis le registre officiel de Claude Code (~/.claude/sessions/<pid>.json) : un agent ne peut pas publier sur la mauvaise session, et n'a rien à retenir.
  • Correct après un /clear. Le registre est relu à chaque appel, jamais mis en cache — un nouveau sessionId frappé dans le même process est pris en compte immédiatement.
  • Cycle de vie déterministe. Le binaire de hook publie « En cours », « Question en attente » et « Terminé » sur les événements Claude Code correspondants : le statut ne reste jamais figé parce que l'agent a oublié d'appeler un outil.
  • Le hook prime sur l'agent, sans règle à écrire : la dernière écriture gagne, et un hook se déclenche toujours là où un outil dépend du bon vouloir du modèle.
  • Inoffensif. Le hook sort toujours en code 0 et n'écrit jamais sur stdout : il ne peut ni bloquer une action de Claude Code, ni polluer le contexte de l'agent. Un Watcher éteint est un cas normal, pas une panne.
  • Mode lecture seule (READ_ONLY) filtrant l'outil d'écriture sur deux couches.

Installation

npx -y @imenam/claude-session-tracker-mcp

Prérequis : Node >= 20.6, et le Claude Session Watcher qui tourne (npm start). Son port n'a pas à être connu : le Watcher publie son adresse dans ~/.claude-session-watcher/endpoint.json à chaque démarrage, et le tracker l'y lit à chaque publication.

Pour vérifier que ce poste sait joindre le Watcher :

npx -y @imenam/claude-session-tracker-mcp --config-diag

La commande dit d'où vient l'adresse retenue et si quelqu'un répond au bout. Sortie 0 si tout va bien, 1 sinon. Il n'existe aucun port par défaut : sans adresse découverte ni surcharge explicite, rien n'est publié et l'erreur le dit — plutôt que d'envoyer les statuts dans le vide.

Depuis les sources

npm install
npm run build

MCP Configuration

Le suivi n'a d'intérêt que si toutes les sessions de la machine sont instrumentées — le Watcher les inventorie toutes. On enregistre donc le serveur en portée utilisateur plutôt que dans un dépôt particulier :

claude mcp add -s user claude-session-tracker -- npx -y @imenam/claude-session-tracker-mcp

Pour la portée projet, une commande écrit le .mcp.json du répertoire courant, en le créant si besoin :

npx -y @imenam/claude-session-tracker-mcp --claude-mcp-setup

Mêmes garanties que --claude-setup : fusion (les autres serveurs déclarés sont préservés), sauvegarde horodatée, idempotence, échec net sur un JSON illisible.

| Option | Effet | |---|---| | --dev | commande node <racine du package>/dist/src/index.js au lieu de npx | | --dry-run | affiche ce qui serait fait, sans rien écrire | | --watcher-url <url> | fige l'URL du Watcher (par défaut : découverte automatique) | | --read-only | ajoute READ_ONLY=1 : set_session_status masqué et refusé | | --mcp-file <fichier> | fichier cible (défaut : ./.mcp.json) | | --help | rappel de l'usage |

Ou, à la main, dans ~/.claude.json (portée utilisateur) ou .mcp.json (portée projet) :

{
  "mcpServers": {
    "claude-session-tracker": {
      "command": "npx",
      "args": ["-y", "@imenam/claude-session-tracker-mcp"]
    }
  }
}

Hooks

Le serveur MCP couvre ce que l'agent sait ; les hooks couvrent ce qui arrive. Sans eux, une session reste affichée « En cours » dès que l'agent oublie d'annoncer qu'il a fini.

npx -y @imenam/claude-session-tracker-mcp --claude-setup

Écrit les quatre hooks dans ~/.claude/settings.json, en préservant le reste du fichier. Idempotent : relancer la commande met à jour l'entrée existante au lieu d'en créer une seconde. Le fichier est sauvegardé (settings.json.backup-<horodatage>) avant réécriture, et un JSON illisible fait échouer la commande plutôt que d'être écrasé.

| Option | Effet | |---|---| | --dev | installe node <racine du package>/dist/src/hook.js au lieu de la commande npx | | --dry-run | affiche ce qui serait fait, sans rien écrire | | --settings <fichier> | fichier cible (défaut : ~/.claude/settings.json) | | --help | rappel de l'usage |

La commande ne touche que les hooks : l'enregistrement du serveur MCP reste claude mcp add.

Diagnostic

npx -y @imenam/claude-session-tracker-mcp --config-diag

Répond à la seule question qui décide de tout le reste : ce process saurait-il joindre le Watcher, maintenant ? Elle mérite une commande parce qu'elle ne se voit nulle part ailleurs — un hook qui échoue n'a le droit ni d'écrire sur stdout (réinjecté dans le contexte de l'agent) ni de sortir en erreur (cela bloquerait l'action observée) : il note et s'efface. La panne est donc structurellement muette côté session.

La sortie donne, dans l'ordre : la surcharge MCP_TRACKER_WATCHER_URL si elle existe — et d'où elle vient, un .env de copie de travail étant signalé comme tel puisqu'il n'existera pas sous npx —, le contenu du fichier de découverte, l'adresse finalement retenue, et le résultat d'un appel réel au Watcher. Sortie 0 s'il répond, 1 sinon. Lancée par npx, la commande s'exécute dans le même environnement que le serveur MCP : ce qu'elle voit est bien ce que lui verrait.

Équivalent manuel, à ajouter dans ~/.claude/settings.json :

{
  "hooks": {
    "UserPromptSubmit": [
      { "hooks": [{ "type": "command", "command": "npx -y -p @imenam/claude-session-tracker-mcp claude-session-tracker-hook" }] }
    ],
    "Notification": [
      { "hooks": [{ "type": "command", "command": "npx -y -p @imenam/claude-session-tracker-mcp claude-session-tracker-hook" }] }
    ],
    "Stop": [
      { "hooks": [{ "type": "command", "command": "npx -y -p @imenam/claude-session-tracker-mcp claude-session-tracker-hook" }] }
    ],
    "SessionEnd": [
      { "hooks": [{ "type": "command", "command": "npx -y -p @imenam/claude-session-tracker-mcp claude-session-tracker-hook" }] }
    ]
  }
}

En développement, remplacer la commande par node <chemin absolu>/dist/src/hook.js, ce qui évite la latence de résolution npx à chaque événement.

SessionEnd supprime la ligne d'affichage dans le Watcher. Il ne termine aucun process : l'événement survient après la fin de la session.

Qui publie quoi

| Origine | Statut publié | |---|---| | Hook UserPromptSubmit | En cours | | Hook Notification | Question en attente | | Hook Stop | Terminé | | Hook SessionEnd | (entrée supprimée) | | Outil set_session_status | Question en attente, ou retour à En cours |

Aucun arbitrage entre les deux : la dernière écriture gagne. Les hooks priment donc de fait, puisqu'ils se déclenchent toujours là où l'outil n'est appelé que si le modèle y pense.

Environment variables

| Variable | Required | Description | |---|---|---| | MCP_TRACKER_WATCHER_URL | Non | Fige l'URL du Watcher et court-circuite la découverte. Aucun défaut : sans elle, l'adresse vient de ~/.claude-session-watcher/endpoint.json, et si ce fichier manque, rien n'est publié et l'erreur le dit. Ne sert qu'à un Watcher que la découverte ne peut pas trouver — autre machine, tunnel. | | MCP_DATA_DIR | Non | Répertoire de persistance des logs. Défaut : <racine du package>/.claude-session-tracker-data. | | READ_ONLY | Non | 1, true ou yes : masque et refuse set_session_status. | | CLAUDE_PID | Auto | Injectée par Claude Code. Sert à localiser l'entrée de registre de la session. | | CLAUDE_CODE_SESSION_ID | Auto | Injectée par Claude Code. Repli si le registre est illisible. |

Un .env placé à la racine du package est chargé s'il existe. Les variables déjà définies dans l'environnement priment.

Available tools

| Tool | Description | |---|---| | set_session_status | Signale que la session attend une réponse humaine (waiting) ou qu'elle l'a reçue (answered → « En cours »). Aucun texte libre : le Watcher n'affiche qu'un badge, la question elle-même se lit dans l'interface de l'agent. Aucun autre état n'est exposé : le reste du cycle appartient aux hooks. Écriture. | | get_session_status | Relit le statut affiché et renvoie l'identité résolue de la session (session id, origine de la résolution, pid, cwd, URL du Watcher). Outil de diagnostic. |

Comment la session est identifiée

C'est la seule question difficile du projet, et elle a une réponse exacte plutôt qu'une heuristique.

Le registre ~/.claude/sessions/<pid>.json porte le sessionId courant de la session dont le pid est <pid>. C'est la source d'autorité qu'utilise aussi le Watcher, donc les deux côtés ne peuvent pas diverger. Tout le problème est de trouver le pid du process Claude Code qui nous a lancés.

Un hook n'a rien à résoudre : Claude Code lui fournit session_id sur stdin. Pour le serveur MCP, trois façons, essayées dans cet ordre :

  1. CLAUDE_PID — injecté par Claude Code dans l'environnement des enfants de l'outil shell et du binaire de hook. Mesuré : absent de l'environnement d'un serveur MCP. Essayé quand même, c'est gratuit.
  2. process.ppid — un serveur MCP stdio est un enfant direct de claude.exe : son parent est sa session, par définition. Aucune chaîne à remonter, aucune requête système, aucun code spécifique à la plateforme. C'est ce chemin qui porte le cas réel.
  3. Balayage du registre à la recherche de l'entrée dont le sessionId égale CLAUDE_CODE_SESSION_ID. Nécessaire quand un intermédiaire s'insère — typiquement npx, qui passe par un cmd.exe sous Windows, si bien que le parent n'est plus claude.exe.

Faute de quoi CLAUDE_CODE_SESSION_ID est employé tel quel, et à défaut une erreur explicite est levée — jamais de devinette.

Le pid trouvé est mémorisé (il est stable pour la durée de vie du process), mais le registre est relu à chaque appel. C'est ce qui rend la résolution correcte après un /clear, qui frappe un nouveau sessionId dans le même process : la variable d'environnement, capturée au démarrage du MCP, devient fausse, tandis que le registre est réécrit. CLAUDE_CODE_SESSION_ID n'arrive donc qu'en dernier recours, précisément parce que c'est la seule valeur qui puisse être périmée.

get_session_status renvoie le chemin effectivement emprunté (found via CLAUDE_PID / parent process / registry scan) : c'est le moyen le plus rapide de vérifier qu'on ne tourne pas sur le repli.

La clé d'échange avec le Watcher est le sessionId, jamais le pid : unique globalement, immunisé à la réutilisation de pid, et seule information dont disposent les hooks.

Data storage

Logs uniquement, dans <MCP_DATA_DIR>/logs/ : claude-session-tracker-mcp.log et claude-session-tracker-hook.log, avec rotation sur un unique .1 au-delà de 1 Mo. Aucune donnée métier n'est stockée localement — les statuts vivent dans le Watcher.

Notes

  • stdout est réservé au JSON-RPC. Tout log part sur stderr et dans le fichier ; console.log est détourné dès la première ligne du process.
  • Le délai de garde des appels HTTP est de 2 s. Un Watcher éteint ou figé produit une erreur immédiate et actionnable, jamais un agent bloqué.
  • src/version.ts est généré par scripts/generate-version.js et ne doit pas être édité. Une release = npm run release (:minor / :major pour les autres incréments) : bump de version, tag git, build via prepublishOnly, publication, puis git push --follow-tags. L'arbre de travail doit être propre, sinon npm version refuse de démarrer.
  • tsconfig.json déclare "types": ["node"] : TypeScript 7 n'inclut plus @types/node automatiquement.