بنقرة واحدة
slash-commands
Developer guide for adding and implementing local slash commands in the Phosphor TUI.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Developer guide for adding and implementing local slash commands in the Phosphor TUI.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
Use when the user needs to query, filter, reshape, extract, create, or construct JSON data — including API responses, config files, log output, or any structured data — or when helping the user write or debug JSON transformations.
Use when the user needs help configuring Phosphor — working with phosphor.json, setting up providers, configuring LSPs, adding MCP servers, managing skills or permissions, or changing Phosphor behavior.
Use when the user wants to add, write, debug, or configure a Phosphor hook — gating or blocking tool calls, approving or rewriting tool input before execution, injecting context into tool results, or troubleshooting hook behavior in phosphor.json.
Use when creating a new builtin skill for Phosphor, editing an existing builtin skill (internal/skills/builtin/), or when the user needs to understand how the embedded skill system works.
Use when creating a new shell builtin command for Phosphor (internal/shell/), editing an existing one, or when the user needs to understand how commands are intercepted in Phosphor's embedded shell.
| name | slash-commands |
| description | Developer guide for adding and implementing local slash commands in the Phosphor TUI. |
Slash commands are typed in the prompt starting with a / (e.g., /menu, /stats, /goal). They are executed locally in the TUI layer and are strictly prevented from leaking into the LLM conversation history.
Phosphor uses a split architecture for slash commands:
internal/commands/slash_commands.go): A data-only package containing the list of available slash commands and their descriptions. This package is imported by the completions engine.internal/ui/model/ui.go): The TUI model maintains a dynamic map (m.slashHandlers) linking command names to handler methods that return a tea.Cmd./learn)While most slash commands are purely local (UI-only) and never reach the LLM, some commands are hybrid.
For instance, /learn <source> is typed in the TUI, but instead of being blocked, the handler translates it into a highly structured system-guided instruction prompt and calls m.sendMessage(prompt) to submit it to the LLM agent.
Because the generated prompt is in plain English and does not start with a /, it naturally bypasses the backend slash-prevention failsafes and leverages the agent's existing file/web tools to execute the command.
To add a new slash command /foo:
Open internal/commands/slash_commands.go and add a new entry to the SlashCommands slice:
{
Name: "foo",
Description: "Open the foo menu or trigger action",
}
Open internal/ui/model/ui.go and implement the handler method on the UI struct. The method must take args []string and return tea.Cmd:
// handleFooSlashCommand handles the "/foo" slash command.
func (m *UI) handleFooSlashCommand(args []string) tea.Cmd {
// Implement command logic here.
// For example, to open a dialog:
// m.dialog.OpenDialog(dialog.NewFoo(m.com))
return func() tea.Msg { return nil }
}
In internal/ui/model/ui.go, locate the registerSlashCommands method and map your command name to the handler:
func (m *UI) registerSlashCommands() {
m.slashHandlers = map[string]slashCommandHandler{
"goal": m.handleGoalSlashCommand,
"menu": m.handleMenuSlashCommand,
"stats": m.handleStatsSlashCommand,
"quit": m.handleQuitSlashCommand,
"foo": m.handleFooSlashCommand, // <-- Register your new handler here
}
}
Open internal/ui/model/ui_test.go and add a unit test to verify that the command executes properly, sanitizes the TUI input states, and triggers the expected side effect (e.g., opening a dialog):
func TestUI_HandleSlashCommand_FooOpensDialog(t *testing.T) {
t.Parallel()
tw := &testWorkspace{}
st := uistyles.CharmtonePantera()
ui := &UI{
com: &common.Common{
Workspace: tw,
Styles: &st,
},
}
ui.registerSlashCommands()
ui.dialog = dialog.NewOverlay()
ui.slashMode = true
ui.completionsOpen = true
ui.completions = completions.New(lipgloss.NewStyle(), lipgloss.NewStyle(), lipgloss.NewStyle())
// Call handleSlashCommand with /foo.
cmd := ui.handleSlashCommand("/foo")
require.NotNil(t, cmd)
// Verify that the dialog is open and states are cleaned up.
require.True(t, ui.dialog.ContainsDialog(dialog.FooID))
require.False(t, ui.slashMode)
require.False(t, ui.completionsOpen)
}
m.slashMode = false and calls m.closeCompletions() before executing any handler. You do not need to do this manually in your handler.m.hasSession() first and return util.ReportWarn if one is not active.