Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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
5 changes: 5 additions & 0 deletions .changeset/tui-about-dialog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@kilocode/cli": minor
---

Add an About dialog in the TUI accessible from the command palette (under "Kilo") or via the `/about` slash command. Shows version, channel, runtime/platform, config path, project root, connected providers, and default model, with helpful links (docs, GitHub, issues, Discord) and a `c` shortcut to copy diagnostics to the clipboard.
5 changes: 5 additions & 0 deletions packages/kilo-docs/source-links.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@
<!-- packages/kilo-vscode/webview-ui/src/components/marketplace/MarketplaceContribute.tsx -->
- <https://github.com/Kilo-Org/kilocode>
<!-- packages/kilo-vscode/webview-ui/src/components/settings/AboutKiloCodeTab.tsx -->
<!-- packages/opencode/src/kilocode/cli/cmd/tui/component/dialog-about.tsx -->
- <https://github.com/Kilo-Org/kilocode/issues>
<!-- packages/opencode/src/kilocode/cli/cmd/tui/component/dialog-about.tsx -->
- <https://github.com/Kilo-Org/kilocode/issues/6986>
<!-- packages/kilo-vscode/src/agent-manager/constants.ts -->
- <https://github.com/Kilo-Org/kilocode/issues/9618>
Expand Down Expand Up @@ -120,9 +123,11 @@
- <https://kilo.ai/discord>
<!-- packages/kilo-vscode/webview-ui/src/components/chat/FeedbackDialog.tsx -->
<!-- packages/kilo-vscode/webview-ui/src/components/settings/AboutKiloCodeTab.tsx -->
<!-- packages/opencode/src/kilocode/cli/cmd/tui/component/dialog-about.tsx -->
- <https://kilo.ai/docs>
<!-- packages/kilo-vscode/webview-ui/src/hooks/useSlashCommand.ts -->
<!-- packages/opencode/src/kilocode/cli/cmd/tui/app.tsx -->
<!-- packages/opencode/src/kilocode/cli/cmd/tui/component/dialog-about.tsx -->
- <https://kilo.ai/docs/ai-providers/cloudflare>
<!-- packages/opencode/src/cli/cmd/providers.ts -->
- <https://kilo.ai/docs/ai-providers/gemini>
Expand Down
156 changes: 156 additions & 0 deletions packages/opencode/src/kilocode/cli/cmd/tui/component/dialog-about.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
// kilocode_change - new file
import { TextAttributes } from "@opentui/core"
import { For } from "solid-js"
import { InstallationVersion, InstallationChannel } from "@opencode-ai/core/installation/version"
import { Global } from "@opencode-ai/core/global"
import { useDialog, type DialogContext } from "@tui/ui/dialog"
import { useTheme } from "@tui/context/theme"
import { useSync } from "@tui/context/sync"
import { useProject } from "@tui/context/project"
import { useClipboard } from "@tui/context/clipboard"
import { useToast } from "@tui/ui/toast"
import { useBindings } from "@tui/keymap"

function runtime() {
const rt = (globalThis as { Bun?: { version?: string } }).Bun
return rt?.version ? `Bun ${rt.version}` : `Node ${process.versions.node}`
}

function truncate(text: string, max: number) {
return text.length > max ? text.slice(0, max - 1) + "\u2026" : text
}

export function showAboutDialog(dialog: DialogContext) {
dialog.replace(() => <DialogAbout />)
}

function Row(props: { label: string; value: string; theme: ReturnType<typeof useTheme>["theme"]; muted?: boolean }) {
return (
<box flexDirection="row" gap={1}>
<text fg={props.theme.textMuted} width={18}>
{props.label}
</text>
<text fg={props.muted ? props.theme.textMuted : props.theme.text} wrapMode="word">
{props.value}
</text>
</box>
)
}

