GUSH - a Graphical User SHell - version 0.3.2


Gush integrates the functions of a shell, a "dumb" terminal and a pager like "more" or "less" to provide a more productive version of the traditional Unix command line. Some features:

  • Use mouse click or cursor keys to move the cursor anywhere.
  • New input can only be typed when cursor is in the input area, after all output.
  • Any text can be selected for copying by mouse or keyboard.
  • All output can be searched, and any new matches of the current search pattern are highlighted in output as it appears.
  • Different colours are used for stdin (blue), stdout (black), stderr (red).
  • Popup menus are used for history, file completion (easy to select from a long list without disturbing the terminal window contents).
  • Output from any backgrounded program will appear in its own screen area, not mixed up with other jobs.
  • Records per-directory command history, use command dirhist to view this, globhist for global history.
  • Right-click menu has options to change text wrap mode, font size, hide stdin/stdout/stderr text, undock a command into a separate window.

Terminal emulation is primitive, just scrolling "glass teletype" style output, curses-style terminal output is not currently supported. This does not seem to be too much of a limitation - nowadays most programs with a complex user interface run with a GUI in their own window. Gush is aimed at aiding interaction with traditional style text-stream-oriented unix tools. When character-graphical (curses-style) programs are required they need to be run in their own xterm window.

Bugs/features to colin(underscore)g(underscore)macleod(at)yahoo(dot)com please. License is BSD-type.


Distributed as one file from . It needs Tcl/Tk 8.4 or newer, Tclx and snit. If available it will use Tile widgets for updated appearance. An installation of ActiveTcl 8.4 [L1 ] will supply all the prerequisites.

There is code which is currently disabled (by "set catch_tty 0") which uses Expect (if available) to handle programs which write/read /dev/tty and pop-up a window for this I/O. Otherwise such output/input will go to the shell Gush was started from - not very helpful as it may not be visible.


The screen is divided into an output area which shows all output from commands run and cannot be edited, followed by an input area where commands and input to running commands can be typed and edited. Most keystrokes have their usual text editing and navigation functions, with exceptions described below. The whole output of commands run will be retained, and can be scrolled or searched. Program output to stderr is displayed in red, stdout is shown in black. If extra arguments are supplied on the command line when gush is started, they will be used as the first command to run.

Keystroke Functions in Input area

