CatchError runs the given script in a catch wrapper and returns the result. If anything in the script throws an uncaught error a diagnostic message is written to stderr and the program exits with an exit code of one.

Note that in CatchError there's a commented-out line. This is a variant of the line which actually runs the script. The commented-out version will, instead of a script, run a single command without it needing to be enclosed in braces.

Perhaps the script version should use script instead of args.

# \
exec tclsh "$0" "$@"

proc CatchError {args} {

        puts "args = #[llength $args]"
#       if {![catch {set r [uplevel $args]} err]} {return $r}
        if {![catch {set r [uplevel eval $args]} err]} {return $r}
        puts stderr $err
        exit 1

CatchError { if {true} {puts "Hello, this is a test"} }
CatchError {
                set fd [open "catcherror" "r"]
                set b [read $fd]
                close $fd
                puts "catcherror size = [string length $b]"