export function DialogAbout() {
const dialog = useDialog()
const { theme } = useTheme()
const sync = useSync()
const project = useProject()
const clipboard = useClipboard()
const toast = useToast()

const providers = () => {
const connected = sync.data.provider_next.connected
return connected.length ? connected.join(", ") : "(none connected)"
}
const defaultModel = () => sync.data.config.model ?? ""

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The selected model here may differ from the model picker. Please take a look at how debug dialog uses local.model.current().

const projectRoot = () => project.data.project.mainDir ?? project.instance.path().directory ?? process.cwd()

const links = [
{ label: "Docs", url: "https://kilo.ai/docs" },
{ label: "GitHub", url: "https://github.com/Kilo-Org/kilocode" },
{ label: "Issues", url: "https://github.com/Kilo-Org/kilocode/issues" },
{ label: "Discord", url: "https://kilo.ai/discord" },
]

const copy = () => {
if (!clipboard.write) {
toast.show({ variant: "error", message: "Clipboard not available" })
return
}
const text = [
`Kilo CLI ${InstallationVersion} (${InstallationChannel})`,
`Runtime: ${runtime()} (${process.platform}/${process.arch})`,
`Config: ${Global.Path.config}`,
`Project: ${projectRoot()}`,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we consider the existing privacy mode here, and abbreviate/redact paths according to the privacy settings?

`Providers: ${providers()}`,
`Default model: ${defaultModel() || "(none)"}`,
].join("\n")
void clipboard.write(text).then(
() => toast.show({ variant: "success", message: "Diagnostics copied" }),
(err: unknown) =>
toast.show({
variant: "error",
message: `Copy failed: ${err instanceof Error ? err.message : String(err)}`,
}),
)
}

useBindings(() => ({
bindings: [
{ key: "escape", desc: "Close about", group: "Dialog", cmd: () => dialog.clear() },
{ key: "return", desc: "Close about", group: "Dialog", cmd: () => dialog.clear() },
{ key: "c", desc: "Copy diagnostics", group: "Dialog", cmd: copy },
],
}))

return (
<box paddingLeft={2} paddingRight={2} gap={1} paddingBottom={1}>
<box flexDirection="row" justifyContent="space-between">
<text fg={theme.text} attributes={TextAttributes.BOLD}>
About Kilo CLI
</text>
<text fg={theme.textMuted} onMouseUp={() => dialog.clear()}>
esc
</text>
</box>

<box gap={1}>
Comment thread
IamCoder18 marked this conversation as resolved.
Resolved
<text fg={theme.textMuted} wrapMode="word">
Open source AI coding agent. Access hundreds of models through Kilo Gateway.
</text>

<box gap={0}>
<text fg={theme.text} attributes={TextAttributes.BOLD}>
Identity
</text>
<Row theme={theme} label="Version" value={InstallationVersion} />
<Row theme={theme} label="Channel" value={InstallationChannel} />
</box>

<box gap={0}>
<text fg={theme.text} attributes={TextAttributes.BOLD}>
Runtime
</text>
<Row theme={theme} label="Runtime" value={`${runtime()} (${process.platform}/${process.arch})`} muted />
<Row theme={theme} label="Config" value={truncate(Global.Path.config, 60)} muted />
<Row theme={theme} label="Project" value={truncate(projectRoot(), 60)} muted />

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above comment about privacy mode.

</box>

<box gap={0}>
<text fg={theme.text} attributes={TextAttributes.BOLD}>
Provider
</text>
<Row theme={theme} label="Connected" value={providers()} />
<Row theme={theme} label="Default model" value={defaultModel() || "(none)"} muted={!defaultModel()} />
</box>

<box gap={0}>
<text fg={theme.text} attributes={TextAttributes.BOLD}>
Links
</text>
<For each={links}>
{(link) => (
<text fg={theme.accent} wrapMode="word">
{" "}
{link.label}: {link.url}
</text>
)}
</For>
</box>
</box>

<box flexDirection="row" justifyContent="flex-start">
<text fg={theme.textMuted} onMouseUp={copy}>
c copy diagnostics
</text>
</box>
</box>
)
}
13 changes: 13 additions & 0 deletions packages/opencode/src/kilocode/kilo-commands.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { DialogClawUpgrade } from "./components/dialog-claw-upgrade.js"
import { DialogIndexing } from "./components/dialog-indexing.js"
import { indexingEnabled } from "./indexing-feature"
import { refreshBalance } from "./balance-refresh"
import { showAboutDialog } from "./cli/cmd/tui/component/dialog-about.js"

Comment thread
IamCoder18 marked this conversation as resolved.
Resolved
// These types are OpenCode-internal and imported at runtime
type UseSDK = any
Expand Down Expand Up @@ -269,6 +270,18 @@ export function registerKiloCommands(useSDK: () => UseSDK) {
}
},
},

// /about command
{
name: "kilo.about",
title: "About",
desc: "Show version, environment, and diagnostic info",
category: "Kilo",
slashName: "about",
run: () => {
showAboutDialog(dialog)
},
},
].map((command) => ({
namespace: "palette",
...command,
Expand Down
Loading