You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

6.6 KiB

name description
punkpath Use to resolve which PATH executable a bare command name actually runs (and what shadows it), and whether a PATH executable clashes with a Tcl command - the two questions agents guess wrong when debugging test failures or 'invalid command name X' errors. Cost: one ~0.7s side-effect-free punkshell invocation. Returns JSON via 'punk91 src script -e {punk::path -return json <name>}' listing PATH entries whose executables match the name, each with overshadowed/overshadowed_by (entry idx) and tcl_conflicts (command:match=exact|nocase) fields. Not a general 'what is installed' tool - PATH shadowing and Tcl-command clash only.

punkpath

PATH-executable resolution and Tcl-command clash diagnosis for the punkshell repo - the "which tclsh will I actually get, and does X.exe shadow a Tcl command?" answer that agents guess wrong. Asks the live interpreter via punk::path -return json, so the verdict is the OS PATH-resolution truth (first non-shadowed entry wins), not a guess from which/where or a single-env-var read.

When to use

  • A test run fails in a way that smells like the wrong interpreter (spurious Tcl-version failures, msys path semantics). The tcl-runtests skill warns that bare tclsh from a Bash tool often resolves to the MSYS/Git-for-Windows tclsh; run this to get the machine-readable verdict on which tclsh.exe wins and what it shadows, instead of guessing.
  • An "invalid command name X" error where X might be an X.exe on PATH clashing with a Tcl command (dir, sort, find, clip are classic). The tcl_conflicts field reports the resolved Tcl command and the exact|nocase match.
  • Before asserting an external tool is available, or which copy of a duplicate (e.g. several tclsh.exe) the shell will execute.

Command

Run from the repo root (punk91 lives in bin/, so bin/punk91 from the Bash tool). punk91 embeds Tcl 9.1; punk905 (Tcl 9.0) or punksys (Tcl 8.6) take the same one-liner. Cost: ~0.7s filtered, ~0.7s full PATH, no side effects (read-only).

bin/punk91 src script -e 'punk::path -return json ?-pathglob <pat>?... ?-context <ns>? ?-conflicts 0|1? ?<binglob>...?'
  • -return json - machine-readable; the only form worth parsing. table (default) is the human ANSI table; text is a plain-ASCII fixed-key layout; dict returns a Tcl dict. All three non-table forms are ANSI-free regardless of other options.
  • <binglob>... - executable-name glob filter (default * = all). Pass a bare name (tclsh) or glob (tclsh*, dir) to narrow to the executables you care about. ALWAYS filter by name unless you genuinely need the whole PATH (the unfiltered scan returns every executable on PATH - thousands).
  • -pathglob <pat>... - filter PATH entries by directory (case-insensitive glob on the directory path). Default * = all PATH entries. Use to narrow "which scoop shims provide X" etc.
  • -context <namespace> - the namespace whose commands are checked for conflicts. Default empty = the caller's namespace. PASS THIS when invoked through a wrapper/one-liner (src script -e) to make the conflict verdict stable and meaningful; the default-caller behaviour is for interactive use. :: checks the global namespace.
  • -conflicts 0|1 - default 1 (compute Tcl conflicts). Set 0 to skip for a small perf win when you only care about overshadowing; the conflict fields are then empty.

Load noise ("src mode: registered ...") goes to stderr; read stdout only (append 2>/dev/null in bash). Prefer the Bash tool over the PowerShell tool (attached consoles flip punkshell's terminal detection).

Output structure (JSON)

{
  "summary": {
    "context": "::", "is_windows": 1, "separator": ";",
    "path_entries": 130,          # total PATH entries scanned
    "shown_entries": 6,            # entries with matching executables
    "executable_total": 6,          # matching executables across shown entries
    "overshadowed_total": 5,        # how many are shadowed by an earlier entry
    "conflict_total": 0            # how many clash with a Tcl command
  },
  "entries": [{
    "idx": 0,                      # PATH order index (0 = first on PATH)
    "path": "C:\\Program Files\\Git\\mingw64\\bin",
    "normalised": "...", "is_directory": 1,
    "is_duplicate": 0, "duplicate_of": -1,   # same dir appearing again on PATH
    "exe_count": 55, "overshadowed_count": 0,
    "executables": [{
      "name": "tclsh.exe",
      "overshadowed": 0,            # 1 = an earlier PATH entry also has this exe
      "overshadowed_by": -1,        # entry IDX (into entries[]) that shadows it
      "tcl_conflicts": []           # list of {command, match}
    }]
  }, ...]
}

Reading the verdict

  • Which copy wins: the first entry (lowest idx) whose executable has overshadowed: 0 - that is what a bare command name resolves to. All later copies of the same name have overshadowed: 1 and overshadowed_by = the winning entry's idx.
  • Tcl-command clash: tcl_conflicts lists {command, match} pairs where command is the resolved Tcl command name (namespace origin) and match is exact (case-identical) or nocase (case-differing). An empty list means the PATH executable does not clash with any resolvable Tcl command in -context.
  • shown_entries < path_entries means the binglob/pathglob filtered some entries out; that is expected when you pass a name.
  • overshadowed_by is an entry idx, not an exe name - cross-reference it against entries[].idx to name the shadowing copy.

Caveats

  • This is PATH-resolution and Tcl-command-clash only. It is NOT a general "what is installed" / which replacement and does not report non-PATH tools, shell builtins, or aliases.
  • The conflict verdict depends on -context (which namespace's commands are resolvable). The default (caller's namespace) is wrong for a wrapper/one-liner invocation - pass -context :: or the target namespace explicitly.
  • is_duplicate/duplicate_of refers to a PATH DIRECTORY appearing more than once (the later copies have no own executable list); it is not the same as overshadowed (an executable name repeated across different directories).
  • Full (unfiltered) output is large - thousands of executables across the whole PATH. Filter by name unless you need the whole picture.
  • From Tcl code, punk::path -return dict returns the same structure as a dict; punk::path -return json round-trips to the same data (decode via tcllib json and recompare - the G-173 acceptance criterion).