From 841f744a63cd1a06a2f6060a2561848371aacadf Mon Sep 17 00:00:00 2001 From: Jeremy Daer Date: Thu, 10 Sep 2026 12:43:58 -0700 Subject: [PATCH] Offer Grok's skills directory in fizzy skill install Add "Grok (Global)" to the skill install wizard's location list beside "Codex (Global)". Grok Build keeps its home at ~/.grok, overridable by GROK_HOME, and reads user skills from ~/.grok/skills/ -- the same shape Codex has with ~/.codex and CODEX_HOME. The Codex helper is generalized into agentGlobalSkillPath(homeEnv, homeDir) and called for both agents rather than copied. Grok also reads the cross-agent ~/.agents/skills/, so the shared baseline already reaches it; this row is the agent-local copy a user can choose, exactly as the Codex row is. Nothing more is added -- no detection, harness entry or setup handler -- because Codex has none of those in fizzy-cli either. README's list of agents gains Grok. A table-driven test covers both helpers' env override, blank override and default. --- README.md | 2 +- internal/commands/skill.go | 19 +++++++++++++++---- internal/commands/skill_test.go | 25 +++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index f0fb987..28c21f7 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ `fizzy` is a command-line interface for [Fizzy](https://fizzy.do). Manage boards, cards, comments, and more from your terminal or through AI agents. -- Works standalone or with any AI agent (Claude, Codex, Copilot, Gemini) +- Works standalone or with any AI agent (Claude, Codex, Copilot, Gemini, Grok) - JSON output with breadcrumbs for easy navigation - Token authentication via personal access tokens - Includes agent skill and Claude plugin setup diff --git a/internal/commands/skill.go b/internal/commands/skill.go index 84b6f4d..9c5370f 100644 --- a/internal/commands/skill.go +++ b/internal/commands/skill.go @@ -31,6 +31,7 @@ var skillLocations = []SkillLocation{ {Name: "OpenCode (Global)", Path: "~/.config/opencode/skill/fizzy/SKILL.md"}, {Name: "OpenCode (Project)", Path: ".opencode/skill/fizzy/SKILL.md"}, {Name: "Codex (Global)", Path: codexGlobalSkillPath()}, + {Name: "Grok (Global)", Path: grokGlobalSkillPath()}, } var skillCmd = &cobra.Command{ @@ -257,11 +258,21 @@ func normalizeSkillPath(path string) string { } func codexGlobalSkillPath() string { - codexHome := strings.TrimSpace(os.Getenv("CODEX_HOME")) - if codexHome == "" { - return "~/.codex/skills/fizzy/SKILL.md" + return agentGlobalSkillPath("CODEX_HOME", "~/.codex") +} + +func grokGlobalSkillPath() string { + return agentGlobalSkillPath("GROK_HOME", "~/.grok") +} + +// agentGlobalSkillPath locates the skill under an agent's home directory: +// homeEnv when set, otherwise homeDir. +func agentGlobalSkillPath(homeEnv, homeDir string) string { + home := strings.TrimSpace(os.Getenv(homeEnv)) + if home == "" { + return homeDir + "/skills/fizzy/SKILL.md" } - return filepath.Join(codexHome, "skills", "fizzy", skillFilename) + return filepath.Join(home, "skills", "fizzy", skillFilename) } // expandSkillPath expands ~ to home directory. diff --git a/internal/commands/skill_test.go b/internal/commands/skill_test.go index 893442b..c050bea 100644 --- a/internal/commands/skill_test.go +++ b/internal/commands/skill_test.go @@ -87,6 +87,31 @@ func TestExpandSkillPath(t *testing.T) { } } +func TestAgentGlobalSkillPath(t *testing.T) { + tests := []struct { + name string + env string + envVal string + path func() string + want string + }{ + {"codex default", "CODEX_HOME", "", codexGlobalSkillPath, "~/.codex/skills/fizzy/SKILL.md"}, + {"codex override", "CODEX_HOME", "/opt/codex", codexGlobalSkillPath, filepath.Join("/opt/codex", "skills", "fizzy", "SKILL.md")}, + {"codex blank override", "CODEX_HOME", " ", codexGlobalSkillPath, "~/.codex/skills/fizzy/SKILL.md"}, + {"grok default", "GROK_HOME", "", grokGlobalSkillPath, "~/.grok/skills/fizzy/SKILL.md"}, + {"grok override", "GROK_HOME", "/opt/grok", grokGlobalSkillPath, filepath.Join("/opt/grok", "skills", "fizzy", "SKILL.md")}, + {"grok blank override", "GROK_HOME", " ", grokGlobalSkillPath, "~/.grok/skills/fizzy/SKILL.md"}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Setenv(tt.env, tt.envVal) + if got := tt.path(); got != tt.want { + t.Errorf("%s = %q, want %q", tt.name, got, tt.want) + } + }) + } +} + func TestInstallSkillFiles(t *testing.T) { home := t.TempDir() t.Setenv("HOME", home)