The Terminal app in macOS keeps track of recent commands you've used so you can reuse them at a later time. Here's how to clear Terminal's command history.
When you type commands and press return in macOS's Terminal app, it remembers the commands you type and stores them, in case you want to reuse the same commands again later.
In Terminal, you can press the Up and Down arrow keys on your Mac's keyboard to cycle through all recent commands. As you do, Terminal replaces whatever is on the command line prompt with each command in the stored command history as you press the arrow keys.
You can cycle forward or backward through your command history in Terminal and press return at any saved command to run it again.
You might want to remove the Terminal's command history for security reasons, or you might be working on one task with certain technologies and then switch to some other task in Terminal using other technologies that use a different set of commands.
Shell variants and dumb terminals
Early UNIX computers were created in 1970 and used dumb terminals connected to mainframe computers on which users had time-share accounts. Each user would use a terminal to connect to the mainframe computer which actually executed commands entered in the terminal.
Early makers of dumb terminals included Digital Equipment Corporation, UNISYS, Wang, WYSE, Lear Siegler, and others. Even earlier - in the 1960s IBM sold large stand-alone paper terminals such as the IBM 2741 which included its own desk-like stand.
One company, Carterfone, was one of the first to allow dumb terminals to connect field remote mainframe computers and run commands via an acoustically-coupled telephone modem - a device that converted computer signals into sound.
In the early 1970s, Lear Siegler released a series of what would become popular dumb terminals starting with the ADM-1 in 1972, and later the wildly popular ADM-3A.
All of this was before the personal computer revolution of the late 1970s. Today, people run UNIX-variant operating systems on their PCs and use built-in terminal or shell apps to communicate with the OS on the same machine.
Lear Siegler was purchased in 1986 by Wall Street investment firms and its divisions and technology were sold to several other companies. By this time the personal computer boom was well underway and dumb terminals faded in popularity.
Once modular phone line jacks were introduced in the early 1980s, several home computer makers including Apple, Atari, and Commodore sold their own phone modems.
WYSE was later bought by DELL which still sells "thin client" computers which are essentially today's successors to dumb terminals. Some very early UNIX systems had paper-based terminals instead of displays.
For a brief period in the 1980's, AT+T made and sold combined PCs which acted both as personal computers, dumb terminals, and included integrated phone and fax systems.
AT+T had been heavily involved in creating UNIX at Bell Labs in the late 1960's and early 1970's.
Over the decades, there have been several variations of shell programs in the UNIX operating system (on which macOS is based).
Shells simply refer to command prompt programs that allow UNIX users to enter text commands to be run by the OS. A shell is essentially a command interpreter and scripting engine for running typed commands, or multiple commands in series from a file.
The macOS Terminal is simply a macOS app that sits on top of a shell program.
There have been several variants of UNIX shells over the decades, including the Bourne-again shell, the Bash shell from the GNU project, Korn shell (ksh), C shell (csh), ZShell (zsh), Fish, and others.
Most UNIX shells conform to the IEEE POSIX standard ISO/IEC/IEEE 9945:2009 Shell and Tools.
POSIX is an acronym for Portable Operating System Interface - an IEEE standard and trademark. POSIX was created to provide a single compatible standard for both operating systems and application APIs across different platforms.
There are many good books available on POSIX. There is also a standard POSIX multitasking programming library called pthreads.
Shells in macOS
For decades Apple used the Bash shell as macOS's standard shell. When Apple released macOS Catalina, it changed the default shell to zsh. Both shells are similar with a few minor differences.
The real reason Apple chose to switch from Bash to zsh in macOS is really about licensing. Bash is now under the GPL v3 license which is incompatible with some of Apple's open source policies.
For the most part, anything you can do in Bash you can also do in zsh. So the change isn't an issue for most users.
The one major difference is that some shell scripts in zsh require the shebang line at the top of every script file to run properly. The shebang line is usually either #!/bin/bash
or #!bin/bash/sh
.
You can learn more about the zsh shell at zsh.org.
Using the history command
zsh includes the history
command, which is part of the GNU History Library.
In macOS Terminal, to use the history
command, simply type history
into the Terminal and press Return. By default, the history
command prints the most recent sixteen commands typed into the Terminal.
Controlling and clearing zsh history
Previous versions of the zsh and other shells provide a -c
flag to be used with the history
command. The -c
flag could be used to clear the Terminal history in macOS, but as of macOS Catalina, the -c
flag is no longer supported for the history
command.
If you're using zsh, to clear the Terminal history, instead use the -p
flag, which accomplishes the same thing. Type history -p
into the Terminal and press Return.
All shell history is cleared instantly - without warning.
Another way to clear zsh history in macOS is to edit the hidden history file itself.
Two hidden files in your macOS's user folder define how zsh behaves, and how zsh history is saved. These files are .zshrc, and .zsh_history, respectively.
In macOS, hidden files and folders in the filesystem begin with a period (".") in their filenames. We've previously detailed on AppleInsider how to show or hide hidden files in the Finder.
To get started showing invisible files in Finder, if you haven't already, you'll need to show your Startup Disk on the Finder's Desktop by turning on Hard disks in the Finder->Settings window from the menu item in the Finder's menu bar.
.zshrc is a profile, or configuration file which defines shell environment variables, paths to other shell files or UNIX command programs, and the export of shell and environment variables to the system and other programs.
.zshrc gets read and loaded by the system when you log in as a user on your Mac.
.zsh_history is a plain text file which stores all the commands you've previously used in macOS's Terminal app. Every time you type a command in Terminal and press Return, the command gets saved in .zsh_history.
To clear and reset your zsh history, quit Terminal first, then open the .zsh_history file, delete its contents, save it, then log out and log back into macOS or Restart your Mac.
You can also delete the .zsh_history file itself if Terminal isn't running, then log out and back in or Restart. Terminal will automatically recreate the file the next time you run it and enter a command at the command prompt.
Programming with the GNU History Library
It turns out the GNU History Library (GNUHL) is quite powerful and provides its own programming API in the C programming language. Most of what zsh does in the history command is accomplished by calling the GNUHL.
GNUHL can read zsh history, its stored commands, and pipe the commands as input to other new commands programmatically.
There are many GNU History Library programming tutorials online.
The main history data type for GNUHL is a C struct
, or structure of type _hist_entry
:
typedef struct _hist_entry { char *line; char *data; } HIST_ENTRY;
The typedef
declaration in C defines a new type name based on a predefined type - in this case HIST_ENTRY
is defined to be the same as struct _hist_entry
.
typedef
in C allows you to shorten variable declarations in code by not having to use the struct
declaration for each declared variable. Instead, in this case, you could just use HIST_ENTRY
, which would shorten the code.
Each field in the _hist_entry
type is of type char
, or character. The char
type in C is used to represent one character of text (think of it as a container for a letter, number, or symbol).
A char *
variable is simply a C pointer - a variable that holds a memory address that points to something. C strings in memory are usually represented by a pointer to an array of char
variables.
C structures allow programmers to easily bundle several variables into one larger grouped variable for easier access later. Each member variable in a C structure is called a field.
So when you enter a line in macOS's Terminal app, the shell creates a new _hist_entry
for each command, stores it in memory, and writes its *data
field out to the .zsh_history file.
The next time you open Terminal, it reads the history file back in and reconstructs the history list using an array of _hist_entry
entries in memory.
In C programming you can define an array of variables using either the []
syntax, or by using a pointer or handle to an array in memory. A handle in C is a pointer to another pointer in memory and is indicated by a double asterisk: **
.
Early Mac programming used handles extensively, and we won't get into all the details of why handles exist - but suffice it to say it allows an operating system to move variables around in memory without programmers having to keep track of the moves.
In GNUHL a handle to the history list can be defined as a single handle pointing to the start of the array of history entries. In C:
HIST_ENTRY **the_history_list;
The GNUHL also keeps a single state structure which defines the current state of the history library at any given moment in time, as defined by the _hist_state
data type:
typedef struct _hist_state
We won't get into the details of the _hist_state
structure here. For more information check out the GNU History Library programming documentation.
Suffice it to say the _hist_state
struct contains a handle to the array of history entries, the offset into the history entry array in bytes, the number of stored entries, the number of possible slots for entries, and some flags.
Once you have a pointer or handle to a _hist_state
structure, you can walk the history entry array and inspect each entry.
There is also an extensive C API for manipulating the history list including adding, removing, and replacing entries, getting state, getting info about the history list, navigating the list, and searching.
There are also APIs for manipulating the history file itself. Using plain C programming, it's fairly easy to read, search, and modify the history. The GNUHL programming documentation provides several examples in C.
The history of UNIX and terminals is fascinating - and the macOS Terminal is a powerful way to use UNIX commands on the Mac. Using Terminal's history allows you to quickly reuse complex Terminal commands without having to retype them each time.