# iRules script stepper

> Run a short iRule snippet one command at a time and see what each command received after substitution, what it returned and which variables changed. The quickest way to understand quotes, braces, append, concat, incr and the branch if or switch took. Local, no network.

- Tool: https://ronutz.com/en/tools/f5-irules-script-stepper
- Family: Networking

---

## What it does

Runs a short snippet one command at a time and shows each command three ways: as written, as the words it actually received after Tcl substituted variables, commands and backslashes, and what it returned. Under each command you see the variables it changed, the branch `if` or `switch` took, and every expression it evaluated as a tree. Log lines are collected, and actions such as `pool`, `HTTP::redirect`, `drop` or `reject` are recorded rather than performed.

In **iRules** mode the request commands (`HTTP::uri`, `HTTP::host`, `HTTP::method`, `HTTP::header`, `IP::client_addr` and others) answer from an editable sample request, and a `when` block runs its body once as if the event had fired.

## How to read the steps

Commands are listed in the order they started. An indented command ran inside the one above it: in its body, or inside brackets while the outer command's words were being built, which means it finished before the outer command ran. "received" shows the words as the command got them; the dashed outline marks where each word begins and ends, which is what quoting decides.

## Worth knowing

- `"$a$b"` joins two values with nothing between; `"$a $b"` keeps the space.
- `append` adds text exactly as given; `concat` trims the white space at both ends of each argument, drops empty ones and joins the rest with single spaces; `lappend` adds list elements.
- A string with spaces is a list to `foreach`: `foreach item "red green blue"` runs three times.
- `incr` reads `010` as octal 8, so the result is 9.
- `switch` reads any word starting with a dash as an option. Put `--` before the value (F5 K15650046), or a value such as `-foo` breaks the command.
- An unbraced `expr` substitutes twice: if a variable holds `[log local0. "x"]`, that command runs (F5 K57410758). The "Double substitution" example shows it.

## Limits

This is a teaching interpreter, not TMM. It models the commands listed in this page's code and stops after 2,000 commands, at values over 1,000,000 characters, and at 200 levels of nesting. Arrays, `proc`, `regexp`, `table`, `after` and the filesystem are not modelled; commands F5 disables in iRules (K36322151) are not available either. Event timing, connection state and other events are out of scope. The tool is not offered over the API, because it executes the Tcl you give it.

## Sources

- [Tcl 8.4 manual: Tcl (the substitution rules)](https://www.tcl-lang.org/man/tcl8.4/TclCmd/Tcl.htm) (read 2026-10-03)
- [Tcl 8.4 manual: append](https://www.tcl-lang.org/man/tcl8.4/TclCmd/append.htm), [concat](https://www.tcl-lang.org/man/tcl8.4/TclCmd/concat.htm), [lappend](https://www.tcl-lang.org/man/tcl8.4/TclCmd/lappend.htm), [incr](https://www.tcl-lang.org/man/tcl8.4/TclCmd/incr.htm) and [switch](https://www.tcl-lang.org/man/tcl8.4/TclCmd/switch.htm) (read 2026-10-03)
- [F5 K6091: The version of Tcl used to develop iRules](https://my.f5.com/manage/s/article/K6091) (read 2026-10-03)
- [F5 K36322151: List of disabled Tcl commands for iRules (12.x - 17.x)](https://my.f5.com/manage/s/article/K36322151) (read 2026-10-03)
- [F5 K57410758: use curly braces to avoid double substitution](https://my.f5.com/manage/s/article/K57410758) (read 2026-10-03)
- [F5 K15650046: Tcl code injection security exposure](https://my.f5.com/manage/s/article/K15650046) (read 2026-10-03)
- [F5 iRules reference: log](https://clouddocs.f5.com/api/irules/log.html) (read 2026-10-02)

## Standards and references

- [F5 K6091: The version of Tcl used to develop iRules](https://my.f5.com/manage/s/article/K6091) - the iRules command set was developed from Tcl base version 8.4.6, which is used in all BIG-IP versions; the engine models that version
- [Tcl 8.4 manual: Tcl (the substitution rules)](https://www.tcl-lang.org/man/tcl8.4/TclCmd/Tcl.htm) - quotes allow substitution, braces prevent it, brackets run a command, and each character is processed exactly once; inside braces, braces nest and a brace quoted with a backslash is not counted, even between double quotes
- [Tcl 8.4 manual: append](https://www.tcl-lang.org/man/tcl8.4/TclCmd/append.htm) - append adds text exactly as given and creates the variable when it does not exist
- [Tcl 8.4 manual: concat](https://www.tcl-lang.org/man/tcl8.4/TclCmd/concat.htm) - concat trims each argument's leading and trailing white space and joins them with single spaces
- [Tcl 8.4 manual: lappend](https://www.tcl-lang.org/man/tcl8.4/TclCmd/lappend.htm) - lappend adds each value as one list element
- [Tcl 8.4 manual: incr](https://www.tcl-lang.org/man/tcl8.4/TclCmd/incr.htm) - incr requires an integer value and stores the result as a decimal string
- [Tcl 8.4 manual: switch](https://www.tcl-lang.org/man/tcl8.4/TclCmd/switch.htm) - the -exact, -glob, -regexp and -- options, fall-through bodies, default, and comments only inside bodies
- [F5 K57410758: warning [use curly braces to avoid double substitution]](https://my.f5.com/manage/s/article/K57410758) - expr, if and while substitute an unbraced argument a second time; the validator warning and the braced fix
- [F5 K36322151: List of disabled Tcl commands for iRules (12.x - 17.x)](https://my.f5.com/manage/s/article/K36322151) - iRules use Tcl 8.4.6 with a subset of commands disabled (file, socket, exec, glob, namespace, rename, time and others)
- [F5 iRules reference: log](https://clouddocs.f5.com/api/irules/log.html) - log ?-noname? ?facility.level? message; syslog keeps the first 1024 bytes
- [F5 iRules reference: HTTP::uri](https://clouddocs.f5.com/api/irules/HTTP__uri.html) - HTTP::uri returns the URI part of the request (path and query); the sample request answers it
- [F5 iRules reference: HTTP::host](https://clouddocs.f5.com/api/irules/HTTP__host.html) - HTTP::host returns the Host header value (with the port when it is not the standard one); the sample request answers it
- [Tcl 8.4.6 source code, tag core-8-4-6 on GitHub](https://github.com/tcltk/tcl/tree/core-8-4-6) - the reference interpreter: the engine was differential-tested against tclsh built from this tag (commit bf3eeadc)

## Related reading

- [Building strings in iRules: quotes, braces, append, concat and lists](https://ronutz.com/en/learn/irules-building-strings.md): Quotes substitute, braces do not, and brackets run a command: almost every surprise when an iRule builds a value comes from those three rules. Here is what Tcl does to each word before a command sees it, how append, concat and lappend differ, why a value with spaces is a list, and how double substitution lets data run as code.
