Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,7 @@ Once configured, ccstatusline automatically formats your Claude Code status line
- **Session Clock** - Shows elapsed time since session start (e.g., "2hr 15m")
- **Session Cost** - Shows total session cost in USD (e.g., "$1.23")
- **Block Timer** - Shows time elapsed in current 5-hour block or progress bar
- **Task Timer** - Shows real-time task execution time (requires hook installation, e.g., "执行中:1分23秒" or "执行完成:2分45秒")
- **Current Working Directory** - Shows current working directory with configurable path segments
- **Version** - Shows Claude Code version
- **Output Style** - Shows the currently set output style in Claude Code
Expand Down Expand Up @@ -432,12 +433,67 @@ The Block Timer widget helps you track your progress through Claude Code's 5-hou
- Progress bars show completion percentage (e.g., "[████████████████████████░░░░░░░░] 73.9%")
- Toggle between modes with the **(p)** key in the widgets editor

### ⏱️ Task Timer Widget

The Task Timer widget provides real-time tracking of how long Claude has been working on the current task:

**Installation Required:**

Before using the Task Timer widget, you need to install the required hooks:

1. Run ccstatusline: `npx ccstatusline@latest` or `bunx ccstatusline@latest`
2. From the main menu, select **"⏱️ Task Timer Setup"**
3. Press **(i)** to install hooks
- This copies `timing_hook.sh` to `~/.claude/hooks/`
- Updates your `~/.claude/settings.json` with hook configurations
- Adds hooks for: `UserPromptSubmit`, `Stop`, and `SessionEnd`

**Display Modes:**
- **Executing** - Shows "执行中:1分23秒" while Claude is working
- **Completed** - Shows "执行完成:2分45秒" after task finishes
- **Raw Value** - Shows just the time (e.g., "1分23秒") without prefix

**Features:**
- **Real-time Updates** - Timer updates during task execution (refresh rate depends on Claude Code)
- **Multi-session Support** - Each Claude Code instance has an independent timer
- **Automatic Cleanup** - State is cleaned up when sessions end
- **Smart Formatting** - Time automatically scales:
- Less than 60s: "42秒"
- 60s to 1hr: "5分30秒"
- Over 1hr: "2时15分30秒"
- **Persistent State** - Timer state survives terminal restarts
- **Cross-platform** - Works on Linux, macOS, and Windows (requires bash)

**How It Works:**

The Task Timer uses Claude Code hooks to track task execution:

1. **UserPromptSubmit Hook** - Records start time when you submit a prompt
2. **Stop Hook** - Calculates duration when Claude finishes the task
3. **SessionEnd Hook** - Cleans up timer state when session ends
4. **Display Mode** - ccstatusline queries the hook script to get current status

**Uninstalling:**

To remove the Task Timer hooks:
1. Run ccstatusline and go to **"⏱️ Task Timer Setup"**
2. Press **(u)** to uninstall
- Removes `timing_hook.sh` from `~/.claude/hooks/`
- Cleans up hook configurations from `settings.json`

**Troubleshooting:**

- **Timer not showing:** Ensure hooks are installed via Task Timer Setup
- **Permission errors:** Run `chmod +x ~/.claude/hooks/timing_hook.sh` on Unix systems
- **Incorrect times:** Clear state with `rm -rf ~/.claude/.timing/*`

### 🔤 Raw Value Mode

Some widgets support "raw value" mode which displays just the value without a label:
- Normal: `Model: Claude 3.5 Sonnet` → Raw: `Claude 3.5 Sonnet`
- Normal: `Session: 2hr 15m` → Raw: `2hr 15m`
- Normal: `Block: 3hr 45m` → Raw: `3hr 45m`
- Normal: `执行中:1分23秒` → Raw: `1分23秒`
- Normal: `Ctx: 18.6k` → Raw: `18.6k`

