SLOPSHOPPER

toggle-color

プロンプト上の帯に色付きのストライプを表示し、ボタンを押すたびに色を切り替える。複数のターミナルやペインを見分けるための MOD

newbandrowscommand
v0.1.0MITupdated 2026-10-15stakiran/toggle-color
A shopper browsing a rack in a slop shop
Preview · a replayed session in a sandbox
claude · ~/work/app · toggle-color
› fix the failing auth test and add an audit log call ⏺ Read(src/auth.ts) ⎿ Read 6 lines ⏺ Update(src/auth.ts) ⎿ Added 2 lines, removed 1 line ⏺ Bash(bun test) ⎿ 3 pass, 1 fail ⟨Claude Code's own drawing⟩ ✻ Worked for 42s · done 4:20 PM › /toggle-color ⎿ toggle-color: 色: blue ⟨Claude Code's own drawing⟩ color ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── › ? for shortcuts

Draws

Band
⟨Claude Code's own drawing⟩ color
Claude's reply
⟨Claude Code's own drawing⟩
README

toggle-color

<img width="718" height="395" alt="Image" src="https://github.com/user-attachments/assets/dab554cf-74a4-4494-b5a9-654f768cd5de" />

プロンプトの上の帯に色付きのストライプを表示し、ボタンを押すたびに色を切り替える Claude Code MOD。色がある間は、会話の中の Claude の回答の左にも同じ色の縦線が付きます。

複数のターミナルやペインで Claude Code を開いているときに、どれがどれか一目で見分けるための道具です。

使い方

  • 帯の color ボタンを押すたびに、色が blue → green → yellow → magenta → cyan → red → none の順に切り替わります。
  • スラッシュコマンドでも操作できます。
  • /toggle-color 次の色へ
  • /toggle-color blue その色に(blue, green, yellow, magenta, cyan, red)
  • /toggle-color none 色を消す
  • 色はセッションの中だけで持ちます。Claude Code を終了すると消え、次回は none から始まります。
  • 「このペインは青」のような記憶はあえてしていません。MOD の保存領域は全セッション共有なので、記憶すると開いたペイン全部が同じ色で起動してしまい、見分けるという目的に反するためです。

仕組み

  • MOD だけで完結しており、ターミナルの背景色などは一切触りません。ターミナル非依存です。
  • 他の MOD が同じ帯に描いたもの(たとえば open-latest のボタン)は同じ行の左側に残り、その右にボタンとストライプが並びます。
  • 帯の並び順は MOD の読み込み順で決まります。他の MOD が toggle-color より先に読み込まれた場合は、縦に 2 行並ぶことがあります。
  • 縦線は Claude の回答ブロックに付きます。ペインを切り替えるとき画面は回答で終わっていることが多いので、回答側に色を付けています。本文は 1 桁右にずれます。
  • アンケート(survey)が帯を使っている間は表示を譲ります。

必要なもの

  • ターミナル版の Claude Code(帯はターミナルとデスクトップアプリで描かれます)

インストール

ターミナル版 Claude Code のプロンプトで:

/plugin install toggle-color --marketplace stakiran/toggle-color

シェルから:

claude plugin install toggle-color --marketplace stakiran/toggle-color

アンインストールは /plugin メニューから。

インストールせずに試す

このリポジトリを clone して:

claude --plugin-dir ./toggle-color

そのセッションだけ MOD が読み込まれます。

開発

claude plugin validate .
claude plugin test .

License

MIT

