## punkshell - an alternative Tcl Shell BSD-2-Clause license (see `LICENSE.txt`) Version 0.11.0 (2026-07) — this is **alpha** level software and still highly experimental. See `CHANGELOG.md` for recent changes. ### Supported Platforms - Tcl 8.6+ required; Tcl 9.0 and 9.1 supported. - Primary target: Windows (win32-x86_64). Linux, macOS, and FreeBSD are secondary targets. ### Getting Started The project uses a Tcl-based build system (`src/make.tcl`). From the project root: ``` # Fetch a suitable Tcl runtime (cross-platform polyglot wrapper — runs from bash, powershell, or cmd.exe) ./bin/runtime.cmd fetch # Build modules and libraries into the project root tclsh src/make.tcl packages # Full build (modules + libraries + VFS + binaries) tclsh src/make.tcl project ``` See `src/README.md` for detailed build instructions and `bin/AGENTS.md` for the runtime manager. For evaluating uncommitted source without a full build, a built executable can run directly against the source tree: ``` src shell ``` ### Features - default ansi color output - toggle with 'colour on' and 'colour off' (or set NO_COLOR environment variable) - convenient and comprehensive in-terminal display of tk, web and terminal ANSI colour names and codes. - rendering of old-school Ansi art (cp437) in the terminal ![Ansi art courtesy of roy-sac.com](hype_roysac.png?raw=true "Ansi cp437 art") - Relatively easy compositing of text blocks containing Ansi colour codes - (or rendered versions of ansi containing movement and other controls) ``` proc welcome_test {} { package require textblock package require punk::ansi package require overtype set ansi [textblock::join -- " " [punk::ansi::ansicat src/testansi/publicdomain/roysac/roy-welc.ans 80x8]] # Ansi art courtesy of Carsten Cumbrowski aka Roy/SAC - roysac.com set table [[textblock::spantest] print] set punks [a+ web-lawngreen][>punk . lhs][a]\n\n[a+ rgb#FFFF00][>punk . rhs][a] set ipunks [overtype::renderspace -width [textblock::width $punks] [punk::ansi::enable_inverse]$punks] set testblock [textblock::testblock -size 15 rainbow] set contents $ansi\n[textblock::join -- " " $table " " $punks " " $testblock " " $ipunks " " $punks] set framed [textblock::frame -type arc -title [a+ cyan]Compositing[a] -subtitle [a+ red]ANSI[a] -ansiborder [a+ web-orange] $contents] } ``` ![textblock composition of Ansi strings](compositing_ansi.png?raw=true "Compositing Ansi in Tcl") - experimental functional/pattern-matching language features. (will not be performant until more work is done on script compilation) e.g.1 basic pipeline with 2 segments `var_pipe_output.= var_list.= list a b c |> string toupper` e.g.2 basic pattern-match multi-assignment to variables x y & z `x@0,y@1,z@2.= list a b c` equivalently: `x@,y@,z@.= list a b c` or even `x@,y@,z@= {a b c}` `x/0,y/1,z/2,zz/3.= list a b c` is similar - but the use of forward-slash instead of @ will not produce a mismatch if an index is out of range. where .= indicates following arguments form a command, and a plain = accepts only a single argument as a value The diminutive case of this is `x= "something"` as equivalent to `set x "something"` Assignment operations and pattern-matches are slightly optimised to bytecompile, but are unlikely to compete with raw Tcl commands performance-wise. e.g.3 destructuring pattern-match. Get value of key 'k1' from last item in a list of dicts. `x@end/@@k1.= list {k1 aaa} {k1 bb}` returns bbb There are many more pattern-matching features yet to be documented. - easy execution of externals commands with return of stdout, stderr and the exitcode of the process The run... commands use a very basic repl-telemetry system to output more information to the console than just the return value, but in a way which makes the return value clear. The telemetry only outputs if the command is the first word on the commandline. - `run ...` (return exitcode of process - and allows process writes to stderr/stdout to appear in console as they occur) - `runout [-n] ...` (return stdout of process - no output until completion) - `runerr [-n] ...` (return stderr of process - no output until completion) - `runx [-n] ...` (return a dict of stdout stderr exitcode - no output until completion) The run... commands attempt to make it clear if a called process outputs a trailing newline by displaying a trailing blank line. The optional `-n` argument can be used to suppress a trailing newline. `runout -n pwd` is thus **similar** to Tcl's `exec pwd` For simple cases `exec ` is fine - but the equivalent `runout -n ` when used in the shell will display exitcode and stderr separately (whilst returning only stdout) exec will return stdout and stderr together. If you are on a unix-like platform, or a windows platform which has something like msys2 to provide commands like 'which' and 'grep' in the path: Try `runx -n which grep nonexistant` vs `exec which grep nonexistant` to see the difference in terms of easy access to what was written to stderr vs stdout. The run... commands are intended as a supplement for rather than a replacement for Tcl's exec/open. - namespace browser (contextual - allowing running of commands within the active namespace - analogous to 'cd' for directories) - `n/` - display child namespaces of current namespace (alias `:/`) also `n/ ` to restrict output - `n/ ` - if the argument doesn't contain glob chars '*' or '?' - attempt to switch to a child namespace of that name. Analogous to `cd ` list any sub namespaces of the namespace we just switched to. - `n//` - display child namespaces and commands (alias `://`) with colourised indication of type such as proc,alias,ensemble,oo object,oo class,imported,exported where possible. (renamed aliases and builtins and commands loaded from binaries will appear unmarked) - `nn/` - move up one namespace towards root namespace '::' analogous to `cd ..` (alias `::/`) - `newns ` - create a child namespace called 'somename' and switch to it in one operation. (alias `:/new`) - cross-platform alternative to cd & ls/dir without invoking child processes. Display colourised listing of dirs and folders - with vfs indication. - `d/` - list current directory (alias `./`) also `d/ ` to restrict output - `d/ ` - switch to subdir and list contents in one operation - `dd/` - move up one directory and output listing. Roughly equivalent to `cd ..` followed by dir or ls (alias `../`) - `newdir ` - create a child directory and switch to it in one operation. - ` script` subcommand for reliable non-interactive script execution: - `punkexe script ?args?` — runs a script file with conventional `::argv0`/`::argv` - `commands | punkexe script` — runs piped stdin commands and exits at EOF (no trailing `exit` needed) - Honest exit codes (0 success, 1 error with errorInfo on stderr); no shellfilter transforms or logging side effects. - `lib:` resolution for scriptlib scripts: `punkexe script lib:hello` or bare `punkexe lib:hello` - pluggable console backends: the REPL can run against non-detectable terminal-like devices via `::opunk::Console` subclasses (ssh-channel, tk-widget, test-double), with size, eof, and capability answered by subclass overrides. - cross-platform runtime manager (`bin/runtime.cmd`): fetch, list, use, and run Tcl runtimes — works from bash, powershell, or cmd.exe. `list -remote` compares local vs server runtimes with sha1 verification. - Ability to create zipfs wrapped applications with all required libraries built in. - Additional libraries - improved fork of tcllib's imap4 (punk::imap4) - netbox client library (punk::netbox) - telnet client with support for cp437 e.g can render mapscii.me with mouse support, and can view the ANSI max-headroom movie at 1984.ws - A feature-rich argument processor (punk::args) that can be used purely to generate function documentation, or also to process and validate flags and values (punk::args) The argument processor/documentor can display command synopses, grids of applicable argument choices, and indications of when short-forms (prefixes for flags/arguments/values) are applicable. Commands documented with punk::args carry inline usage tables accessible via `i ` at the repl. - In-shell help system: `i ` shows documented usage tables; `i help` lists registered help topics (tcl, env, console, etc.) with per-topic documented usage. #### missing - raw mode REPL (read-eval-print-loop) to allow commandline completion etc (undergoing development). - documentation is incomplete, though the punk::args (PUNKARGS) system now provides inline usage tables and command documentation for many commands via `i ` at the repl. - tests coverage is growing but not yet comprehensive — characterization suites exist for punk::args, punk::ns, punk::lib, punk::libunknown, punk::mix, shellthread, shellfilter, and console, among others. - signal handling on unix-like platforms (ctrl-c implemented on windows only). #### very unripe parts: - shellfilter - api is clumsy - scriptlib - will likely be reorganised/pruned significantly - theming ### Documentation - `src/README.md` — detailed build instructions - `CHANGELOG.md` — version history and recent changes - `AGENTS.md` (root) + child AGENTS.md files — contributor guidance and project structure (DOX hierarchy) - `GOALS.md` — technical goal index with per-goal detail files under `goals/`