diff --git a/cmd/toolsrv/internal/exec/exec.go b/cmd/toolsrv/internal/exec/exec.go index f8b6eee..cd465f7 100644 --- a/cmd/toolsrv/internal/exec/exec.go +++ b/cmd/toolsrv/internal/exec/exec.go @@ -143,6 +143,14 @@ func executeSandboxed(ctx context.Context, toolPath, stdinData, cwd string, envE for k, v := range envExtra { envMap[k] = v } + // Prepend tools directory to PATH so meta-only cmd fields can reference other tools + if toolsDir := toolsrv.ToolsPath(); toolsDir != "" { + if existing := envMap["PATH"]; existing != "" { + envMap["PATH"] = toolsDir + ":" + existing + } else { + envMap["PATH"] = toolsDir + } + } // Compute NAMESPACE if not set if _, ok := envMap["NAMESPACE"]; !ok { if ns := Plan9Namespace(envMap); ns != "" { diff --git a/toolsrv/meta.go b/toolsrv/meta.go index e6584d7..e4a2735 100644 --- a/toolsrv/meta.go +++ b/toolsrv/meta.go @@ -187,10 +187,10 @@ func ToolInfoFromMeta(name string, m *MetaFile) ToolInfo { } } -// ResolveTool returns the executable path for a named tool. +// ResolveTool returns the command string for a named tool. // Resolution order: -// 1. ~/.config/ollie/tools/ (local wrapper wins over system binary) -// 2. .meta "cmd" field (after variant resolution; absolute path or bare name via $PATH) +// 1. ~/.config/ollie/tools/ (local script/binary) +// 2. .meta "cmd" field (returned as-is; it's a shell command string) // 3. exec.LookPath() as final fallback func ResolveTool(name string) (string, error) { // Local tools path always wins — allows wrappers to shadow system binaries. @@ -199,22 +199,11 @@ func ResolveTool(name string) (string, error) { return local, nil } - // Check .meta cmd field (after variant resolution). + // Check .meta cmd field — return as-is (shell command string, not a path to resolve). if m, err := LoadMetaFile(name); err == nil && m != nil { resolved := m.Resolve() if resolved != nil && resolved.Cmd != "" { - // Check tools path for the cmd name first - cmdLocal := filepath.Join(ToolsPath(), resolved.Cmd) - if info, err := os.Stat(cmdLocal); err == nil && !info.IsDir() { - return cmdLocal, nil - } - if filepath.IsAbs(resolved.Cmd) { - return resolved.Cmd, nil - } - if p, err := exec.LookPath(resolved.Cmd); err == nil { - return p, nil - } - return "", fmt.Errorf("tool %s: cmd %q not found in PATH", name, resolved.Cmd) + return resolved.Cmd, nil } }