Source 1 files
hooks/register.js 110 lines
1// 色の候補。先頭は「色なし」。押すたびにこの順で巡回する
2// ライト/ダークどちらのテーマでも目に刺さらないよう、彩度を少し落とした色
3const COLORS = [
4  { name: 'none', color: null },
5  { name: 'blue', color: '#4A7BD0' },
6  { name: 'green', color: '#3E9E5B' },
7  { name: 'yellow', color: '#C9A227' },
8  { name: 'magenta', color: '#B569C8' },
9  { name: 'cyan', color: '#3AA6B9' },
10  { name: 'red', color: '#D05A5A' },
11]
12
13// 現在の色。セッション内だけで持ち、終了すれば消える(あえて記憶しない)
14let index = 0
15
16function setIndex($, next) {
17  index = next
18  // 帯も会話の各行も描き直す
19  $.ui.invalidate('ui.render')
20}
21
22function cycle($) {
23  setIndex($, (index + 1) % COLORS.length)
24}
25
26export function register(on) {
27  on('session.start', async ($, e, next) => {
28    await $.command.register({
29      name: 'toggle-color',
30      description: '帯の色を切り替える。/toggle-color <色名> で直接指定、none で消す',
31    })
32    return next(e)
33  })
34
35  // /toggle-color        → 次の色へ
36  // /toggle-color blue   → その色に
37  // /toggle-color none   → 色なしに
38  on('command.run', { command: 'toggle-color' }, async ($, e) => {
39    const arg = e.args.trim().toLowerCase()
40    if (arg === '') {
41      cycle($)
42    } else {
43      const found = COLORS.findIndex(c => c.name === arg)
44      if (found < 0) {
45        return { text: `不明な色: ${arg}。使える色: ${COLORS.map(c => c.name).join(', ')}` }
46      }
47      setIndex($, found)
48    }
49    return { text: `色: ${COLORS[index].name}` }
50  })
51
52  // プロンプト上の帯に、トグルボタンと色付きのストライプを描く
53  on('ui.render', { component: 'AbovePrompt' }, async ($, e, next) => {
54    // 他の mod が帯に描いたもの(open-latest のボタンなど)は同じ行の左側に残す
55    const others = await next(e)
56    // アンケートが帯を使っている間は譲る
57    if (e.props.hasSurvey) return others
58
59    const { Box, Text, Button } = $.ui.resolve(e)
60    const { color } = COLORS[index]
61
62    // ラベルは固定の "color" だけにする(色名を入れると幅が変わって並びがずれる)
63    const button = Button({
64      key: 'toggle-color',
65      label: 'color',
66      plain: true,
67      dimColor: true,
68      onPress: () => cycle($),
69    })
70
71    // 他 mod の描画とボタンは縮ませない(ストライプが余白を食ってずれていた)
72    // 他 mod の描画との間は 2 桁あける(columnGap は入れ子の Box との間で効かなかった)
73    const children = [Box({ flexShrink: 0, marginLeft: others ? 2 : 0, children: [button] })]
74    if (others) children.unshift(Box({ flexShrink: 0, children: [others] }))
75    if (color) {
76      // ボタンの右側を帯の端まで塗りつぶす。残り幅いっぱいに伸び、はみ出す分は隠す
77      children.push(
78        Box({
79          flexGrow: 1,
80          flexShrink: 1,
81          overflow: 'hidden',
82          marginLeft: 1,
83          backgroundColor: color,
84          children: [Text({ backgroundColor: color, wrap: 'truncate-end', children: ' ' })],
85        }),
86      )
87    }
88
89    return Box({ flexDirection: 'row', children })
90  })
91
92  // 会話の中の Claude の回答ブロックの左に、色付きの縦線を付ける
93  // (ペインを切り替えるとき、画面は回答で終わっていることが多いので、回答側に色を付ける)
94  on('ui.render', { component: 'AssistantMessage' }, async ($, e, next) => {
95    const row = await next(e)
96    const { color } = COLORS[index]
97    if (!color || !row) return row
98
99    const { Box } = $.ui.resolve(e)
100    // 幅 1 桁の Box に背景色を付ける。行方向の Box の子は高さが揃うので、回答の全行にわたる
101    return Box({
102      flexDirection: 'row',
103      children: [
104        Box({ width: 1, flexShrink: 0, backgroundColor: color }),
105        Box({ flexGrow: 1, children: [row] }),
106      ],
107    })
108  })
109}
110