claude-code-hud 0.3.4 → 0.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -26
- package/package.json +1 -1
- package/tui/hud.tsx +170 -26
package/README.md
CHANGED
|
@@ -8,27 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
Claude Code로 작업할 때 토큰 사용량, git 상태, 파일 구조를 IDE나 별도 탭 없이 터미널 하나에서 확인할 수 있는 HUD입니다.
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
┌──────────────────────────────────────────────────────────────────────────────┐
|
|
13
|
-
│ ◆ HUD │ ◉ TOKENS │ ○ PROJECT │ ○ GIT sonnet-4-6 · up 4m │
|
|
14
|
-
├──────────────────────────────────────────────────────────────────────────────┤
|
|
15
|
-
│ ▸ CONTEXT WINDOW │
|
|
16
|
-
│ ████████████████████░░░░░░░░░░░░░░░░░░░░░░░ 46% 92K / 200K OK │
|
|
17
|
-
│ │
|
|
18
|
-
│ ▸ USAGE WINDOW │
|
|
19
|
-
│ 5h ████████░░░░░░░░░░░░░░░░░░░░ 28.0% resets in 3h 12m │
|
|
20
|
-
│ wk ███░░░░░░░░░░░░░░░░░░░░░░░░░ 9.0% resets in 6h 48m │
|
|
21
|
-
│ │
|
|
22
|
-
│ ▸ TOKENS (this session) │
|
|
23
|
-
│ input ░░░░░░░░░░░░░░░░░░░░░░░░ 4.8K 0% │
|
|
24
|
-
│ output ░░░░░░░░░░░░░░░░░░░░░░░░ 188.5K 0% │
|
|
25
|
-
│ cache-read ████████████████████████ 51.5M 100% │
|
|
26
|
-
│ cache-write ██░░░░░░░░░░░░░░░░░░░░░░ 3.8M 7% │
|
|
27
|
-
│ │
|
|
28
|
-
│ ▸ OUTPUT TOKENS / HR │
|
|
29
|
-
│ total 2.1M │ avg 48.2K/hr │ peak 312K/hr │
|
|
30
|
-
└──────────────────────────────────────────────────────────────────────────────┘
|
|
31
|
-
```
|
|
11
|
+
<img src="./demo.gif" width="700" alt="demo">
|
|
32
12
|
|
|
33
13
|
### 사용법
|
|
34
14
|
|
|
@@ -137,11 +117,7 @@ Claude Code를 한 번 실행하면 `~/.claude/.credentials.json`에 credentials
|
|
|
137
117
|
|
|
138
118
|
A Terminal HUD (Heads-Up Display) for Claude Code — real-time token usage, git status, and interactive project file browser. No IDE, no extra tabs. Just a second terminal window.
|
|
139
119
|
|
|
140
|
-
|
|
141
|
-
┌──────────────────────────────────────────────────────────────────────────────┐
|
|
142
|
-
│ ◆ HUD │ ◉ TOKENS │ ○ PROJECT │ ○ GIT sonnet-4-6 · up 4m │
|
|
143
|
-
└──────────────────────────────────────────────────────────────────────────────┘
|
|
144
|
-
```
|
|
120
|
+
<img src="./demo.gif" width="700" alt="demo">
|
|
145
121
|
|
|
146
122
|
### Usage
|
|
147
123
|
|
package/package.json
CHANGED
package/tui/hud.tsx
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import React, { useState, useEffect, useCallback } from 'react';
|
|
7
7
|
import { render, Box, Text, useStdout, useInput } from 'ink';
|
|
8
8
|
import { fileURLToPath } from 'url';
|
|
9
|
-
import { dirname, join } from 'path';
|
|
9
|
+
import { dirname, join, basename } from 'path';
|
|
10
10
|
import fs from 'fs';
|
|
11
11
|
import os from 'os';
|
|
12
12
|
import { execSync } from 'child_process';
|
|
@@ -16,23 +16,34 @@ const { readTokenUsage, readTokenHistory } = await import(join(__dir, '../script
|
|
|
16
16
|
const { readGitInfo } = await import(join(__dir, '../scripts/lib/git-info.mjs'));
|
|
17
17
|
const { getUsage, getUsageSync } = await import(join(__dir, '../scripts/lib/usage-api.mjs'));
|
|
18
18
|
|
|
19
|
-
//
|
|
20
|
-
process.stdout.write('\x1b[
|
|
19
|
+
// Enter alternate screen buffer (like vim/htop — terminal never scrolls, header stays fixed)
|
|
20
|
+
process.stdout.write('\x1b[?1049h\x1b[2J\x1b[H');
|
|
21
|
+
process.on('exit', () => process.stdout.write('\x1b[?1049l'));
|
|
22
|
+
process.on('SIGINT', () => { process.stdout.write('\x1b[?1049l'); process.exit(0); });
|
|
23
|
+
process.on('SIGTERM', () => { process.stdout.write('\x1b[?1049l'); process.exit(0); });
|
|
21
24
|
|
|
22
25
|
const SESSION_START = Date.now();
|
|
23
26
|
|
|
24
27
|
// ── Themes ─────────────────────────────────────────────────────────────────
|
|
25
|
-
|
|
26
|
-
|
|
28
|
+
// Base is always dark. Only accent colors cycle with `d`.
|
|
29
|
+
const BASE = {
|
|
30
|
+
text: '#E6EDF3', dim: '#8B949E', dimmer: '#6E7681',
|
|
27
31
|
border: '#30363D', green: '#3FB950', yellow: '#D29922', red: '#F85149',
|
|
28
|
-
purple: '#A371F7', cyan: '#58A6FF',
|
|
29
|
-
};
|
|
30
|
-
const LIGHT = {
|
|
31
|
-
brand: '#3182F6', text: '#1F2328', dim: '#656D76', dimmer: '#8C959F',
|
|
32
|
-
border: '#D8DEE4', green: '#1A7F37', yellow: '#9A6700', red: '#CF222E',
|
|
33
|
-
purple: '#8250DF', cyan: '#0969DA',
|
|
34
32
|
};
|
|
35
33
|
|
|
34
|
+
const ACCENTS = [
|
|
35
|
+
{ brand: '#3B82F6', cyan: '#60A5FA', purple: '#A78BFA' }, // blue
|
|
36
|
+
{ brand: '#F43F5E', cyan: '#FB7185', purple: '#F9A8D4' }, // red
|
|
37
|
+
{ brand: '#F59E0B', cyan: '#FCD34D', purple: '#FDE68A' }, // amber
|
|
38
|
+
{ brand: '#10B981', cyan: '#34D399', purple: '#6EE7B7' }, // emerald
|
|
39
|
+
{ brand: '#EC4899', cyan: '#F472B6', purple: '#F9A8D4' }, // pink
|
|
40
|
+
] as const;
|
|
41
|
+
|
|
42
|
+
type Theme = typeof BASE & typeof ACCENTS[number];
|
|
43
|
+
function makeTheme(accentIdx: number): Theme {
|
|
44
|
+
return { ...BASE, ...ACCENTS[accentIdx] };
|
|
45
|
+
}
|
|
46
|
+
|
|
36
47
|
// ── Helpers ────────────────────────────────────────────────────────────────
|
|
37
48
|
const fmtNum = (n: number) =>
|
|
38
49
|
n >= 1_000_000 ? (n / 1_000_000).toFixed(1) + 'M' :
|
|
@@ -197,6 +208,62 @@ function getBranches(cwd: string): string[] {
|
|
|
197
208
|
}
|
|
198
209
|
}
|
|
199
210
|
|
|
211
|
+
// ── Timeline ────────────────────────────────────────────────────────────────
|
|
212
|
+
type TimelineEntry = {
|
|
213
|
+
time: string;
|
|
214
|
+
text: string;
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
async function readSessionTimeline(cwd: string): Promise<TimelineEntry[]> {
|
|
218
|
+
const projectsDir = join(os.homedir(), '.claude', 'projects');
|
|
219
|
+
if (!fs.existsSync(projectsDir)) return [];
|
|
220
|
+
|
|
221
|
+
let latestFile: string | null = null;
|
|
222
|
+
let latestMtime = 0;
|
|
223
|
+
try {
|
|
224
|
+
for (const projectHash of fs.readdirSync(projectsDir)) {
|
|
225
|
+
const sessionDir = join(projectsDir, projectHash);
|
|
226
|
+
if (!fs.statSync(sessionDir).isDirectory()) continue;
|
|
227
|
+
for (const file of fs.readdirSync(sessionDir)) {
|
|
228
|
+
if (!file.endsWith('.jsonl')) continue;
|
|
229
|
+
const filePath = join(sessionDir, file);
|
|
230
|
+
try {
|
|
231
|
+
const mtime = fs.statSync(filePath).mtimeMs;
|
|
232
|
+
if (mtime > latestMtime) { latestMtime = mtime; latestFile = filePath; }
|
|
233
|
+
} catch {}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
} catch {}
|
|
237
|
+
|
|
238
|
+
if (!latestFile) return [];
|
|
239
|
+
|
|
240
|
+
const lines = fs.readFileSync(latestFile, 'utf-8').split('\n').filter(Boolean);
|
|
241
|
+
const entries: TimelineEntry[] = [];
|
|
242
|
+
|
|
243
|
+
for (const line of lines) {
|
|
244
|
+
try {
|
|
245
|
+
const obj = JSON.parse(line);
|
|
246
|
+
if (obj.type !== 'user') continue;
|
|
247
|
+
const content = obj.message?.content;
|
|
248
|
+
const textBlock = Array.isArray(content)
|
|
249
|
+
? content.find((b: any) => b.type === 'text')
|
|
250
|
+
: null;
|
|
251
|
+
const text: string = textBlock?.text ?? (typeof content === 'string' ? content : '');
|
|
252
|
+
if (!text.trim()) continue;
|
|
253
|
+
|
|
254
|
+
const ts: string = obj.timestamp ?? '';
|
|
255
|
+
let time = '';
|
|
256
|
+
if (ts) {
|
|
257
|
+
try { time = new Date(ts).toTimeString().slice(0, 5); } catch {}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
entries.push({ time, text: text.replace(/\n/g, ' ').slice(0, 80) });
|
|
261
|
+
} catch {}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
return entries.slice(-30);
|
|
265
|
+
}
|
|
266
|
+
|
|
200
267
|
// ── UI Components ──────────────────────────────────────────────────────────
|
|
201
268
|
function Bar({ ratio, width, color, C }: { ratio: number; width: number; color: string; C: typeof DARK }) {
|
|
202
269
|
const filled = Math.max(0, Math.min(width, Math.round(ratio * width)));
|
|
@@ -218,7 +285,7 @@ function Section({ title, children, C, accent }: { title: string; children: Reac
|
|
|
218
285
|
}
|
|
219
286
|
|
|
220
287
|
// ── Tab 1: TOKENS ──────────────────────────────────────────────────────────
|
|
221
|
-
function TokensTab({ usage, history, rateLimits, termWidth, C }: any) {
|
|
288
|
+
function TokensTab({ usage, history, rateLimits, termWidth, currentActivity, C }: any) {
|
|
222
289
|
const ctxPct = usage.contextWindow > 0 ? usage.totalTokens / usage.contextWindow : 0;
|
|
223
290
|
const ctxColor = ctxPct > 0.85 ? C.red : ctxPct > 0.65 ? C.yellow : C.brand;
|
|
224
291
|
const ctxLabel = ctxPct > 0.85 ? 'WARN' : ctxPct > 0.65 ? 'MID' : 'OK';
|
|
@@ -330,6 +397,14 @@ function TokensTab({ usage, history, rateLimits, termWidth, C }: any) {
|
|
|
330
397
|
</Section>
|
|
331
398
|
);
|
|
332
399
|
})()}
|
|
400
|
+
|
|
401
|
+
{/* Current activity */}
|
|
402
|
+
{currentActivity && (
|
|
403
|
+
<Box borderStyle="single" borderColor={C.border} paddingX={1}>
|
|
404
|
+
<Text color={C.dimmer}>now </Text>
|
|
405
|
+
<Text color={C.brand}>{currentActivity.slice(0, termWidth - 12)}</Text>
|
|
406
|
+
</Box>
|
|
407
|
+
)}
|
|
333
408
|
</Box>
|
|
334
409
|
);
|
|
335
410
|
}
|
|
@@ -599,18 +674,46 @@ function GitTab({ git, C, termWidth, branchMode, branchList, branchCursor }: any
|
|
|
599
674
|
);
|
|
600
675
|
}
|
|
601
676
|
|
|
677
|
+
// ── Tab 4: TIMELINE ────────────────────────────────────────────────────────
|
|
678
|
+
const TIMELINE_VISIBLE = 10;
|
|
679
|
+
|
|
680
|
+
function TimelineTab({ timeline, timelineScroll, C }: any) {
|
|
681
|
+
const entries = timeline as TimelineEntry[];
|
|
682
|
+
const visible = entries.slice(timelineScroll, timelineScroll + TIMELINE_VISIBLE);
|
|
683
|
+
return (
|
|
684
|
+
<Box flexDirection="column" borderStyle="single" borderColor={C.border} paddingX={1}>
|
|
685
|
+
<Text color={C.dimmer} bold>▸ <Text color={C.text}>SESSION HISTORY</Text>
|
|
686
|
+
{entries.length > 0 && <Text color={C.dimmer}> {timelineScroll + 1}–{Math.min(timelineScroll + TIMELINE_VISIBLE, entries.length)} / {entries.length}</Text>}
|
|
687
|
+
</Text>
|
|
688
|
+
<Box flexDirection="column" marginTop={1}>
|
|
689
|
+
{entries.length === 0 && <Text color={C.dimmer}> no messages yet</Text>}
|
|
690
|
+
{visible.map((entry, i) => (
|
|
691
|
+
<Box key={i} marginBottom={1}>
|
|
692
|
+
<Box width={6}><Text color={C.dimmer}>{entry.time}</Text></Box>
|
|
693
|
+
<Text color={C.text}>{entry.text}</Text>
|
|
694
|
+
</Box>
|
|
695
|
+
))}
|
|
696
|
+
{entries.length > TIMELINE_VISIBLE && (
|
|
697
|
+
<Text color={C.dimmer}> [j/k] scroll</Text>
|
|
698
|
+
)}
|
|
699
|
+
</Box>
|
|
700
|
+
</Box>
|
|
701
|
+
);
|
|
702
|
+
}
|
|
703
|
+
|
|
602
704
|
// ── Main App ───────────────────────────────────────────────────────────────
|
|
603
705
|
function App() {
|
|
604
706
|
const { stdout } = useStdout();
|
|
605
|
-
const [termWidth,
|
|
707
|
+
const [termWidth, setTermWidth] = useState(stdout?.columns ?? 80);
|
|
708
|
+
const [termHeight, setTermHeight] = useState(stdout?.rows ?? 24);
|
|
606
709
|
const [tab, setTab] = useState(0); // 0=TOKENS 1=PROJECT 2=GIT
|
|
607
|
-
const [
|
|
710
|
+
const [accent, setAccent] = useState(3); // 0=blue 1=red 2=amber 3=emerald 4=pink
|
|
608
711
|
const [scrollY, setScrollY] = useState(0);
|
|
609
712
|
const [tick, setTick] = useState(0);
|
|
610
713
|
const [updatedAt, setUpdatedAt] = useState(Date.now());
|
|
611
714
|
|
|
612
715
|
const cwd = process.env.CLAUDE_PROJECT_ROOT || process.cwd();
|
|
613
|
-
const C =
|
|
716
|
+
const C = makeTheme(accent);
|
|
614
717
|
|
|
615
718
|
const [usage, setUsage] = useState<any>(readTokenUsage());
|
|
616
719
|
const [history, setHistory] = useState<any>(readTokenHistory());
|
|
@@ -632,12 +735,24 @@ function App() {
|
|
|
632
735
|
const [branchList, setBranchList] = useState<string[]>([]);
|
|
633
736
|
const [branchCursor, setBranchCursor] = useState(0);
|
|
634
737
|
|
|
738
|
+
// Timeline state
|
|
739
|
+
const [timeline, setTimeline] = useState<TimelineEntry[]>([]);
|
|
740
|
+
const [timelineScroll, setTimelineScroll] = useState(0);
|
|
741
|
+
const [currentActivity, setCurrentActivity] = useState<string>('');
|
|
742
|
+
|
|
635
743
|
const refresh = useCallback(() => {
|
|
636
744
|
setUsage(readTokenUsage());
|
|
637
745
|
setHistory(readTokenHistory());
|
|
638
746
|
setGit(readGitInfo(cwd));
|
|
639
747
|
setUpdatedAt(Date.now());
|
|
640
748
|
getUsage().then(setRateLimits).catch(() => {});
|
|
749
|
+
readSessionTimeline(cwd).then(entries => {
|
|
750
|
+
setTimeline(entries);
|
|
751
|
+
if (entries.length > 0) {
|
|
752
|
+
const last = entries[entries.length - 1];
|
|
753
|
+
setCurrentActivity(last.text);
|
|
754
|
+
}
|
|
755
|
+
}).catch(() => {});
|
|
641
756
|
}, [cwd]);
|
|
642
757
|
|
|
643
758
|
useEffect(() => {
|
|
@@ -645,10 +760,19 @@ function App() {
|
|
|
645
760
|
scanProject(cwd).then(setProject).catch(() => {});
|
|
646
761
|
// Initial API usage fetch
|
|
647
762
|
getUsage().then(setRateLimits).catch(() => {});
|
|
763
|
+
// Initial timeline load
|
|
764
|
+
readSessionTimeline(cwd).then(entries => {
|
|
765
|
+
setTimeline(entries);
|
|
766
|
+
if (entries.length > 0) {
|
|
767
|
+
const last = entries[entries.length - 1];
|
|
768
|
+
setCurrentActivity(last.text);
|
|
769
|
+
}
|
|
770
|
+
}).catch(() => {});
|
|
648
771
|
|
|
649
772
|
const onResize = () => {
|
|
650
773
|
process.stdout.write('\x1b[2J\x1b[3J\x1b[H');
|
|
651
774
|
setTermWidth(stdout?.columns ?? 80);
|
|
775
|
+
setTermHeight(stdout?.rows ?? 24);
|
|
652
776
|
};
|
|
653
777
|
stdout?.on('resize', onResize);
|
|
654
778
|
|
|
@@ -727,7 +851,8 @@ function App() {
|
|
|
727
851
|
if (input === '1') { setTab(0); setScrollY(0); }
|
|
728
852
|
if (input === '2') { setTab(1); setScrollY(0); }
|
|
729
853
|
if (input === '3') { setTab(2); setScrollY(0); }
|
|
730
|
-
if (input === '
|
|
854
|
+
if (input === '4') { setTab(3); setScrollY(0); }
|
|
855
|
+
if (input === 'd' || input === 'ㅇ') setAccent(a => (a + 1) % ACCENTS.length);
|
|
731
856
|
|
|
732
857
|
// r = manual refresh
|
|
733
858
|
if (input === 'r' || input === 'ㄱ') {
|
|
@@ -743,6 +868,8 @@ function App() {
|
|
|
743
868
|
} else if (tab === 1) {
|
|
744
869
|
const flat = project?.dirTree ? flattenTree(project.dirTree, 0, treeExpanded) : [];
|
|
745
870
|
setTreeCursor(c => Math.min(c + 1, flat.length - 1));
|
|
871
|
+
} else if (tab === 3) {
|
|
872
|
+
setTimelineScroll(s => Math.min(s + 1, Math.max(0, timeline.length - 10)));
|
|
746
873
|
} else {
|
|
747
874
|
setScrollY(s => Math.min(s + 1, 20));
|
|
748
875
|
}
|
|
@@ -752,6 +879,8 @@ function App() {
|
|
|
752
879
|
setFileScroll(s => Math.max(s - 1, 0));
|
|
753
880
|
} else if (tab === 1) {
|
|
754
881
|
setTreeCursor(c => Math.max(c - 1, 0));
|
|
882
|
+
} else if (tab === 3) {
|
|
883
|
+
setTimelineScroll(s => Math.max(s - 1, 0));
|
|
755
884
|
} else {
|
|
756
885
|
setScrollY(s => Math.max(s - 1, 0));
|
|
757
886
|
}
|
|
@@ -798,7 +927,7 @@ function App() {
|
|
|
798
927
|
}
|
|
799
928
|
});
|
|
800
929
|
|
|
801
|
-
const TAB_NAMES = ['TOKENS', 'PROJECT', 'GIT'];
|
|
930
|
+
const TAB_NAMES = ['TOKENS', 'PROJECT', 'GIT', 'TIMELINE'];
|
|
802
931
|
const since = fmtSince(Date.now() - updatedAt);
|
|
803
932
|
const uptime = fmtSince(SESSION_START - Date.now() + (Date.now() - SESSION_START)); // forces tick dep
|
|
804
933
|
void tick;
|
|
@@ -826,26 +955,41 @@ function App() {
|
|
|
826
955
|
</Box>
|
|
827
956
|
</Box>
|
|
828
957
|
|
|
829
|
-
{/* ── Content
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
958
|
+
{/* ── Content: fixed height so header/footer never get pushed off screen ── */}
|
|
959
|
+
{(() => {
|
|
960
|
+
// header ~3 rows, footer key row ~1, footer dir row ~3 = 7 total chrome
|
|
961
|
+
const contentH = Math.max(4, termHeight - 7);
|
|
962
|
+
return (
|
|
963
|
+
<Box flexDirection="column" height={contentH} overflow="hidden">
|
|
964
|
+
<Box flexDirection="column" marginTop={-scrollY}>
|
|
965
|
+
{tab === 0 && <TokensTab usage={usage} history={history} rateLimits={rateLimits} termWidth={termWidth} currentActivity={currentActivity} C={C} />}
|
|
966
|
+
{tab === 1 && <ProjectTab info={project} treeCursor={treeCursor} treeExpanded={treeExpanded} selectedFile={selectedFile} fileLines={fileLines} fileScroll={fileScroll} termWidth={termWidth} git={git} C={C} />}
|
|
967
|
+
{tab === 2 && <GitTab git={git} termWidth={termWidth} branchMode={branchMode} branchList={branchList} branchCursor={branchCursor} C={C} />}
|
|
968
|
+
{tab === 3 && <TimelineTab timeline={timeline} timelineScroll={timelineScroll} C={C} />}
|
|
969
|
+
</Box>
|
|
970
|
+
</Box>
|
|
971
|
+
);
|
|
972
|
+
})()}
|
|
835
973
|
|
|
836
|
-
{/* ── Footer ── */}
|
|
974
|
+
{/* ── Footer row 1: keys ── */}
|
|
837
975
|
<Box justifyContent="space-between" paddingX={1}>
|
|
838
976
|
<Box>
|
|
839
977
|
<Text color={C.green}>● </Text>
|
|
840
|
-
<Text color={C.dimmer}>[1/2/3] tabs </Text>
|
|
978
|
+
<Text color={C.dimmer}>[1/2/3/4] tabs </Text>
|
|
841
979
|
<Text color={tab === 1 ? C.brand : C.dimmer}>[j/k] {tab === 1 ? 'tree' : 'scroll'} </Text>
|
|
842
980
|
<Text color={tab === 1 ? C.brand : C.dimmer}>{tab === 1 ? (selectedFile ? '[esc/←] close [j/k] scroll ' : '[enter] open [→←] expand ') : ''}</Text>
|
|
843
981
|
{tab === 2 && !branchMode && <Text color={C.brand}>[b] branch </Text>}
|
|
844
|
-
<Text color={C.dimmer}>[r] refresh [d]
|
|
982
|
+
<Text color={C.dimmer}>[r] refresh [d] color [q] quit</Text>
|
|
845
983
|
</Box>
|
|
846
984
|
<Text color={C.dimmer}>↻ {since}</Text>
|
|
847
985
|
</Box>
|
|
848
986
|
|
|
987
|
+
{/* ── Footer row 2: current dir ── */}
|
|
988
|
+
<Box paddingX={1} borderStyle="single" borderColor={C.brand}>
|
|
989
|
+
<Text color={C.brand} bold>◆ </Text>
|
|
990
|
+
<Text color={C.text} bold>~/{basename(cwd)}</Text>
|
|
991
|
+
</Box>
|
|
992
|
+
|
|
849
993
|
</Box>
|
|
850
994
|
);
|
|
851
995
|
}
|