100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Programming

Your First Tcl Script

Write, run, and extend a first Tcl script — from a simple puts statement to procedures, control flow, and a minimal Tk GUI.

FoundationsBeginner8 min readJul 10, 2026
Analogies

Writing a Hello World Script

The smallest useful Tcl script is a single line: puts "Hello, world!", where puts writes its string argument to standard output followed by a newline (use puts -nonewline to suppress it). Comments start with # as the first non-whitespace character of a command — importantly, # only introduces a comment where a new command is expected, so a stray # after other content on the same logical line (without a preceding ;) is not treated as a comment, which trips up newcomers coming from languages where # always comments out the rest of a physical line.

🏏

Cricket analogy: Just as the very first ball of a match is a simple, low-risk delivery to get things underway, puts "Hello, world!" is the simplest possible Tcl statement to get a script running and producing visible output.

Adding Logic: Procedures and Control Flow

A reusable block of logic is defined with proc name {args} {body}, e.g. proc greet {name} { puts "Hi, $name!" }, and called just like any built-in command: greet Ada. Control flow uses if/elseif/else for branching and foreach/while/for for iteration, all following the same brace-quoted-body convention already covered, so foreach n {1 2 3} { puts $n } prints each of 1, 2, and 3 on its own line, and if {$score >= 80} { puts pass } else { puts fail } branches on a boolean expression.

🏏

Cricket analogy: Just as a bowling coach teaches a repeatable bowling action that any bowler can then execute on demand, proc greet {name} { ... } defines a repeatable block of logic that can be called on demand with greet Ada.

Taking Input

Reading a line typed by the user is done with gets stdin line, which reads one line of standard input into the variable line and returns the number of characters read (or -1 at end-of-file), so a common pattern is puts -nonewline "Name: "; flush stdout; gets stdin name. Command-line arguments passed to a script are available as the list $argv (and its count as $argc), while $argv0 holds the script's own invocation name, letting a script branch on how many arguments were supplied with if {$argc != 2} { puts "Usage: $argv0 <a> <b>" ; exit 1 }.

🏏

Cricket analogy: Just as an umpire waits for the bowler to complete their delivery before signaling the outcome, gets stdin line waits for the user to type a full line and press Enter before the script continues.

From Console Script to Tk GUI

Turning a console script into a graphical one starts with package require Tk (unnecessary under wish, which loads it automatically), after which widgets like label .l -text "Enter your name:", entry .e -textvariable name, and button .b -text OK -command { puts "Hello, $name!" } are created and then placed on screen with a geometry manager, most simply pack .l .e .b. Event handling beyond button clicks uses bind, e.g. bind .e <Return> { puts "Hello, $name!" } runs the same script when the Enter key is pressed while the entry widget has focus, which is how Tk GUIs respond to keyboard and mouse events generally, not just predefined widget actions.

🏏

Cricket analogy: Just as a broadcaster adds a graphical scoreboard overlay on top of the raw video feed to make it watchable for fans, package require Tk adds a graphical widget layer on top of a plain Tcl script's console output.

tcl
#!/usr/bin/env tclsh
# hello.tcl - a first Tcl script with input and a proc

proc greet {name} {
    puts "Hi, $name! Welcome to Tcl."
}

puts -nonewline "What is your name? "
flush stdout
gets stdin userName
greet $userName

foreach n {1 2 3} {
    puts "Countdown: $n"
}
tcl
#!/usr/bin/env wish
# hello_gui.tcl - the same greeting, as a small Tk GUI

label .l -text "Enter your name:"
entry .e -textvariable name
button .b -text OK -command { puts "Hello, $name!" }
bind .e <Return> { puts "Hello, $name!" }

pack .l .e .b -padx 10 -pady 5

Run console scripts like hello.tcl with tclsh and GUI scripts like hello_gui.tcl with wish (or add package require Tk at the top and keep using tclsh). Mixing them up isn't fatal — tclsh can load Tk on demand — but using wish for GUI scripts avoids needing that extra line.

  • puts "text" writes a string plus a trailing newline to standard output; puts -nonewline suppresses it.
  • # starts a comment only where a new command is expected, not anywhere in the middle of a line.
  • proc name {args} {body} defines a reusable command; it is then called just like a built-in command.
  • if/elseif/else handle branching, and foreach/while/for handle iteration, using the same brace-body convention.
  • gets stdin line reads a line of user input; $argv, $argc, and $argv0 give access to command-line arguments.
  • package require Tk (automatic under wish) unlocks widgets like label, entry, and button, laid out with pack.
  • bind attaches a script to a specific event, such as <Return>, generalizing Tk's event handling beyond simple button clicks.

Practice what you learned

Was this page helpful?

Topics covered

#Programming#TclTkStudyNotes#YourFirstTclScript#Tcl#Script#Writing#Hello#StudyNotes#SkillVeris#ExamPrep