SLOPSHOPPER

nvim-title-state

nvim の内蔵ターミナルで動く Claude の状態を親 nvim のタブタイトルへ通知する

newguardprocess
★ 1v0.1.0no licenseupdated 2026-10-16void2610/dotfiles/.claude/mods/nvim-title-state
A shopper browsing a rack in a slop shop
README

dotfiles

個人用のdotfiles設定リポジトリです。 パッケージ管理と Homebrew 管理は別の nix-config リポジトリで行い、このリポジトリは主にシェルやアプリ設定を管理します。

セットアップ手順

1. リポジトリのクローン

git clone https://github.com/yourusername/dotfiles.git ~/dotfiles
cd ~/dotfiles

2. Nix / nix-darwin 設定の適用

cd ~/nix-config
darwin-rebuild switch --flake .#<nix-configで定義したホスト名>

3. dotfilesのシンボリックリンク作成

./install.sh

既存の設定ファイルは~/backupディレクトリにバックアップされます。

ファイル構成

  • install.sh: dotfilesのシンボリックリンク作成スクリプト
  • MANUAL_APPS.md: 手動インストールが必要なアプリケーション一覧
  • .config/: 各種アプリケーションの設定ファイル
  • .zshrc: Zshシェルの設定
  • .gitconfig: Git設定
  • .tmux.conf: tmux設定
  • .claude/: Claude Code の設定
  • .codex/: Codex の設定
Source 1 files
hooks/index.ts 50 lines
1import type { EngineInterface, Register } from "claude-code";
2
3type State = "working" | "waiting" | "done" | "none";
4
5async function send($: EngineInterface, state: State) {
6  // nvim の :terminal から起動された時だけ $NVIM に親のソケットが入る
7  const server = await $.env.get("NVIM");
8  if (!server) return;
9  // ターンの進行を nvim の応答待ちで止めないよう await しない
10  $.process
11    .run([
12      "nvim",
13      "--server",
14      server,
15      "--remote-expr",
16      `luaeval('ClaudeTitleState(_A)', '${state}')`,
17    ])
18    .catch(() => {});
19}
20
21export const register: Register = (on) => {
22  on("turn.start", async ($, e, next) => {
23    await send($, "working");
24    return next(e);
25  });
26
27  on("tool.check", async ($, e, next) => {
28    const result = await next(e);
29    // ask はモードの判定者へ回るため、auto モードでは分類器の判定中も一瞬 waiting になる
30    if (e.tool_use_id && result.decision === "ask") await send($, "waiting");
31    return result;
32  });
33
34  on("tool.call", async ($, e, next) => {
35    const result = await next(e);
36    await send($, "working");
37    return result;
38  });
39
40  on("turn.complete", async ($, e, next) => {
41    if (!e.agentId) await send($, "done");
42    return next(e);
43  });
44
45  on("session.end", async ($, e, next) => {
46    await send($, "none");
47    return next(e);
48  });
49};
50