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

matan-bridge

v0.1.33

Published

まーたんコンパニオン — ローカルブリッジサーバー。Claude Code CLIとブラウザUIを接続します。

Readme

matan-bridge

まーたんWebコンパニオンのローカルブリッジサーバー。 ブラウザとClaude Code CLIの間を中継し、リアルタイム会話・TTS音声合成を提供する。

クイックスタート

npx matan-bridge

初回実行時にClaude Code CLIのインストール確認・ログイン確認・~/matan-home/のセットアップが自動で行われる。

アーキテクチャ

ブラウザ (matan.app / localhost:5174)
    │
    │ WebSocket (port 17619)
    ▼
matan-bridge (Express + WebSocket)
    ├── /health          ... ヘルスチェック
    ├── /api/tts         ... Fish Audio TTSプロキシ(ローカル開発用)
    └── WebSocket
         ├── chat:send   ... ユーザーメッセージ → Claude CLI
         ├── matan:speech ... まーたんの応答(ストリーミング)
         └── matan:stream-end ... 応答完了
              │
              │ stdin/stdout (NDJSON)
              ▼
         Claude Code CLI (--print --input-format stream-json)
              CWD: ~/matan-home/

開発セットアップ

cd matan-bridge
npm install

環境変数

.env ファイルを作成:

# Fish Audio TTS(音声合成に必要)
FISH_AUDIO_API_KEY=your_api_key
FISH_AUDIO_MODEL_ID=your_model_id

起動

# 開発(ホットリロード)
npm run dev

# 本番
npm start

初回起動時にClaude CLIの永続プロセスが起動する(約25秒)。 2回目以降のメッセージは5-8秒で応答。

~/matan-home/

Claude CLIのCWD。初回起動時に自動作成される。 ~/matan-home/CLAUDE.md にまーたんのペルソナが定義される。

~/matan-home/cheer/ (v4)

cheer-generator (応援メッセージ生成用 Claude CLI 子プロセス) の CWD。 Claude Code のCLAUDE.md 階層読み込みで ~/matan-home/CLAUDE.md が自動注入される。

Cheer v4 設計

応援メッセージ機能は v4 で抜本リファクタされた。詳細設計は ai-vtuber-context-cheer/docs/designs/cheer-2channel-design-v4.md 参照。

主要変更点

  • 立ち位置: Claude 応援団 → 作業者(Claude/ユーザー)を横から見守る第三者
  • トリガー(CH1): session_start / assistant_done連打 削除 → user_input + 2分CDハイブリッド
  • トリガー(CH2): 新設。jsonl監視ベースの 4状態遷移(IDLE/WORKING/NEEDS_ATTENTION/COMPLETED)
  • 文脈: 30分循環バッファ → 5分スライディング窓 + compaction summary(1500字clip) + Supabase story_event_logs の3層注入
  • チャンネル: 旧 cheer:set-modechannel:toggle で CH1/CH2 個別ON/OFF
  • プロンプト: B9プロンプト v3(XMLタグ/反応多軸化/観察→褒め連結/物語touch厳格化/固有名排除)
  • 生成(CH1): 50/50 AI/テンプレ → AI100%, 失敗時のみfallbackテンプレ11行
  • 生成(CH2): 速度優先でテンプレ主体(completed 5行 + permission 4行、AI生成なし)

Phase 4 アーキテクチャ(God Class 分割後)

v4 初期実装の CheerMonitor は責務10個を抱えた God Class だったため、 Phase 4 で以下の4コンポーネントに分離した。各コンポーネントは単一責任で独立テスト可能。

CheerMonitor (router / bootstrap / session exclude, 薄い facade)
  ├─ ContextCollector  — 3層文脈集約
  │    ├─ SlidingWindowBuffer (短期: 5分)
  │    ├─ latestCompactionSummary (中期: 1500字 clip)
  │    └─ StoryEventsLoader (長期: Supabase + TTL 5分キャッシュ)
  ├─ CheerFirer       — CH1 発火(AI 生成 + fallback + 2分CD + mutex + 履歴)
  │    └─ CheerGenerator (Claude CLI 永続プロセス、--tools "" で安全サンドボックス)
  └─ NotifyFirer      — CH2 発火(state machine + 5秒 timeout scan)
       └─ ChannelStateMachine (4状態 + TOOL_TIMEOUT_MS)

