diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..65b188e --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,70 @@ +# chktime + +Claude Code の会話ログ(`~/.claude/projects/<プロジェクト>/<セッションID>.jsonl`)を解析して、 +タスクごとのやりとりの時刻を表示するローカル Web アプリ。使い方は [README.md](README.md) に書いてある。 + +## 構成 + +``` +chktime.py サーバ + jsonl 解析(これ1本で完結) +web/index.html 画面の骨組み +web/app.js 表示ロジック(フレームワークなし・素の DOM 操作) +web/style.css スタイル(ダークテーマ固定) +run.bat コンソール表示で起動 +stop.cmd 起動中の chktime を終了 +``` + +`chktime.py` の中身は上から「解析ロジック → Store(キャッシュ)/ Watcher(更新検出)→ HTTP」の順。 + +## 守ること + +- **標準ライブラリのみ**。外部パッケージも CDN も使わない。ブラウザ側もフレームワークなし。 +- **外部通信しない**。読むのはローカルの jsonl だけ。 +- 会話ログは**読み取り専用**。検証で書き換えるときはスクラッチパッドにコピーしてから行う。 +- `.bat` / `.cmd` は cmd の既定コードページで読まれるので**中身は ASCII のみ**(日本語を書かない)。 +- コメント・コミットメッセージ・UI の文言は日本語。 +- 機能を足したら README.md も更新する。 + +## 動かす + +```bash +python chktime.py --port 8799 --no-browser +``` + +ユーザーは 8787 でデスクトップショートカットから常用しているので、**検証は 8799 など別ポート**で立てる。 +停止は `stop.cmd`(ただし `chktime.py` を実行中の python/pythonw を**すべて**終了するので、 +検証用だけを止めたいときはコマンドラインでポートを見て個別に kill する)。 + +## API + +| ルート | 内容 | +| --- | --- | +| `/api/projects` | プロジェクト一覧 | +| `/api/sessions?project=` | そのプロジェクトのタスク一覧 | +| `/api/all` | 全プロジェクトのタスク一覧(横断モード) | +| `/api/session?project=&id=` | 1タスクのターン一覧 | +| `/api/daily?project=&days=&from=&to=&exclude=` | 日別集計 | +| `/api/timeline?project=&days=` | ガント(タスク単位)。ターン単位は `/api/session` から描く | +| `/api/watch` | SSE。ログが変わったら `change` を流す | +| `/api/rev` `/api/reload` | 現在の版 / キャッシュ破棄 | + +いずれも `&format=csv` を付けると CSV を返す(Excel 用に BOM 付き)。 + +## 解析の前提 + +- ターンの起点は**人間の発言だけ**。ツール実行結果・システム挿入・サブエージェント(`isSidechain`)は起点にしない。 +- 再開時に書かれるメタ行(attachment / system / mode / queue-operation)は**ターンの所要時間に数えない**。 + セッション全体の開始・終了時刻には反映する。 +- `tool_result` を含む行は巨大なので JSON パースせず、正規表現で `timestamp` だけ拾う。 +- 解析結果は `(mtime, size)` でキャッシュし、追記されただけのファイルは**増えたぶんだけ**読み足す + (`SessionParser.read()`)。書きかけの行は消費せず次回に回す。先頭と解析済み末尾のバイト列が + 変わっていたら書き換えとみなして頭から読み直す。 +- 追記解析は状態を持つので、同じファイルを複数スレッドで同時に解析しない(`Entry.lock`)。 + +## 画面 + +- 3ペイン(プロジェクト / タスク一覧 / 詳細)。右ペインは **やりとり・日別集計・ガント**のタブ。 +- 状態はすべて `app.js` 冒頭の `state` オブジェクト。再描画は `render*()` が `#detail-body` を作り直す方式。 +- 自動追従(SSE)で作り直すときも、選択・スクロール位置・絞り込み・タブは保つ(`refreshFollow()`)。 +- ガントの軸・背景・枠組みは `timeScale` / `axisSvg` / `gridSvg` / `ganttFrame` をタスク単位と + ターン単位で共有している。