From 6e047e12726a4a5f62ce823b7d72353a9a089dca Mon Sep 17 00:00:00 2001 From: Kc Date: Sat, 15 Aug 2026 23:25:56 +0800 Subject: [PATCH 1/2] fix(skills): install Codex user skills to ~/.agents/skills --- internal/skills/registry/registry.go | 2 +- internal/skills/registry/registry_test.go | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/internal/skills/registry/registry.go b/internal/skills/registry/registry.go index 487e12ba3ac..83c376a9af5 100644 --- a/internal/skills/registry/registry.go +++ b/internal/skills/registry/registry.go @@ -69,7 +69,7 @@ var Agents = []AgentHost{ ID: "codex", Name: "Codex", ProjectDir: sharedProjectSkillsDir, - UserDir: ".codex/skills", + UserDir: sharedProjectSkillsDir, }, { ID: "gemini-cli", diff --git a/internal/skills/registry/registry_test.go b/internal/skills/registry/registry_test.go index 8472ae3af21..43c991f0bc0 100644 --- a/internal/skills/registry/registry_test.go +++ b/internal/skills/registry/registry_test.go @@ -114,6 +114,14 @@ func TestInstallDir(t *testing.T) { homeDir: "/home/monalisa", wantDir: filepath.Join("/tmp/monalisa-repo", ".agents", "skills"), }, + { + name: "codex user scope", + hostID: "codex", + scope: ScopeUser, + gitRoot: "/tmp/monalisa-repo", + homeDir: "/home/monalisa", + wantDir: filepath.Join("/home/monalisa", ".agents", "skills"), + }, { name: "gemini project scope", hostID: "gemini-cli", From b9908d170abb42bf83045652aedba94d7bca7b66 Mon Sep 17 00:00:00 2001 From: tommaso-moro Date: Tue, 25 Aug 2026 16:31:40 +0100 Subject: [PATCH 2/2] Support PI_CODING_AGENT_DIR for skills Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- internal/skills/registry/registry.go | 14 +++++++--- internal/skills/registry/registry_test.go | 22 +++++++++++++++- pkg/cmd/skills/install/install_test.go | 31 +++++++++++++++++++++++ 3 files changed, 63 insertions(+), 4 deletions(-) diff --git a/internal/skills/registry/registry.go b/internal/skills/registry/registry.go index 487e12ba3ac..4cd36afc500 100644 --- a/internal/skills/registry/registry.go +++ b/internal/skills/registry/registry.go @@ -31,7 +31,8 @@ const ( DefaultAgentID = "github-copilot" - claudeConfigDirEnv = "CLAUDE_CONFIG_DIR" + claudeConfigDirEnv = "CLAUDE_CONFIG_DIR" + piCodingAgentDirEnv = "PI_CODING_AGENT_DIR" sharedProjectSkillsDir = ".agents/skills" ) @@ -415,8 +416,15 @@ func (h *AgentHost) InstallDir(scope Scope, gitRoot, homeDir string) (string, er } return filepath.Join(gitRoot, h.ProjectDir), nil case ScopeUser: - if h.ID == "claude-code" { - if configDir := os.Getenv(claudeConfigDirEnv); configDir != "" { + var configDirEnv string + switch h.ID { + case "claude-code": + configDirEnv = claudeConfigDirEnv + case "pi": + configDirEnv = piCodingAgentDirEnv + } + if configDirEnv != "" { + if configDir := os.Getenv(configDirEnv); configDir != "" { return filepath.Join(configDir, "skills"), nil } } diff --git a/internal/skills/registry/registry_test.go b/internal/skills/registry/registry_test.go index 8472ae3af21..aa71ed7bb7c 100644 --- a/internal/skills/registry/registry_test.go +++ b/internal/skills/registry/registry_test.go @@ -44,6 +44,7 @@ func TestFindByID(t *testing.T) { func TestInstallDir(t *testing.T) { t.Setenv(claudeConfigDirEnv, "") + t.Setenv(piCodingAgentDirEnv, "") tests := []struct { name string @@ -90,7 +91,7 @@ func TestInstallDir(t *testing.T) { { name: "claude code user scope, respect env var", setup: func(t *testing.T) { - t.Setenv("CLAUDE_CONFIG_DIR", filepath.Join("/home", "monalisa", ".config", "claude")) + t.Setenv(claudeConfigDirEnv, filepath.Join("/home", "monalisa", ".config", "claude")) }, hostID: "claude-code", scope: ScopeUser, @@ -98,6 +99,25 @@ func TestInstallDir(t *testing.T) { homeDir: "/home/monalisa", wantDir: filepath.Join("/home", "monalisa", ".config", "claude", "skills"), }, + { + name: "pi user scope", + hostID: "pi", + scope: ScopeUser, + gitRoot: "/tmp/monalisa-repo", + homeDir: "/home/monalisa", + wantDir: filepath.Join("/home/monalisa", ".pi", "agent", "skills"), + }, + { + name: "pi user scope, respect env var", + setup: func(t *testing.T) { + t.Setenv(piCodingAgentDirEnv, filepath.Join("/home", "monalisa", ".config", "pi", "agent")) + }, + hostID: "pi", + scope: ScopeUser, + gitRoot: "/tmp/monalisa-repo", + homeDir: "/home/monalisa", + wantDir: filepath.Join("/home", "monalisa", ".config", "pi", "agent", "skills"), + }, { name: "cursor project scope", hostID: "cursor", diff --git a/pkg/cmd/skills/install/install_test.go b/pkg/cmd/skills/install/install_test.go index 9a78da48042..1d9eba5749c 100644 --- a/pkg/cmd/skills/install/install_test.go +++ b/pkg/cmd/skills/install/install_test.go @@ -1589,6 +1589,37 @@ func TestInstallRun(t *testing.T) { }, wantStdout: "Installed git-commit", }, + { + name: "respect pi coding agent dir env var for user scope", + setup: func(t *testing.T) { + t.Setenv("PI_CODING_AGENT_DIR", t.TempDir()) + }, + stubs: func(reg *httpmock.Registry) { + stubResolveVersion(reg, "monalisa", "skills-repo", "v1.0.0", "abc123") + stubDiscoverTree(reg, "monalisa", "skills-repo", "abc123", + singleSkillTreeJSON("git-commit", "treeSHA", "blobSHA")) + stubInstallFiles(reg, "monalisa", "skills-repo", "treeSHA", "blobSHA", gitCommitContent) + }, + opts: func(ios *iostreams.IOStreams, reg *httpmock.Registry) *InstallOptions { + t.Helper() + return &InstallOptions{ + IO: ios, + HttpClient: func() (*http.Client, error) { return &http.Client{Transport: reg}, nil }, + GitClient: &git.Client{RepoDir: t.TempDir()}, + SkillSource: "monalisa/skills-repo", + SkillName: "git-commit", + Agent: "pi", + Scope: "user", + ScopeChanged: true, + Telemetry: &telemetry.NoOpService{}, + } + }, + assert: func(t *testing.T) { + assert.FileExists(t, filepath.Join(os.Getenv("PI_CODING_AGENT_DIR"), "skills", "git-commit", "SKILL.md")) + assert.NoFileExists(t, filepath.Join(os.Getenv("HOME"), ".pi", "agent", "skills", "git-commit", "SKILL.md")) + }, + wantStdout: "Installed git-commit", + }, } for _, tt := range tests {