Shared utility:
  JsonlParser (static) — parseTimestamp / extractUserText / extractAssistant
                          / hasToolResult / isCompactionSummary

CheerMonitor は以下の薄い責務だけ残す:

  • preloadContext: 起動時に既存 jsonl(直近5分)を ContextCollector に注入
  • onJsonlEvent: chokidar から届く jsonl 行を各コンポーネントに配信
  • isMatanSession: matan-home 配下のセッションを除外(無限ループ防止)
  • purgeTimer: 1時間毎の stale state 掃除

グローバル汚染ゼロ原則

cheer 状態検出は ~/.claude/projects/*/*.jsonl の読み取り監視のみ。 ~/.claude/settings.json<project>/.claude/settings.json への書き込みは一切行わない。 先人 OSS (c9watch, claude-watch-status) の jsonl 監視アプローチに準拠。

CH2 (完了通知)

Phase 2 で実装済み。ChannelStateMachine がプロジェクト単位で以下 4 状態を管理する:

| 状態 | 遷移条件 | |---|---| | IDLE | 起動直後(never touched) | | WORKING | user_input 検知 or tool_use 検知 | | NEEDS_ATTENTION | tool_use から TOOL_TIMEOUT_MS 経過しても tool_result なし | | COMPLETED | assistant stop_reason='end_turn' |

TOOL_TIMEOUT_MS マップ

| ツール | timeout | |---|---| | TodoWrite | 5s | | Read / Write / Edit / Bash / Glob / Grep | 10s | | WebSearch / WebFetch | 60s | | Task | 3min | | (未登録ツール) | 30s (DEFAULT) |

発火ルール

  • WORKING → COMPLETED 遷移で 'completed' 通知(fx_lv=1)
  • WORKING → NEEDS_ATTENTION 遷移で 'permission' 通知(fx_lv=2)
  • NOTIFY_COOLDOWN_MS = 3分 — 同一プロジェクトの連続通知抑止(初回は即許可)
  • 優先度: 同一 batch で notify + cheer の発火候補がある場合は notify 優先、cheer は skip
  • notifyTimer 5秒間隔で runTimeoutScancheckTimeouts() → permission 通知

通知の主語

CH2 の全通知文は 「claudeが」 を主語として固定。 作業者(Claude)の状態を第三者が観察して告げる体裁。

通知テンプレ(抜粋)

  • completed: claudeが仕事終わらせたぞ、見てみろよ / claudeが返事してるぞ、{nickname}の番だ
  • permission: claudeが止まってるな、許可してやれよ / claudeが固まってるぞ、{nickname}の一押しが必要だ

長期コンテキスト (Phase 3: story_event_logs Supabase 実接続)

B9 プロンプトの <long_term_user_context> に注入する StoryEvent[] は StoryEventsLoader が Supabase story_event_logs テーブルから動的に取得する。

| 要素 | 内容 | |---|---| | テーブル | public.story_event_logs(RLS有効) | | カラム | user_id / event_level / conversation jsonb / summary / created_at | | 取得パス | /rest/v1/story_event_logs?select=...&order=created_at.desc&limit=5 | | キャッシュ | TTL 5分 (同一ユーザーなら 5分間は fetch を再実行しない) | | 認証 | auth:token 受信時に setAuth(userId) を bridge 側が呼び出し | | ユーザー切替 | setAuth で userId 変化を検知 → キャッシュ自動破棄 |

Fallback 動作

以下いずれの場合も STORY_EVENTS_STUB (5件の開発用固定値) に自動フォールバックする:

  • 未認証(auth:token 未送信 / 未検証)
  • Supabase fetch エラー (5xx / network error)
  • fetch 401 (トークン期限切れ)
  • レスポンスが空配列(ユーザーに story_event_logs 未蓄積)

長期コンテキスト欠落で B9 プロンプトの物語 touch が空になる事態を防ぐことが目的。 実ユーザーに story_event_logs が蓄積されるまでは stub で B9 の品質を担保する。

DB 行 → StoryEvent 変換ルール

event_level  → level
created_at   → createdAt (YYYY-MM-DD に丸め)
summary      → summary (null なら conversation.topic、両方空なら "LvX の物語")

web-companion との接続

  1. matan-bridge を起動(port 17619)
  2. web-companion を起動(npm run dev、port 5173/5174)
  3. Vite が /api/tts と WebSocket を自動的に matan-bridge にプロキシ
  4. ブラウザで http://localhost:5174/ を開く