/cmdHistory lists PowerShell (PSReadLine) history in a pane and puts the picked command in the prompt as a ! shell command.

Windows 環境の Claude Code dotfiles(hooks・skills・settings)を一元管理するリポジトリ。
claude/
install.ps1 インストーラ(CLAUDE.md・settings.json を ~/.claude に配置)
settings.template.json settings.json のテンプレート
mods/ Claude Code プラグイン(dotfiles-mods マーケットプレイス)
dotfiles/ 自作の skills・hooks をまとめた plugin
app-settings/ アプリ設定ファイルのバックアップ
tools/ 汎用 PowerShell ユーティリティ
app-settings/pwsh/Microsoft.PowerShell_profile.ps1 は基本ヘルパー・エイリアスと Update-Profile を持つローダーで、機能本体は app-settings/pwsh/profile.d/ に 分割しています(navigation / git / vs-build / integrations / ai-cli / devtools-catalog / devtools / extra-tools / windows-settings / psreadline / help)。 読み込み順は profile.d/manifest.txt が決めます。新しいファイルを足すときは profile.d/ に置いて manifest.txt に 1 行追加します。配置時はローダーと profile.d/ の両方が必要です。
profile は現在読み込んでいるプロファイルを編集し、reload は再読み込みします。 Update-Profile は GitHub の main からローダーと profile.d/ 一式を取得し、構文検証・ 上書き確認・バックアップ後に更新するため、未公開のローカル変更は反映しません。
コマンド一覧は phelp(例: phelp git)、検索は Ctrl+G で開けます。 gl、gp、gcm、cat は標準エイリアスを置き換え、それぞれ Git log、Git push、Git commit、bat 連携として動作します。 gco の引数なし実行は git-switch と同じブランチ選択を使います。 その他の既存の短縮名も維持しています。
検証は pwsh -NoProfile -File app-settings/pwsh/tests/Invoke-AllTests.ps1 で全テストファイルを一括実行します(個別実行は各 Test-*.ps1)。
DevDeck(ntaksh42/DevDeck)と RdpManager(ntaksh42/rdp-manager)は全端末には不要なため、 Install-DevTools のカタログには入れず、専用の Install-ExtraTools で導入します。 GitHub Releases の最新インストーラを取得して実行し、導入済みで最新なら何もしません。 古い場合は更新し、実行中のアプリは終了します。
Install-ExtraTools # DevDeck と RdpManager の両方
Install-ExtraTools -Name DevDeck # 指定したものだけ
Install-ExtraTools -Name RdpManager -Yes # 確認を省略
DevDeck は NSIS 版(ユーザー単位・無人)、RdpManager は MSI 版(マシン単位のため UAC が出ます)を使います。 対象を増やすときは profile.d/extra-tools.ps1 の $script:ExtraTools に 1 行足します。
PowerShell 7 / Git for Windows 向けの共有設定は app-settings/git/.gitconfig にあります。個人情報や署名鍵、認証 helper は 公開用の設定から分離し、~/.gitconfig.local で管理します。既存の設定が ある場合は、それをローカル設定として残してから共有設定を配置します。
# 既存の ~/.gitconfig がある場合(認証・ユーザー情報もそのまま保持)
Move-Item ~/.gitconfig ~/.gitconfig.local
Copy-Item app-settings/git/.gitconfig ~/.gitconfig
# Git を初めて設定する場合は、上の Move-Item の代わりにこちらを実行
Copy-Item app-settings/git/.gitconfig.local.example ~/.gitconfig.local
notepad ~/.gitconfig.local
delta が未導入の場合は Install-DevTools で導入できます。設定後は git config --global --list で読み込み結果を確認してください。
claude/settings.template.json の statusLine は npx -y ccstatusline@latest を呼び出します。ccstatusline はレイアウト設定を ~/.config/ccstatusline/settings.json から読み込みます。この設定は app-settings/ccstatusline/settings.json を管理元として Install-DevTools (remote-config バックエンド)が配置・更新します。
Install-DevTools
ccstatusline はTUI上での編集で設定ファイル自身を書き換えるため、 Install-DevTools は配置済みの設定と管理元の内容が異なる場合、差分を表示した 上で上書き可否を確認します(手元での編集を誤って消さないよう、この確認は -Force を付けても省略されません)。上書き確認も含めてすべての確認に「はい」と 答える場合は Install-DevTools -Yes を使います(差分表示とバックアップは行われます)。
Install-DevTools は ~/.agents/skills/ にだけあるスキルを ~/.claude/skills/ へ移し、 元の場所にシンボリックリンクを作ります。同名の既存スキルと SKILL.md のないディレクトリは変更しません。
配置後は Claude Code を再起動すると、モデル・コンテキスト使用率・git ブランチ・ セッション使用量などの構成が反映されます。
Install-DevTools は claude/mods/ の Mod(dotfiles、auto-session-title、toast-notify など)も導入します。 自作の skills と hooks は dotfiles plugin にまとめてあります(スキル名は dotfiles:<name>)。 dotfiles-mods マーケットプレイスが未登録なら GitHub の ntaksh42/dotfiles から登録し、 その後 claude plugin install を実行します。claude/install.ps1 がクローン先のパスで 登録済みの場合は、そのマーケットプレイスをそのまま使います。GitHub から登録する場合は、 Mod が main に取り込まれている必要があります。claude が PATH に無いとスキップされます。
現在は一時的に無効化中です。 Install-DevTools は Codex ステータスラインを インストールせず、導入済みの環境では %LOCALAPPDATA%\CodexStatusline\codex-wt.ps1 を codex-wt.ps1.disabled に退避します(codex は通常の Codex CLI を起動します)。 再び有効にするには、.disabled を元の名前に戻し、Install-DevTools のカタログと Disable-CodexStatusline の呼び出しを元に戻します。
有効だった頃は、下側 18% のペインにモデル、推論強度、コンテキスト、git 状態、 セッション/週次の使用量を表示していました。tools/Install-CodexStatusline.ps1 と app-settings/codex-statusline/ は再開用に残してあります。
Install-DevTools は Crit 本体と Codex 連携もインストールします。インストール時に ~/.crit.config.json の既存項目を維持しつつ、社内利用向けの安全設定として ローカルホスト限定、更新確認の無効化、Share の無効化、agent_cmd の無効化を設定します。
{
"host": "127.0.0.1",
"no_update_check": true,
"share_url": "",
"share_targets": [],
"agent_cmd": ""
}
git clone https://github.com/ntaksh42/env.git
cd env
powershell.exe -ExecutionPolicy Bypass -File claude\install.ps1
インストーラが行うこと:
claude/CLAUDE.global.md を ~/.claude/CLAUDE.md にコピーsettings.template.json からパスを解決して ~/.claude/settings.json を生成Install-DevTools
skills・hooks・Mod を claude plugin install で導入します。
設定を反映するために Claude Code を再起動してください。
%LOCALAPPDATA%\Microsoft\WinGet\Links\ に以下のツールをインストール済みです。
jq v1.8.1: JSON プロセッサ。API レスポンスや設定ファイルの前処理でトークン消費を大きく抑えられます。rg (ripgrep) v15.1.0: .gitignore を自動除外する高速 grep。--json 出力に対応し、多くの AI エージェントと相性が良いです。yq v4.53.2: YAML / TOML / XML プロセッサ。jq 風構文で K8s や CI 設定を処理できます。app-settings/ の設定ファイルは Install-DevTools が GitHub の main から配置します (プロファイルは Update-Profile)。実環境で変えた設定は、手でリポジトリへコピーして取り込みます。
# Windows 設定(レジストリ)を適用 (pwsh プロファイル経由)。HKLM 項目は管理者権限が必要
Set-WindowsSettings -Check # 差分のみ表示
Set-WindowsSettings # 適用
Install-DevTools は Orca 本体も winget(StablyAI.Orca)でインストールします。 導入済みの場合はスキップします。
app-settings/orca/keybindings.json は Install-DevTools が ~/.orca/keybindings.json へ配置します。 外観・エディタ・ターミナル設定の控えは app-settings/orca/settings.json にあります。 JSON の自動読み込みには対応していないため、app-settings/orca/README.md を参照してください。
Install-DevTools は Dockyard の最新リリース(MSIX)も インストール・更新します(tools/Install-Dockyard.ps1)。ARM64 の PC でも x64 版を入れます。 署名証明書が未信頼の場合は Cert:\LocalMachine\TrustedPeople へ登録するため UAC の確認が出ます。 x64 版の .NET 10 Desktop Runtime が無ければ winget で入れます(ARM64 の PC では dotnet\x64 に入ります)。
hooks/register.tsx 107 lines1import { atom, read, update } from 'claude-code'
2import type { EngineInterface, Register } from 'claude-code'
3
4const PANE = 'cmd-history'
5const MAX_ENTRIES = 3000
6const entries = atom({ plugin: 'cmdHistory', key: 'entries' } as const, [])
7const filter = atom({ plugin: 'cmdHistory', key: 'filter' } as const, '')
8
9// PSReadLine の履歴ファイルを新しい順・重複なしの項目にする。複数行の項目は最終行以外の行末がバッククォート
10export const parseHistory = (text: string) => {
11 const items: string[] = []
12 let pending: string[] = []
13 for (const line of text.split(/\r?\n/)) {
14 if (line.endsWith('`')) {
15 pending.push(line.slice(0, -1))
16 continue
17 }
18 const item = [...pending, line].join('\n').trim()
19 pending = []
20 if (item !== '') items.push(item)
21 }
22 return [...new Set(items.reverse())].slice(0, MAX_ENTRIES)
23}
24
25// 空白区切りの語をすべて含む項目(大文字小文字は区別しない)
26export const matches = (list: readonly string[], query: string) => {
27 const words = query.toLowerCase().split(/\s+/).filter(Boolean)
28 return list.filter(item => words.every(w => item.toLowerCase().includes(w)))
29}
30
31const loadHistory = async ($: EngineInterface) => {
32 const appData = await $.env.get('APPDATA')
33 if (appData === undefined) return []
34 const path = `${appData}/Microsoft/Windows/PowerShell/PSReadLine/ConsoleHost_history.txt`
35 if (!(await $.fs.exists(path))) return []
36 return parseHistory(await $.fs.read(path))
37}
38
39// ペインを閉じてから入力欄に入れる(ペインがキーを持っている間は入力欄が受け付けない)
40const pick = async ($: EngineInterface, command: string) => {
41 await $.ui.close({ id: PANE })
42 const filled = await $.prompt.fill({ text: `!${command}` })
43 if (!filled.isFilled) $.ui.toast('cmdHistory: 入力欄に入れられませんでした')
44}
45
46export const register: Register = on => {
47 on('session.start', async ($, e, next) => {
48 await $.command.register({
49 name: 'cmdHistory',
50 description: 'PowerShell の履歴から選んで ! コマンドとして入力欄に入れる',
51 argumentHint: '[絞り込む語]',
52 })
53 return next(e)
54 })
55
56 on('command.run', { command: 'cmdHistory' }, async ($, e) => {
57 await update($, entries, () => [])
58 await update($, filter, () => e.args.trim())
59 const list = await loadHistory($)
60 if (list.length === 0) return { text: 'PowerShell の履歴が見つかりませんでした。' }
61 await update($, entries, () => list)
62 await $.ui.open({ id: PANE, title: 'PowerShell history', focus: true, closeOnEscape: true, rows: 16 })
63 return {}
64 })
65
66 on('ui.render', { component: 'Pane', requestId: PANE }, async ($, e) => {
67 // mobile には Input がない
68 if (e.surface === 'mobile') {
69 const { Text } = $.ui.resolve(e)
70 return <Text dimColor>端末で開いてください</Text>
71 }
72 const { Box, Text, Input, Button } = $.ui.resolve(e)
73 const query = await read($, filter)
74 const hits = matches(await read($, entries), query)
75 const room = Math.max(1, (e.props.scroll?.bodyRows ?? 16) - 2)
76 const width = Math.max(10, (e.props.bodyColumns ?? 80) - 2)
77 const label = (item: string) => {
78 const one = item.replace(/\n/g, ' ⏎ ')
79 return one.length > width ? `${one.slice(0, width - 1)}…` : one
80 }
81
82 return (
83 <Box flexDirection="column">
84 <Input
85 key="filter"
86 label="> "
87 placeholder="絞り込む語(空白区切り)"
88 value={query}
89 submitLabel="先頭を選ぶ"
90 autoFocus
91 onInput={(value: string) => void update($, filter, () => value)}
92 onSubmit={() => {
93 if (hits[0] !== undefined) void pick($, hits[0])
94 }}
95 />
96 {hits.length === 0 && <Text dimColor>一致する履歴がありません</Text>}
97 {hits.slice(0, room).map((item, i) => (
98 <Button key={`row:${i}`} plain onPress={() => void pick($, item)}>
99 {label(item)}
100 </Button>
101 ))}
102 {hits.length > room && <Text dimColor>ほか {hits.length - room} 件</Text>}
103 </Box>
104 )
105 })
106}
107types/index.d.ts 9 lines1// 新しい順・重複なしの PowerShell 履歴と、ペインの絞り込み語
2export type CmdHistoryEntries = string[]
3
4declare module 'claude-code' {
5 interface PluginState {
6 'cmdHistory': { entries: CmdHistoryEntries; filter: string }
7 }
8}
9