Skip to content

Commit 48e459e

Browse files
davindicodeclaude
andcommitted
Show tool versions (tmux, nano, vim) in their respective panels
- New /api/tool-versions endpoint returns versions for tmux, nano, vim - Versions displayed in file opener and session panels - Fetched once on first tool tab open, cached for session Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent dfc9cef commit 48e459e

3 files changed

Lines changed: 38 additions & 2 deletions

File tree

app/components/terminal/InputBox.tsx

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,8 @@ export default function InputBox() {
166166
const [activeGroup, setActiveGroup] = useState<string | null>(null);
167167
const [tmuxSessions, setTmuxSessions] = useState<TmuxSession[]>([]);
168168
const [tmuxLoading, setTmuxLoading] = useState(false);
169+
const [toolVersions, setToolVersions] = useState<{ tmux: string | null; nano: string | null; vim: string | null }>({ tmux: null, nano: null, vim: null });
170+
const toolVersionsFetched = useRef(false);
169171
const [tmuxNewName, setTmuxNewName] = useState("");
170172
const [editorFileName, setEditorFileName] = useState("");
171173
const [cdDirs, setCdDirs] = useState<string[]>([]);
@@ -258,13 +260,24 @@ export default function InputBox() {
258260
onContextMenu: (e: React.MouseEvent) => e.preventDefault(),
259261
});
260262

263+
const fetchToolVersions = async () => {
264+
if (toolVersionsFetched.current) return;
265+
toolVersionsFetched.current = true;
266+
try {
267+
const res = await fetch("/api/tool-versions");
268+
const data = await res.json();
269+
setToolVersions(data);
270+
} catch {}
271+
};
272+
261273
const toggleGroup = (id: string) => {
262274
if (activeGroup === id) {
263275
setActiveGroup(null);
264276
} else {
265277
setActiveGroup(id);
266278
if (id === TMUX_TAB && !inTmux) fetchTmuxSessions();
267279
if (id === "cmds") fetchDirs();
280+
if ([TMUX_TAB, NANO_TAB, VIM_TAB].includes(id)) fetchToolVersions();
268281
}
269282
};
270283

@@ -569,7 +582,7 @@ export default function InputBox() {
569582
{activeGroup === NANO_TAB && inEditor !== "nano" && (
570583
<div className="border-b border-gray-700/50 bg-[#12122a] px-3 py-2">
571584
<div className="flex items-center gap-2">
572-
<span className="text-[11px] text-gray-500">nano</span>
585+
<span className="text-[11px] text-gray-500">nano{toolVersions.nano ? ` v${toolVersions.nano}` : ""}</span>
573586
<input
574587
value={editorFileName}
575588
onChange={(e) => setEditorFileName(e.target.value)}
@@ -609,7 +622,7 @@ export default function InputBox() {
609622
{activeGroup === VIM_TAB && inEditor !== "vim" && (
610623
<div className="border-b border-gray-700/50 bg-[#12122a] px-3 py-2">
611624
<div className="flex items-center gap-2">
612-
<span className="text-[11px] text-gray-500">vim</span>
625+
<span className="text-[11px] text-gray-500">vim{toolVersions.vim ? ` v${toolVersions.vim}` : ""}</span>
613626
<input
614627
value={editorFileName}
615628
onChange={(e) => setEditorFileName(e.target.value)}
@@ -645,6 +658,9 @@ export default function InputBox() {
645658
)}
646659
{activeGroup === TMUX_TAB && !inTmux && (
647660
<div className="border-b border-gray-700/50 bg-[#12122a] px-3 py-2">
661+
{toolVersions.tmux && (
662+
<span className="text-[10px] text-gray-600 float-right">v{toolVersions.tmux}</span>
663+
)}
648664
{tmuxLoading ? (
649665
<span className="text-[11px] text-gray-500">Loading...</span>
650666
) : tmuxSessions.length === 0 ? (

app/routes.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,5 @@ export default [
1111
route("api/files/download", "routes/api/files.download.ts"),
1212
route("api/files/mkdir", "routes/api/files.mkdir.ts"),
1313
route("api/tmux/sessions", "routes/api/tmux.sessions.ts"),
14+
route("api/tool-versions", "routes/api/tool-versions.ts"),
1415
] satisfies RouteConfig;

app/routes/api/tool-versions.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { execSync } from "child_process";
2+
import type { Route } from "./+types/tool-versions";
3+
4+
function getVersion(cmd: string): string | null {
5+
try {
6+
const output = execSync(cmd, { encoding: "utf-8", timeout: 3000, stdio: ["ignore", "pipe", "pipe"] }).trim();
7+
return output;
8+
} catch {
9+
return null;
10+
}
11+
}
12+
13+
export async function loader({ request }: Route.LoaderArgs) {
14+
const tmux = getVersion("tmux -V")?.replace(/^tmux\s+/, "") || null;
15+
const nano = getVersion("nano --version")?.split("\n")[0]?.replace(/.*nano\s+/, "")?.trim() || null;
16+
const vim = getVersion("vim --version")?.split("\n")[0]?.match(/Vi IMproved (\S+)/)?.[1] || null;
17+
18+
return Response.json({ tmux, nano, vim });
19+
}

0 commit comments

Comments
 (0)