When Convenience Costs Time: Completion, Git Status, and the Prompt

Oh My Zsh’s prompt and completion features make the shell feel informed before you ask it a question, but that feeling comes from work performed at startup and during interaction. This chapter examines two common sources of confusion: Git-aware prompt status and prepared completion state. The practical goal is diagnosis, not a universal performance promise—identify which subsystem is doing work, then change the narrowest control that addresses the symptom.

The prompt is a live query, not decoration

A prompt can look like a line of text, but a Git-aware prompt is closer to a small monitoring view. The default Robby Russell theme includes the current directory and calls a Git prompt helper. That helper first checks whether the current directory belongs to a Git repository. If it does, it tries to identify the current branch, an exact tag, or a short commit reference, then asks Git for working-tree and upstream status. A dirty marker is the visible result of those checks.

The distinction matters because the prompt is evaluated repeatedly. After a command finishes and before the next command is read, Zsh prepares the next prompt. If the prompt asks for repository state, the shell may perform repository queries again. Outside a Git repository, the helper can return no Git information. Inside one, the amount of work depends on the repository, the status being requested, and the functions included in the selected prompt. A prompt that is fast in a small project can feel different in a large working tree without the configuration having changed.

The status query is also more detailed than a branch-name lookup. The Git library parses porcelain status information, recognizes untracked, added, modified, renamed, deleted, unmerged, ahead, behind, diverged, and stashed states, and maps those states to prompt markers. It can inspect the upstream relationship as well as the working tree. That is useful operational context: a prompt can tell the user not only which branch is checked out, but whether local work differs from a remote tracking branch. It is also more work than printing the current directory.

The framework exposes ways to bound that work. A user can hide prompt information or status at the repository level, and the template provides a setting to stop treating untracked files as a source of dirty-state information. The Git code also controls how submodules are considered, with an option to let Git decide or to ignore submodule changes at a chosen level. These switches do not make Git status free; they change which questions the prompt asks. Suppressing untracked-file checks may make a large repository more responsive, but the prompt will no longer warn about that category of change.

That is the right way to describe a performance control: it trades information for less work. “Disable the dirty check” is not a neutral optimization if dirty state is the reason the prompt is useful. Conversely, keeping every possible status signal enabled is not automatically the more professional choice. The correct setting depends on whether the prompt is being used as a compact dashboard or merely as a location and branch indicator.

There is also a difference between local working-tree information and remote relationship information. A prompt can report that files are modified without asking how the local branch compares with its upstream. It can report ahead, behind, or diverged states when that relationship is available, but those states depend on the repository’s refs and remote configuration.