From 3e060e899f7b86e499593eb14b6cd761a5baab8b Mon Sep 17 00:00:00 2001 From: tim-watcha Date: Sat, 6 Dec 2025 15:06:17 +0900 Subject: [PATCH 1/3] Add Git Root Dir widget MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a new widget that displays the git repository root directory name. - Shows directory name with 📁 icon (e.g., "📁 my-repo") - Supports rawValue option for icon-free display - Supports hideNoGit option to hide message when not in a git repo 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- bun.lock | 1 + src/utils/widgets.ts | 1 + src/widgets/GitRootDir.ts | 80 +++++++++++++++++++++++++++++++++++++++ src/widgets/index.ts | 1 + 4 files changed, 83 insertions(+) create mode 100644 src/widgets/GitRootDir.ts diff --git a/bun.lock b/bun.lock index bdc89ca..32c3593 100644 --- a/bun.lock +++ b/bun.lock @@ -1,5 +1,6 @@ { "lockfileVersion": 1, + "configVersion": 0, "workspaces": { "": { "name": "ccstatusline", diff --git a/src/utils/widgets.ts b/src/utils/widgets.ts index 15a2510..a31793a 100644 --- a/src/utils/widgets.ts +++ b/src/utils/widgets.ts @@ -11,6 +11,7 @@ const widgetRegistry = new Map([ ['output-style', new widgets.OutputStyleWidget()], ['git-branch', new widgets.GitBranchWidget()], ['git-changes', new widgets.GitChangesWidget()], + ['git-root-dir', new widgets.GitRootDirWidget()], ['git-worktree', new widgets.GitWorktreeWidget()], ['current-working-dir', new widgets.CurrentWorkingDirWidget()], ['tokens-input', new widgets.TokensInputWidget()], diff --git a/src/widgets/GitRootDir.ts b/src/widgets/GitRootDir.ts new file mode 100644 index 0000000..56e35b9 --- /dev/null +++ b/src/widgets/GitRootDir.ts @@ -0,0 +1,80 @@ +import { execSync } from 'child_process'; + +import type { RenderContext } from '../types/RenderContext'; +import type { Settings } from '../types/Settings'; +import type { + CustomKeybind, + Widget, + WidgetEditorDisplay, + WidgetItem +} from '../types/Widget'; + +export class GitRootDirWidget implements Widget { + getDefaultColor(): string { return 'cyan'; } + getDescription(): string { return 'Shows the git repository root directory name'; } + getDisplayName(): string { return 'Git Root Dir'; } + getEditorDisplay(item: WidgetItem): WidgetEditorDisplay { + const hideNoGit = item.metadata?.hideNoGit === 'true'; + const modifiers: string[] = []; + + if (hideNoGit) { + modifiers.push('hide \'no git\''); + } + + return { + displayText: this.getDisplayName(), + modifierText: modifiers.length > 0 ? `(${modifiers.join(', ')})` : undefined + }; + } + + handleEditorAction(action: string, item: WidgetItem): WidgetItem | null { + if (action === 'toggle-nogit') { + const currentState = item.metadata?.hideNoGit === 'true'; + return { + ...item, + metadata: { + ...item.metadata, + hideNoGit: (!currentState).toString() + } + }; + } + return null; + } + + render(item: WidgetItem, context: RenderContext, _settings: Settings): string | null { + const hideNoGit = item.metadata?.hideNoGit === 'true'; + + if (context.isPreview) { + return item.rawValue ? 'my-repo' : '\uD83D\uDCC1 my-repo'; + } + + const rootDir = this.getGitRootDir(); + if (rootDir) { + const dirName = rootDir.split('/').pop() ?? rootDir; + return item.rawValue ? dirName : `\uD83D\uDCC1 ${dirName}`; + } + + return hideNoGit ? null : '\uD83D\uDCC1 no git'; + } + + private getGitRootDir(): string | null { + try { + const rootDir = execSync('git rev-parse --show-toplevel', { + encoding: 'utf8', + stdio: ['pipe', 'pipe', 'ignore'] + }).trim(); + return rootDir || null; + } catch { + return null; + } + } + + getCustomKeybinds(): CustomKeybind[] { + return [ + { key: 'h', label: '(h)ide \'no git\' message', action: 'toggle-nogit' } + ]; + } + + supportsRawValue(): boolean { return true; } + supportsColors(item: WidgetItem): boolean { return true; } +} \ No newline at end of file diff --git a/src/widgets/index.ts b/src/widgets/index.ts index faaa705..e7d2d15 100644 --- a/src/widgets/index.ts +++ b/src/widgets/index.ts @@ -2,6 +2,7 @@ export { ModelWidget } from './Model'; export { OutputStyleWidget } from './OutputStyle'; export { GitBranchWidget } from './GitBranch'; export { GitChangesWidget } from './GitChanges'; +export { GitRootDirWidget } from './GitRootDir'; export { GitWorktreeWidget } from './GitWorktree'; export { TokensInputWidget } from './TokensInput'; export { TokensOutputWidget } from './TokensOutput'; From 5553c44125b3f8a6c1235b9dea58b9b35a4618f7 Mon Sep 17 00:00:00 2001 From: tim-watcha Date: Sat, 6 Dec 2025 15:12:43 +0900 Subject: [PATCH 2/3] Change Git Root Dir widget icon to text label MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace 📁 emoji with "Repo:" text label for better compatibility. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- src/widgets/GitRootDir.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/widgets/GitRootDir.ts b/src/widgets/GitRootDir.ts index 56e35b9..8ef4cba 100644 --- a/src/widgets/GitRootDir.ts +++ b/src/widgets/GitRootDir.ts @@ -45,16 +45,16 @@ export class GitRootDirWidget implements Widget { const hideNoGit = item.metadata?.hideNoGit === 'true'; if (context.isPreview) { - return item.rawValue ? 'my-repo' : '\uD83D\uDCC1 my-repo'; + return item.rawValue ? 'my-repo' : 'Repo: my-repo'; } const rootDir = this.getGitRootDir(); if (rootDir) { const dirName = rootDir.split('/').pop() ?? rootDir; - return item.rawValue ? dirName : `\uD83D\uDCC1 ${dirName}`; + return item.rawValue ? dirName : `Repo: ${dirName}`; } - return hideNoGit ? null : '\uD83D\uDCC1 no git'; + return hideNoGit ? null : 'Repo: no git'; } private getGitRootDir(): string | null { From d386d7845a09d29ebde7fe3bd3cb88c4cea0847b Mon Sep 17 00:00:00 2001 From: tim-watcha Date: Sat, 6 Dec 2025 15:14:04 +0900 Subject: [PATCH 3/3] Remove label from Git Root Dir widget MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Display only the repository name without any prefix. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- src/widgets/GitRootDir.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/widgets/GitRootDir.ts b/src/widgets/GitRootDir.ts index 8ef4cba..e96cdd7 100644 --- a/src/widgets/GitRootDir.ts +++ b/src/widgets/GitRootDir.ts @@ -45,16 +45,16 @@ export class GitRootDirWidget implements Widget { const hideNoGit = item.metadata?.hideNoGit === 'true'; if (context.isPreview) { - return item.rawValue ? 'my-repo' : 'Repo: my-repo'; + return 'my-repo'; } const rootDir = this.getGitRootDir(); if (rootDir) { const dirName = rootDir.split('/').pop() ?? rootDir; - return item.rawValue ? dirName : `Repo: ${dirName}`; + return dirName; } - return hideNoGit ? null : 'Repo: no git'; + return hideNoGit ? null : 'no git'; } private getGitRootDir(): string | null {