EnterWhen at the command prompt, run what has been typed in the input area as a command. If the command typed so far contains { or " or ' or [ without a corresponding closing } " ' or ] it will not be run and input will continue on the next line. If a command is currently running, the input will be sent as input to that program.
Shift-EnterAdd a new line to the input area, without sending it to be processed.
Control-wdelete previous word.
Control-udelete from current position to start of input area.
Control-cif entering a command, delete whole input area; if a command is running, kill it (send SIGTERM).
control-dif a command is running, close its input channel.
control-zif a command is running, leave it running but prompt for a new command. Subsequent output from the first command will appear at the end of its own output area, above the new command prompt. You can resume interaction with the first command later by moving it to new window.
Homego to start of input area.
Endgo to end of input area.
Escjumps to just before input area.
Up-arrowAt start of input area only, gives popup menu of command history for current session - use keyboard or mouse to select from menu or Esc to dismiss.
Tabdoes filename completion, giving a popup menu if there are multiple matches. Note that you can use glob patterns in the partial filename. If directories are matched they get submenus - use right-click or right-arrow to enter, or left-click or Enter-key to select the directory itself.
Insertinsert the currently selected text.
Control-fopen a search dialogue at the top of the screen where you can enter text or a regular expression to search for. Note that all occurrences of the string will be highlighted, and this continues incrementally as new program output appears on the screen. The cursor will be moved to the next or previous matched text when the Next or Prev buttons are clicked.
F1open help window.

Keystroke Functions in Output area

Enterjump back to last position in input area.
Insertjump back to last position in input area.
Control-PageUpjump to the previous command line.
Control-PageDownjump to the next command line.
spacepage forward
"b"page back
"/"start search forward
"?"start search backwards
"n"repeat search forward
"p"repeat search backwards

Mouse Functions

Left-clickmove cursor to point clicked.
Middle-clickcopies selected text to current insertion point in the input area.
Right-clickgive a popup menu of actions, details below.

The right-click menu options are:

Kill Jobwill kill (send SIGTERM to) this command's processes.
End Job Inputwill close the input channel to this command's processes.
Undock Job Windowwill move this command's whole input and output to a separate window (whether the command is complete or still running).
Hide Outputhides all standard output text from commands run.
Hide Errorhides all standard error text from commands run.
Hide Inputhides all standard input text sent to commands run.
Font Sizegives submenu of text font sizes.
Line Wrapgives submenu to switch text wrap mode - none/char/word. When wrap mode is none, a horizontal scrollbar will appear so that long lines can be seen by scrolling sideways.

Command Syntax

Usage is generally similar to other shells (particularly csh, the Berkeley C-Shell) with some differences. Each command typed is first tried as a Tcl command, if not defined in Tcl it will be run as an external command. The use of an external command can be forced by giving its path, eg. /usr/bin/file to get the Unix "file" command instead of the Tcl "file" command. Any file-matching patterns in the command line will be expanded to multiple arguments for the matching files. In particular [ ] matches the set of enclosed characters. If Tcl-style argument expansion is wanted this can be done by eval {tcl-style code}, eg. eval {set n [llength [glob *]}.

Within the command line, $_ can be used to substitute the standard output of the last command. The output of previous command number n can be substituted by $out(n) or $err(n) for its standard error output. Entering $(command) or putting back-quotes around command will run command and substitute its output into the command line.

Use "set name value" to set internal variables, whose value can be retrieved as $name. Environment variables can also be read with $name. Use "setenv name value" to set environment variables.

A command can be run "in the background" by ending it with &, so you will immediately get a new command prompt, however any output from that command will be shown in its own screen area, not mixed with the output of subsequent commands.Commands:

exitexit from gush.
historylists current session history.
dirhistshows history for the current directory, or "dirhist directoryname" for another directory.
globhist <time>shows global history across all sessions and directories since time specified, eg. "globhist yesterday". Globhist takes an optional pattern argument to show only commands matching the pattern, eg. "globhist 'last month' svn" to find subversion commands from the last month.
which <somecommand>reports whether a command is built-in (in Tcl) or if not reports the path it will be run from.
rehashclears the cache of paths to commands, this may be needed if PATH is changed or a new command is installed.
<directoryname>Typing just the name of a directory will do "cd directory" (as long as the same name is not also a command).
winwill cause the job it is part of it to be moved to a new window of its own.
xt <command>will run the supplied command in a separate xterm window. This is needed for character-graphical (curses-style) programs.



  • Window undock boundaries wrong.
  • Title of undocked window - should show command.
  • Auto-scroll not working in undocked window.
  • Not clear when undocked command has finished.
  • Treatment of current search/hilite when undocking?
  • File path globbing fails silently when unreadable directory matched!
  • File completion of paths containing spaces does not quote result, so not usable.
  • 'file *' broken, clash with internal Tcl file command (can use /bin/file *).
  • Backslash quoting of spaces not working.
  • ProgramX uses ESC[4mTicket: ESC[m in dialog - handle this?
  • ProgramY prompts for password ok but input typed appears on screen :-O


  • Better indication of state of jobs - running/succeeded/failed.
  • Job control - stop and continue, show live jobs.
  • Trap curses-style programs and move their output on-the-fly to an xterm?
  • set command limit so eg. "while 1 {}" doesn't hang program - needs Tcl8.5
  • History searching etc. (whole system pretty klunky at present).
  • Track history of input sent to an interactive command and provide readline/rlwrap-like functionality - or at least separate in-command history from shell history.
  • Collapse/expand individual/all jobs.
  • Support non-gui operation as fallback?
  • Some way for built-ins to work with pipelines??
  • Quick repeat for last (few) command(s).
  • Windows-ish environment variable editor ??
  • Easy way to feed tabular output (eg. from ls -l, or ps, into a table widget).
  • Etc., etc., etc.
  • (compare with 9term from Plan 9)

RFox - 2012-10-08 11:42:19

On Win7 64bit, this pops up an error dialog:

 can't set "ProgramFiles(x86)": variable isn't array 
 while executing...
 (file ....gush.tcl" line 83)

CGM 2012-10-09 I made a fix (v0.3.2) and uploaded to my ISP's web space (since I can't see how to upload an updated version of the file to the "half-bakery"). The problem was that I convert environment variables to variables in the slave interpreter so they can be accessed with shell-compatible syntax. However this breaks if one of them looks like an array element and another looks like the name of the same array, as happens with "ProgramFiles(x86)" and "ProgramFiles". In this case I now just catch the error and skip that variable.