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
tclshfrom a Bash tool often resolves to the MSYS/Git-for-Windows tclsh; run this to get the machine-readable verdict on whichtclsh.exewins and what it shadows, instead of guessing. - An "invalid command name X" error where X might be an
X.exeon PATH clashing with a Tcl command (dir,sort,find,clipare classic). Thetcl_conflictsfield 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;textis a plain-ASCII fixed-key layout;dictreturns 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 hasovershadowed: 0- that is what a bare command name resolves to. All later copies of the same name haveovershadowed: 1andovershadowed_by= the winning entry'sidx. - Tcl-command clash:
tcl_conflictslists{command, match}pairs wherecommandis the resolved Tcl command name (namespace origin) andmatchisexact(case-identical) ornocase(case-differing). An empty list means the PATH executable does not clash with any resolvable Tcl command in-context. shown_entries<path_entriesmeans the binglob/pathglob filtered some entries out; that is expected when you pass a name.overshadowed_byis an entry idx, not an exe name - cross-reference it againstentries[].idxto name the shadowing copy.
Caveats
- This is PATH-resolution and Tcl-command-clash only. It is NOT a general
"what is installed" /
whichreplacement 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_ofrefers to a PATH DIRECTORY appearing more than once (the later copies have no own executable list); it is not the same asovershadowed(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 dictreturns the same structure as a dict;punk::path -return jsonround-trips to the same data (decode via tcllib json and recompare - the G-173 acceptance criterion).