---
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
"ccstatusline": "dist/ccstatusline.js"
},
"files": [
"dist/"
"dist/",
"templates/"
],
"scripts": {
"start": "bun run src/ccstatusline.ts",
Expand Down
20 changes: 16 additions & 4 deletions src/tui/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import {
MainMenu,
PowerlineSetup,
StatusLinePreview,
TaskTimerSetup,
TerminalOptionsMenu,
TerminalWidthMenu
} from './components';
Expand All @@ -55,7 +56,7 @@ export const App: React.FC = () => {
const [settings, setSettings] = useState<Settings | null>(null);
const [originalSettings, setOriginalSettings] = useState<Settings | null>(null);
const [hasChanges, setHasChanges] = useState(false);
const [screen, setScreen] = useState<'main' | 'lines' | 'items' | 'colorLines' | 'colors' | 'terminalWidth' | 'terminalConfig' | 'globalOverrides' | 'confirm' | 'powerline' | 'install'>('main');
const [screen, setScreen] = useState<'main' | 'lines' | 'items' | 'colorLines' | 'colors' | 'terminalWidth' | 'terminalConfig' | 'globalOverrides' | 'confirm' | 'powerline' | 'taskTimer' | 'install'>('main');
const [selectedLine, setSelectedLine] = useState(0);
const [menuSelections, setMenuSelections] = useState<Record<string, number>>({});
const [confirmDialog, setConfirmDialog] = useState<{ message: string; action: () => Promise<void> } | null>(null);
Expand Down Expand Up @@ -208,6 +209,9 @@ export const App: React.FC = () => {
case 'powerline':
setScreen('powerline');
break;
case 'taskTimer':
setScreen('taskTimer');
break;
case 'install':
handleInstallUninstall();
break;
Expand Down Expand Up @@ -273,9 +277,10 @@ export const App: React.FC = () => {
lines: 0,
colors: 1,
powerline: 2,
terminalConfig: 3,
globalOverrides: 4,
install: 5
taskTimer: 3,
terminalConfig: 4,
globalOverrides: 5,
install: 6
};
setMenuSelections({ ...menuSelections, main: menuMap[value] ?? 0 });
}
Expand Down Expand Up @@ -451,6 +456,13 @@ export const App: React.FC = () => {
onClearMessage={() => { setFontInstallMessage(null); }}
/>
)}
{screen === 'taskTimer' && (
<TaskTimerSetup
onBack={() => {
setScreen('main');
}}
/>
)}
</Box>
</Box>
);
Expand Down
2 changes: 2 additions & 0 deletions src/tui/components/MainMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export const MainMenu: React.FC<MainMenuProps> = ({ onSelect, isClaudeInstalled,
{ label: '📝 Edit Lines', value: 'lines', selectable: true },
{ label: '🎨 Edit Colors', value: 'colors', selectable: true },
{ label: '⚡ Powerline Setup', value: 'powerline', selectable: true },
{ label: '⏱️ Task Timer Setup', value: 'taskTimer', selectable: true },
{ label: '', value: '_gap1', selectable: false }, // Visual gap
{ label: '💻 Terminal Options', value: 'terminalConfig', selectable: true },
{ label: '🌐 Global Overrides', value: 'globalOverrides', selectable: true },
Expand Down Expand Up @@ -64,6 +65,7 @@ export const MainMenu: React.FC<MainMenuProps> = ({ onSelect, isClaudeInstalled,
lines: 'Configure any number of status lines with various widgets like model info, git status, and token usage',
colors: 'Customize colors for each widget including foreground, background, and bold styling',
powerline: 'Install Powerline fonts for enhanced visual separators and symbols in your status line',
taskTimer: 'Install hooks to track and display task execution time in your status line',
globalOverrides: 'Set global padding, separators, and color overrides that apply to all widgets',
install: isClaudeInstalled
? 'Remove ccstatusline from your Claude Code settings'
Expand Down
Loading