Skip to content

Commit c5e6055

Browse files
anandgupta42claude
andcommitted
fix: replace fake slash commands with real TUI dialogs for create/install (#341)
Remove non-functional `/skill-create` and `/skill-install` slash commands that only pre-filled input text. Replace with real keybind actions in the `/skills` dialog: - `ctrl+n` (create) — opens `DialogPrompt` for skill name, then runs `altimate-code skill create` and shows result as toast - `ctrl+i` (install) — opens `DialogPrompt` for source (owner/repo, URL, or path), then runs `altimate-code skill install` and shows result Full CLI ↔ TUI parity: skill list → /skills dialog skill show → ctrl+o in dialog skill create → ctrl+n in dialog (input prompt) skill test → ctrl+t in dialog skill install → ctrl+i in dialog (input prompt) skill edit → ctrl+e in dialog Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 16050f3 commit c5e6055

2 files changed

Lines changed: 85 additions & 42 deletions

File tree

packages/opencode/src/cli/cmd/tui/component/dialog-skill.tsx

Lines changed: 85 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@ import { DialogSelect, type DialogSelectOption } from "@tui/ui/dialog-select"
22
import { createResource, createMemo } from "solid-js"
33
import { useDialog } from "@tui/ui/dialog"
44
import { useSDK } from "@tui/context/sdk"
5-
// altimate_change start — import helpers for tool detection and keybind support
5+
// altimate_change start — import helpers for tool detection, keybind support, and prompt dialog
66
import { detectToolReferences } from "../../skill-helpers"
77
import { Keybind } from "@/util/keybind"
88
import { useToast } from "@tui/ui/toast"
99
import { spawn } from "child_process"
10+
import { DialogPrompt } from "@tui/ui/dialog-prompt"
1011
// altimate_change end
1112

1213
export type DialogSkillProps = {
@@ -35,6 +36,74 @@ const SKILL_CATEGORIES: Record<string, string> = {
3536
}
3637
// altimate_change end
3738

39+
// altimate_change start — sub-dialogs for create and install
40+
function DialogSkillCreate() {
41+
const dialog = useDialog()
42+
const toast = useToast()
43+
44+
return (
45+
<DialogPrompt
46+
title="Create Skill"
47+
placeholder="my-tool"
48+
onConfirm={async (name) => {
49+
dialog.clear()
50+
toast.show({ message: `Creating ${name}...`, variant: "info" })
51+
try {
52+
const proc = Bun.spawn(["altimate-code", "skill", "create", name], {
53+
stdout: "pipe",
54+
stderr: "pipe",
55+
})
56+
await proc.exited
57+
const stdout = await new Response(proc.stdout).text()
58+
const stderr = await new Response(proc.stderr).text()
59+
if (proc.exitCode === 0) {
60+
toast.show({ message: `✓ Created skill "${name}"\n${stdout.trim()}`, variant: "success", duration: 5000 })
61+
} else {
62+
toast.show({ message: stderr.trim() || `Failed to create "${name}"`, variant: "error", duration: 5000 })
63+
}
64+
} catch {
65+
toast.show({ message: `Failed to create "${name}"`, variant: "error" })
66+
}
67+
}}
68+
onCancel={() => dialog.clear()}
69+
/>
70+
)
71+
}
72+
73+
function DialogSkillInstall() {
74+
const dialog = useDialog()
75+
const toast = useToast()
76+
77+
return (
78+
<DialogPrompt
79+
title="Install Skill (owner/repo, URL, or path)"
80+
placeholder="anthropics/skills"
81+
onConfirm={async (source) => {
82+
dialog.clear()
83+
toast.show({ message: `Installing from ${source}...`, variant: "info" })
84+
try {
85+
const proc = Bun.spawn(["altimate-code", "skill", "install", source], {
86+
stdout: "pipe",
87+
stderr: "pipe",
88+
})
89+
await proc.exited
90+
const stdout = await new Response(proc.stdout).text()
91+
const stderr = await new Response(proc.stderr).text()
92+
if (proc.exitCode === 0) {
93+
toast.show({ message: stdout.trim(), variant: "success", duration: 6000 })
94+
} else {
95+
toast.show({ message: stderr.trim() || `Failed to install from "${source}"`, variant: "error", duration: 5000 })
96+
}
97+
} catch {
98+
toast.show({ message: `Failed to install from "${source}"`, variant: "error" })
99+
}
100+
}}
101+
onCancel={() => dialog.clear()}
102+
/>
103+
)
104+
}
105+
// altimate_change end
106+
38107
export function DialogSkill(props: DialogSkillProps) {
39108
const dialog = useDialog()
40109
const sdk = useSDK()
@@ -79,7 +148,7 @@ export function DialogSkill(props: DialogSkillProps) {
79148
})
80149
})
81150

82-
// Keybind actions: view, edit, test
151+
// Keybind actions: view, edit, test, create, install
83152
const keybinds = createMemo(() => [
84153
{
85154
keybind: Keybind.parse("ctrl+o")[0],
@@ -141,6 +210,20 @@ export function DialogSkill(props: DialogSkillProps) {
141210
}
142211
},
143212
},
213+
{
214+
keybind: Keybind.parse("ctrl+n")[0],
215+
title: "create",
216+
onTrigger: async () => {
217+
dialog.replace(() => <DialogSkillCreate />)
218+
},
219+
},
220+
{
221+
keybind: Keybind.parse("ctrl+i")[0],
222+
title: "install",
223+
onTrigger: async () => {
224+
dialog.replace(() => <DialogSkillInstall />)
225+
},
226+
},
144227
])
145228
// altimate_change end
146229

packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx

Lines changed: 0 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -408,46 +408,6 @@ export function Prompt(props: PromptProps) {
408408
))
409409
},
410410
},
411-
// altimate_change start — skill management commands
412-
{
413-
title: "Create skill",
414-
value: "prompt.skill-create",
415-
category: "Skills",
416-
slash: {
417-
name: "skill-create",
418-
arguments: "<name>",
419-
},
420-
onSelect: () => {
421-
input.setText("/skill-create ")
422-
setStore("prompt", { input: "/skill-create ", parts: [] })
423-
input.gotoBufferEnd()
424-
toast.show({
425-
message: "Type a name, e.g.: /skill-create my-tool\nOr use CLI: altimate-code skill create <name>",
426-
variant: "info",
427-
duration: 5000,
428-
})
429-
},
430-
},
431-
{
432-
title: "Install skill",
433-
value: "prompt.skill-install",
434-
category: "Skills",
435-
slash: {
436-
name: "skill-install",
437-
arguments: "<source>",
438-
},
439-
onSelect: () => {
440-
input.setText("/skill-install ")
441-
setStore("prompt", { input: "/skill-install ", parts: [] })
442-
input.gotoBufferEnd()
443-
toast.show({
444-
message: "Type a source, e.g.: /skill-install anthropics/skills\nSupports: owner/repo, URL, or local path",
445-
variant: "info",
446-
duration: 5000,
447-
})
448-
},
449-
},
450-
// altimate_change end
451411
]
452412
})
453413

0 commit comments

Comments
 (0)