{"id":51949708,"url":"https://github.com/niksavis/terminal","last_synced_at":"2026-07-29T04:30:42.684Z","repository":{"id":370902407,"uuid":"1297674966","full_name":"niksavis/terminal","owner":"niksavis","description":"Cross-platform terminal setup for WezTerm + WSL (zsh, tmux, starship) with reproducible CLI tooling and a live cheat sheet.","archived":false,"fork":false,"pushed_at":"2026-07-23T06:49:13.000Z","size":825,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-07-23T08:10:04.872Z","etag":null,"topics":["cli-tools","dev-environment","developer-experience","dotfiles","starship","terminal","tmux","wezterm","wsl","zsh"],"latest_commit_sha":null,"homepage":"https://niksavis.github.io/terminal/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/niksavis.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-07-11T18:05:49.000Z","updated_at":"2026-07-23T06:49:14.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/niksavis/terminal","commit_stats":null,"previous_names":["niksavis/terminal"],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/niksavis/terminal","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/niksavis%2Fterminal","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/niksavis%2Fterminal/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/niksavis%2Fterminal/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/niksavis%2Fterminal/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/niksavis","download_url":"https://codeload.github.com/niksavis/terminal/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/niksavis%2Fterminal/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":36018011,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-07-20T02:08:10.276Z","status":"online","status_checked_at":"2026-07-29T02:00:04.910Z","response_time":95,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cli-tools","dev-environment","developer-experience","dotfiles","starship","terminal","tmux","wezterm","wsl","zsh"],"created_at":"2026-07-29T04:30:41.992Z","updated_at":"2026-07-29T04:30:42.670Z","avatar_url":"https://github.com/niksavis.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# terminal\n\nCross-platform terminal environment setup for developers using coding agents. Install WezTerm, WSL2 Ubuntu tooling, zsh, tmux, starship, and an agent-first CLI toolchain with one idempotent setup flow.\n\n## Quick install\n\nPrerequisites: [uv](https://docs.astral.sh/uv/) and Python 3.14+. On Windows, install WSL2 Ubuntu.\n\nInstall everything (tools + configs) directly from `main` — no clone required:\n\n```bash\nuvx --from git+https://github.com/niksavis/terminal@main terminal-setup\n```\n\nAlready installed? Re-apply only the configs (fast, no package installs) — for example after a config update:\n\n```bash\nuvx --from git+https://github.com/niksavis/terminal@main terminal-setup --only config\n```\n\nFor a reproducible install pinned to a version, use the command shown on the [latest release](https://github.com/niksavis/terminal/releases/latest) page.\n\nNo admin rights are needed on Windows, WSL, or macOS: tools install into `~/.local` (or via Homebrew on macOS). Add `--system-install` for a system-wide install through apt/brew. On a native Linux host the default installs via apt and uses sudo.\n\n## Overview\n\nIf you use Claude Code, Copilot CLI, or similar agents, this repo gives you:\n\n- A consistent terminal stack across Windows+WSL, Linux, and macOS.\n- Better defaults for multitasking: WezTerm + tmux + zsh + starship.\n- Fast CLI tools agents rely on: ripgrep, fd, bat, jq/yq, lazygit, uv, and more.\n- Managed runtimes in WSL/Linux: Python via uv and Node.js (latest v24), matching the Windows versions.\n- Safe re-runs: missing tools install, up-to-date tools skip, and updates prompt for `y/n`.\n- No admin needed by default: tools install user-locally into `~/.local`; the setup reports conflicts with any system copies (with versions) and can remove the duplicates. Use `--system-install` for a system-wide install.\n\n## Contributor setup (required once after clone)\n\n```bash\ngit clone https://github.com/niksavis/terminal.git\ncd terminal\nuv sync\nnpm install\nuv run pre-commit install --install-hooks --hook-type pre-commit --hook-type commit-msg --hook-type pre-push\nuv run pre-commit run --all-files\nuv run pytest tests/\n```\n\nRun the setup flow after your contributor environment is ready:\n\n```bash\nuv run python setup-terminal.py\n```\n\nOptional validation:\n\n```bash\nuv run python setup-terminal.py --only check\nuv run python setup-terminal.py --dry-run\nuv run python setup-terminal.py --only report\n```\n\n## What's here\n\n- **Terminal setup** — Python package in [`terminal_setup/`](terminal_setup/) that detects the platform, checks prerequisites, installs tools, and deploys configs.\n- **Config templates** — [`wezterm.lua`](terminal_setup/templates/wezterm.lua), [`.tmux.conf`](terminal_setup/templates/tmux.conf), [`.zshrc`](terminal_setup/templates/zshrc), [`starship.toml`](terminal_setup/templates/starship.toml), [`micro-settings.json`](terminal_setup/templates/micro-settings.json), and [`statusline.sh`](terminal_setup/templates/statusline.sh) (Claude Code status line).\n- **Cheat sheet** — [Live HTML](https://niksavis.github.io/terminal/) and [`terminal-cheat-sheet.md`](terminal-cheat-sheet.md) source with Linux commands, shell shortcuts, tmux controls, and WezTerm shortcuts.\n- **Agent skills (optional)** — many provided tools have companion skills in [`.claude/skills/`](.claude/skills/). For now, copy the skills you want into your own repository manually.\n\n### Install with an AI coding agent\n\nCopy and paste the prompt below into your coding agent (GitHub Copilot, Claude Code, etc.) after cloning this repo. The agent will run the setup for you and report what it changed.\n\n```text\nInstall this repository's terminal setup from the current directory.\n\n1. Ensure uv (https://docs.astral.sh/uv/) and Python 3.14+ are available. If missing, stop and tell me what to install.\n2. Run `uv run python setup-terminal.py` (user-local, no admin required).\n3. Only if a system-wide install is explicitly wanted, run `uv run python setup-terminal.py --system-install` (needs admin/sudo).\n4. If any sudo/password or y/n update prompt appears, pause and ask me.\n5. When done, run `uv run python setup-terminal.py --only report` and summarize what was installed, skipped, and any manual next steps.\n```\n\n## Quick start\n\n### Windows\n\nAfter installation, start WezTerm from the Start menu or run:\n\n```powershell\nwezterm\n```\n\nWezTerm is configured to open WSL2 Ubuntu by default. The first time it starts, you will be in a zsh shell with tmux, starship, lazygit, direnv, just, fzf, and the extra CLI tools ready.\n\nPress `Ctrl + Shift + l` for the launch menu to switch shells: **Ubuntu (WSL)** (default), **PowerShell** (pwsh 7), **Git Bash** (shown when Git for Windows is installed), and **Command Prompt**. The setup wires the same Starship prompt into PowerShell 7 (`$PROFILE`) and Git Bash (`~/.bashrc`), sharing one `~/.config/starship.toml` on the Windows host, so those native shells match the WSL prompt. Command Prompt is left plain (cmd has no Starship prompt hook).\n\nThe default Starship prompt is single-line for readability and now includes project context modules (git state/metrics, common runtimes, and container context) before the prompt symbol.\n\nLinux-style shortcuts are enabled in WezTerm: use `Ctrl + Shift + t` for a new tab, `Ctrl + Shift + c` to copy, and `Ctrl + Shift + v` to paste. To split a pane, press `Ctrl + Shift + Space` (leader) then `-` (vertical) or `backslash` (horizontal). To close a pane, press `Ctrl + Shift + Space` then `x`.\n\n### WSL2 Ubuntu\n\nIf you prefer to work inside an existing WSL terminal, run the setup there too:\n\n```bash\nuv run python setup-terminal.py\n```\n\nThis installs the same tools and configs directly on the WSL host. Then start a new zsh shell:\n\n```bash\nzsh\n```\n\n### Linux / macOS\n\nRun the setup directly on the host:\n\n```bash\nuv run python setup-terminal.py\n```\n\nThen start WezTerm from your application launcher or run:\n\n```bash\nwezterm\n```\n\n## Daily controls\n\n### WezTerm\n\n| Action                    | Shortcut                                                        |\n| ------------------------- | --------------------------------------------------------------- |\n| New tab                   | `Ctrl + Shift + t`                                              |\n| Close tab                 | `Ctrl + Shift + w`                                              |\n| Copy selection            | `Ctrl + Shift + c`                                              |\n| Paste                     | `Ctrl + Shift + v`                                              |\n| Search in scrollback      | `Ctrl + Shift + f`                                              |\n| Jump to previous prompt   | `Ctrl + Shift + Up`                                             |\n| Jump to next prompt       | `Ctrl + Shift + Down`                                           |\n| Quick-select URL/text     | `Ctrl + Shift + p`                                              |\n| Launcher (profiles/tabs)  | `Ctrl + Shift + l`                                              |\n| Copy with mouse           | Select text and release left button                             |\n| Paste with mouse          | Right-click                                                     |\n| Split horizontal (direct) | `Ctrl + Alt + backslash`                                        |\n| Split vertical (direct)   | `Ctrl + Alt + -`                                                |\n| Close pane (direct)       | `Ctrl + Alt + x`                                                |\n| Next tab                  | `Ctrl + Tab`                                                    |\n| Previous tab              | `Ctrl + Shift + Tab`                                            |\n| Split vertical            | `Ctrl + Shift + Space` then `-` or `s`                          |\n| Split horizontal          | `Ctrl + Shift + Space` then `backslash`, `pipe`, or `v`         |\n| Move between panes        | `Ctrl + Shift + Left/Right` or `Ctrl + Shift + Space` then `h`/`j`/`k`/`l` |\n| Zoom pane                 | `Ctrl + Shift + Space` then `z`                                 |\n| Close pane                | `Ctrl + Shift + Space` then `x`                                 |\n| Rename tab                | `Ctrl + Shift + Space` then `,`                                 |\n| Switch workspace          | `Ctrl + Shift + Space` then `w`                                 |\n| Toggle fullscreen         | `Alt + Enter`                                                   |\n| Increase font size        | `Ctrl + Shift + =`                                              |\n| Decrease font size        | `Ctrl + Shift + -`                                              |\n| Reset font size           | `Ctrl + 0`                                                      |\n| Open config               | `Ctrl + Shift + Space` then `.`                                 |\n\n`Ctrl + Shift + Space` is the WezTerm leader key with a 3-second timeout. Press and release `Ctrl + Shift + Space`, then press the second key. Plain `Ctrl + Space` is the tmux prefix, so the leader must not shadow it, and the readline shortcuts `Ctrl + A` (beginning-of-line) and `Ctrl + E` (end-of-line) stay untouched. Jump to previous/next prompt needs the OSC 133 prompt marks emitted by the deployed zshrc.\n\n### tmux\n\n| Action             | Shortcut                                |\n| ------------------ | --------------------------------------- |\n| Prefix key         | `Ctrl + Space`                          |\n| New window         | `Ctrl + Space` then `c`                 |\n| Next window        | `Ctrl + Space` then `n`                 |\n| Previous window    | `Ctrl + Space` then `p`                 |\n| Reload config      | `Ctrl + Space` then `r`                 |\n| Split vertical     | `Ctrl + Space` then `\\|`                |\n| Split horizontal   | `Ctrl + Space` then `-`                 |\n| Move between panes | `Ctrl + Space` then `h`/`j`/`k`/`l`     |\n| Resize pane        | `Ctrl + Space` then `H`/`J`/`K`/`L`     |\n| Zoom pane          | `Ctrl + Space` then `m`                 |\n\nSee [`terminal-cheat-sheet.md`](terminal-cheat-sheet.md) for the full command reference.\n\nWezTerm and tmux shortcuts in this README are project-defined keybindings from [`terminal_setup/templates/wezterm.lua`](terminal_setup/templates/wezterm.lua) and [`terminal_setup/templates/tmux.conf`](terminal_setup/templates/tmux.conf). They are intentionally included in the cheat sheet alongside native Linux commands.\n\n## Starship prompt\n\nThe prompt is intentionally single-line and context-rich. It is configured in [`terminal_setup/templates/starship.toml`](terminal_setup/templates/starship.toml) and deployed to `~/.config/starship.toml`.\n\nA typical prompt looks like:\n\n```text\n~/projects/terminal  main !? +12-3 py:v3.14.0 took 30s \u003e\n```\n\n| Segment               | Meaning                                               |\n| --------------------- | ----------------------------------------------------- |\n| `~/projects/terminal` | Current directory (truncated to repo root)            |\n| ` main`              | Git branch                                            |\n| `!?`                  | Git status (`!` modified, `?` untracked, etc.)        |\n| `+12-3`               | Git line metrics for staged/unstaged changes          |\n| `py:v3.14.0`          | Runtime context for active project tools              |\n| `took 30s`            | Duration of the last command (shown when over 500 ms) |\n| `\u003e`                   | Prompt character (red if the last command failed)     |\n| `✦1`                  | Number of background jobs (only shown when present)   |\n\nThe prompt uses the Tokyo Night color palette and keeps all segments on one line for readability.\n\n## Claude Code status line\n\nWhen [Claude Code](https://claude.com/claude-code) is installed (`~/.claude` exists), the setup deploys a responsive status line to `~/.claude/statusline.sh` and registers it in `~/.claude/settings.json` (existing settings are preserved). It shows the model and reasoning effort, git repo/branch/state, gauges for context-window and 5-hour/weekly rate-limit usage (green → yellow → red), session cost with burn rate, and lines changed — using the same Tokyo Night palette as the prompt. Segments shorten and drop by priority as the terminal narrows.\n\nOn Windows the status line is installed into **both** Claude Code homes so it looks the same wherever you open `claude`: the WSL `~/.claude` (Claude launched from WezTerm's Ubuntu shell) and the Windows-native `%USERPROFILE%\\.claude` (Claude launched from PowerShell 7 or Git Bash). Windows-native Claude runs the status line through Git Bash, so that half is installed only when Git for Windows is present; the single bash script is shared across all of them (it strips the CR that Windows `jq` adds to its output).\n\nNerd Font icons are used by default (WezTerm ships a Nerd Font). Pass `--no-nerd-font` for the universal build that renders in any font, or `--skip-claude` to skip it. If Claude Code is not installed, this step is a no-op. To re-apply the configuration later — including an updated status line — without reinstalling packages, run `--only config`; an existing `~/.claude/statusline.sh` is overwritten (logged in the output), while other keys in `settings.json` are preserved.\n\n## What gets installed\n\n### Common baseline (all supported platforms)\n\n- Core shell tools: `zsh`, `tmux`, `git`, `curl`, `wget`\n- Agent-first CLI tools: `lazygit`, `git-lfs`, `direnv`, `just`, `fzf`, `fd`/`fd-find`, `bat`, `ripgrep`, `jq`, `yq`, `shellcheck`, `tree`, `xh`, `ast-grep`, `sd`, `git-delta`, `typos`, `uv`\n- Runtimes (WSL/Linux/macOS): `node` (latest v24, user-local in `~/.local`)\n- Config files: `wezterm.lua`, `.tmux.conf`, `.zshrc`, `starship.toml`, micro `settings.json`, and `~/.claude/statusline.sh` (Claude Code status line, when Claude Code is installed)\n\n`lazygit` and `node` are installed from the latest upstream release archives (not distro/Homebrew package versions) and their downloads are sha256-verified against the published checksum files.\n\n### Platform differences\n\n#### Windows (PowerShell / Git Bash)\n\n- Targets WSL2 Ubuntu as the primary shell environment\n- Windows host installs: WezTerm and Starship from portable release archives into `%LOCALAPPDATA%\\Programs\\` (no admin rights or MSI needed; existing winget installs are detected and kept), plus the VS Code Remote - WSL extension\n- WSL aliases: `fd` -\u003e `fdfind`, `bat` -\u003e `batcat`\n- Config destinations: Windows `wezterm.lua` under `%USERPROFILE%\\.config\\wezterm\\`, WSL files under `~`\n\n#### Linux / macOS / WSL terminal\n\n- Installs directly on the current host\n- WezTerm install path: `apt` repo / `pacman` / `dnf` / Homebrew cask (platform-dependent)\n- Starship install path: Linux install script or Homebrew on macOS\n- Config destinations: all files under `~` on the host\n\n## CLI options\n\n```bash\nuv run python setup-terminal.py --only check # verify prerequisites, then exit\nuv run python setup-terminal.py --dry-run    # preview changes\nuv run python setup-terminal.py --only config # re-apply all configs (incl. Claude status line); no package installs\nuv run python setup-terminal.py --only report # print verification summary, then exit\nuv run python setup-terminal.py --report     # run setup, then print verification summary\nuv run python setup-terminal.py --skip-vscode # skip VS Code: settings/extensions\nuv run python setup-terminal.py --skip-starship # skip starship prompt\nuv run python setup-terminal.py --skip-claude # skip the Claude Code status line\nuv run python setup-terminal.py --no-nerd-font # install the universal (no Nerd Font) status line\nuv run python setup-terminal.py --system-install # install system-wide via apt/brew (needs sudo/admin)\nuv run python setup-terminal.py --no-sudo    # force the user-local path; skip missing base packages\nuv run python setup-terminal.py --system-versions uninstall # remove system tool versions without prompting\nuv run python setup-terminal.py --system-versions keep # keep system tool versions; only warn\nuv run python setup-terminal.py --windows-terminal-cwd \"D:\\\\Workspace\" --wsl-terminal-cwd \"$HOME/workspace\" # optional user-specific cwd values\n```\n\nBy default the setup installs user-locally: on Windows and inside WSL every managed tool goes under `~/.local` without sudo, even when a system copy already exists, so re-running updates everything from one place. `--system-install` opts into the system-wide package-manager path (apt/brew, needs sudo/admin). On a native Linux host the default stays on apt (a user-local host install is not yet implemented there); macOS uses Homebrew, which needs no admin either way. The deprecated `--user-install` flag is a no-op kept for compatibility.\n\nAfter installing, the setup reconciles duplicates: it reports every tool present both in `~/.local/bin` and system-wide, with both versions (for example `lazygit: user-local 0.63.0 vs system 0.60.0`), then asks per tool whether to remove the system copy. `--system-versions uninstall` removes them all without prompting (requires sudo); `--system-versions keep` only reports. Headless runs never prompt or hang; they report and explain instead.\n\n`--windows-terminal-cwd` and `--wsl-terminal-cwd` are optional user-specific values. No personal paths are hardcoded by default.\n\n\u003e **Note:** On Windows, WezTerm and Starship are always installed from portable release archives to `%LOCALAPPDATA%\\Programs\\` and the user PATH is updated (no admin rights or MSI needed). You must restart your terminal for the new PATH to take effect; until then the setup report marks them OK with a restart hint.\n\n## Command-line editing\n\nThe zsh configuration uses Emacs-style readline shortcuts. These work in any terminal and are the fastest way to edit long commands without reaching for the mouse:\n\n| Shortcut       | Action                                      |\n| -------------- | ------------------------------------------- |\n| `Ctrl + A`     | Move cursor to start of line                |\n| `Ctrl + E`     | Move cursor to end of line                  |\n| `Shift + Home` | Select from cursor to start of line         |\n| `Shift + End`  | Select from cursor to end of line           |\n| `Backspace`    | Delete selection or character before cursor |\n| `Delete`       | Delete selection or character under cursor  |\n| `Ctrl + U`     | Delete from cursor to start of line         |\n| `Ctrl + K`     | Delete from cursor to end of line           |\n| `Ctrl + W`     | Delete previous word                        |\n| `Alt + D`      | Delete next word                            |\n| `Ctrl + Y`     | Paste the last deleted text                 |\n| `Ctrl + L`     | Clear screen                                |\n\n`Shift + Home` and `Shift + End` are bound in zsh to create a selection region; once text is selected, `Backspace` or `Delete` removes it just like on Windows.\n\n## Troubleshooting\n\n### `xdg-desktop-portal` warning when starting WezTerm in WSL\n\nYou may see a warning like this on WSL2 Ubuntu:\n\n```text\nWARN window::os::x11::connection \u003e Unable to resolve appearance using xdg-desktop-portal:\norg.freedesktop.DBus.Error.ServiceUnknown: The name org.freedesktop.portal.Desktop was not\nprovided by any .service files\n```\n\nThis is **harmless and expected**. The setup is intentionally lightweight: it targets a minimal WSL2 environment used as a virtual Linux machine inside Windows, not a full Linux desktop distribution. WezTerm hard-codes a dark color scheme so it does not need to query the desktop environment, but the underlying X11 connection still logs the missing portal service. Installing `xdg-desktop-portal` and its GTK/KDE backend would pull in GUI dependencies and a D-Bus session manager, which conflicts with the goal of keeping WSL lean. The warning does not affect WezTerm functionality.\n\n## Development\n\nContributor environment setup (dependencies and git hooks) is covered under [Contributor setup](#contributor-setup-required-once-after-clone). Once that is done, run the test suite and checks manually with:\n\n```bash\nuv run pytest tests/\nuv run python .scripts/git-hooks/pre-commit.py\n```\n\n## VS Code\n\nWorkspace settings, recommended extensions, tasks, and launch configs are committed in [`.vscode/`](.vscode/). Open the repo in VS Code and install the recommended extensions when prompted.\n\n## License\n\n[MIT](LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fniksavis%2Fterminal","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fniksavis%2Fterminal","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fniksavis%2Fterminal/lists"}