# fix(review): codex discovery honors CODEX_HOME (Bugbot finding)

`bf34f40`→[main](/content/gh/entireio/cli/commits/main/index.html)·

peyton-alt·1w ago·2 files·+23 added/-4 removed

Discovery walked ~/.codex via UserHomeDir while every other codex-agent
path resolves through resolveCodexHome, which honors CODEX_HOME — so
skills installed under a custom codex home were invisible to discovery
and spawn-time validation rejected saved $skills as 'not installed'
even though codex itself finds and runs them. Discovery now uses the
canonical resolution; the fake-home test helper also pins CODEX_HOME
empty so a dev shell's value can't leak into the hermetic tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

## Sessions

01KX0Y35F2WQNBG14701C9WNWFView transcript

[?\
test(review): pin that codex $name skills survive the legacy repair + native invocationClaude Code·33 steps](/content/gh/entireio/cli/session/99f0d90a-6e31-4c60-ba62-aa2dccd29033#timeline-01KX0Y35F2WQNBG14701C9WNWF/index.html)

## Changes

2

- cmd/entire/cli/agent/codex

- Mdiscovery.go+4/-4
  
  - Mdiscovery_test.go+19
  
  
  ```
  2 unmodified lines

3
  4
  5
  6
  6
  7
  8
  19 unmodified lines

28
  29
  30
  32
  31
  32
  33
  34
  34
  35
  36
  37
  37
  38
  39
  40

2 unmodified lines

import (
      "context"
      "log/slog"
      "os"
      "path/filepath"

"github.com/entireio/cli/cmd/entire/cli/agent"
  19 unmodified lines

//
  //nolint:unparam // error return is part of SkillDiscoverer contract; future implementations may report hard failures
  func (c *CodexAgent) DiscoverReviewSkills(ctx context.Context) ([]agent.DiscoveredSkill, error) {
      home, err := os.UserHomeDir()
      // resolveCodexHome is the agent's canonical config-tree resolution
      // (honors CODEX_HOME) — discovery must see the same skills codex runs.
      codexHome, err := resolveCodexHome()
      if err != nil {
          logging.Debug(ctx, "codex discovery: UserHomeDir failed", slog.String("error", err.Error()))
          logging.Debug(ctx, "codex discovery: resolve codex home failed", slog.String("error", err.Error()))
          return nil, nil
      }
      codexHome := filepath.Join(home, ".codex")

form := skilldiscovery.DollarForm
      var found []agent.DiscoveredSkill
  ```

Mcmd/entire/cli/agent/codex/discovery.go+4/-4

```
  18 unmodified lines

19
  20
  21
  22
  23
  24
  25
  87 unmodified lines

113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133

18 unmodified lines

t.Helper()
      home := t.TempDir()
      t.Setenv("HOME", home)
      t.Setenv("CODEX_HOME", "") // hermetic: a dev shell's CODEX_HOME must not leak in
      return home
  }

87 unmodified lines

t.Errorf("want only $code-reviewer; got %+v", skills)
  }
  
  // TestCodexAgent_DiscoverReviewSkills_HonorsCodexHome pins discovery to the
  // agent's canonical home resolution: the rest of the codex agent resolves its
  // config tree through resolveCodexHome (which honors CODEX_HOME), so skills
  // installed under a custom codex home must be discoverable too — otherwise
  // saved $skills fail spawn-time validation as "not installed" even though
  // codex itself finds and runs them.
  func TestCodexAgent_DiscoverReviewSkills_HonorsCodexHome(t *testing.T) {
      // Cannot t.Parallel — uses t.Setenv.
      withFakeHome(t) // HOME points at an empty dir; the skill lives elsewhere
      codexHome := t.TempDir()
      t.Setenv("CODEX_HOME", codexHome)
      writeSkill(t, codexHome, "skills/code-review", "code-review", "Reviews code.")

if !nameOf(discover(t), "$code-review") {
          t.Fatal("skill under CODEX_HOME not discovered — discovery must use resolveCodexHome, not ~/.codex")
      }
  }
  ```

Mcmd/entire/cli/agent/codex/discovery_test.go+19
