Per-project terminal profiles for iTerm2 (macOS) and Windows Terminal (Windows), safely via per-file JSON.
Project description
termprofiles
Per-project terminal profiles that feel native on macOS (iTerm2) and Windows (Windows Terminal), without hand-editing JSON.
Keywords: iTerm2 dynamic profiles, Windows Terminal fragments, per-project ZDOTDIR, developer automation CLI.
TermProfiles creates one JSON file per project so you can add or remove profiles safely. On macOS, each project gets its own ZDOTDIR (history + .zshrc), while Windows users receive tidy Windows Terminal fragments. Everything lives inside your home directory.
Contents
- Overview
- Supported Platforms & Requirements
- Installation
- Quick Start
- Command Reference
- How Profiles Are Structured
- macOS Details
- Windows Details
- Configuration & Environment Variables
- Example Workflows
- Troubleshooting & FAQ
- Uninstalling
- Contributing
- License
Overview
- Per-project profiles: Generates one dynamic profile (macOS) or fragment (Windows) per directory.
- Safe JSON handling: Files are written atomically with UTF-8 encoding to avoid corruption.
- No tmux required: Launch directly into the project directory with your preferred shell.
- Easy cleanup:
termprofiles removedeletes the generated JSON (and optional macOS ZDOTDIR). - Discoverable:
termprofiles listshows exactly what was created.
Supported Platforms & Requirements
macOS
- macOS 11 or newer recommended.
- iTerm2 with Dynamic Profiles enabled.
- Shell:
/bin/zshis used, but you can customize via the generated.zshrc.
Windows
- Windows 10 19041+ or Windows 11 with Windows Terminal 1.16 or newer.
- PowerShell installed (default). Optional: Git Bash, Command Prompt, or WSL.
Installation
TermProfiles is published on PyPI; choose one of the installation methods below.
Using pipx (recommended)
pipx installs packages in isolated virtual environments and adds entry points to your shell.
# macOS (optional helper if Homebrew is available)
brew install pipx
pipx ensurepath
exec $SHELL
# macOS or Windows
pipx install termprofiles
# Upgrade later
pipx upgrade termprofiles
Verify the installation:
termprofiles --help
Using pip
If you prefer a virtual environment or user-site install:
python -m venv .venv # optional virtual environment
source .venv/bin/activate # Windows: .venv\Scripts\activate
python -m pip install --upgrade pip
python -m pip install termprofiles
From source
git clone https://github.com/yaioyaio/termprofiles.git
cd termprofiles
pipx install . # or: python -m pip install .
Quick Start
macOS (iTerm2)
- Run
termprofiles add /path/to/project. - Reopen iTerm2 (or
Profiles → Other Actions → Reload All Profiles). - Launch the new profile named
proj-<slug>. - Enjoy an isolated
.zshrcand history backed by~/.zsh-profiles/<slug>/.
Example:
termprofiles add ~/dev/sample-app
Outputs something like Added: proj-sample-app and creates dp-sample-app.json in iTerm2's DynamicProfiles directory.
Windows (Windows Terminal)
- Run PowerShell as the user (no admin needed).
- Execute
termprofiles add "C:\\src\\sample-app". - Close and reopen Windows Terminal (or run
wt.exeagain). - Select the new profile
proj-sample-appfrom the dropdown.
By default the profile uses PowerShell and opens in your project directory.
Command Reference
termprofiles add <dir> [<dir> ...]
Create profiles for one or more project directories.
macOS options:
--parent-guid GUID— inherit UI from an existing iTerm2 profile.--parent-name NAME— locate a profile by name (case-insensitive) and use its GUID.
Windows options:
--color-scheme NAME— apply an existing Windows Terminal color scheme.--shell TYPE—powershell(default),cmd,git-bash,wsl,wsl:<alias>.--wsl-distro NAME— WSL distribution to launch (defaultUbuntu).--wsl-zdotdir PATH— exportZDOTDIRbefore startingzshin WSL.
termprofiles remove <target> [<target> ...]
Delete generated profiles. Each target can be the original directory or its slug.
- macOS: add
--keep-zdotdirto preserve~/.zsh-profiles/<slug>. - Windows: only the fragment JSON is removed.
termprofiles list
Show profiles discovered via the generated JSON files. Helpful for auditing or scripting.
termprofiles parents (macOS only)
Enumerate iTerm2 profiles detected in ~/Library/Preferences/com.googlecode.iterm2.plist with their GUIDs.
termprofiles setopt (macOS only)
Interactively toggle recommended setopt flags (e.g., NO_SHARE_HISTORY, SHARE_HISTORY, EXTENDED_HISTORY, INC_APPEND_HISTORY) for the current project's .zshrc, or run non-interactively via --enable SHARE_HISTORY --disable NO_SHARE_HISTORY. Changes are written atomically and active iTerm sessions using the same profile automatically source the updated file.
termprofiles prompt on|off|toggle (macOS only)
Enable, disable, or toggle the built-in prompt ([%F{cyan}<slug>%f] user@host path %#). When enabled, it overrides whatever prompt your inherited parent profile provides. The command rewrites the project .zshrc and reloads the profile in running tabs.
termprofiles new (macOS only)
Open a new iTerm window (or add --tab to open a tab) that uses the current project's profile, useful after tweaking settings.
How Profiles Are Structured
- Slug generation: The directory name is lowercased, spaces become
-, and non-alphanumeric characters are stripped (e.g.,/Users/Alex/My App→my-app). - File naming:
- macOS:
~/Library/Application Support/iTerm2/DynamicProfiles/dp-<slug>.json - Windows:
%LOCALAPPDATA%\Microsoft\Windows Terminal\Fragments\TermProfiles\proj-<slug>.json
- macOS:
- Idempotent: If a JSON file already exists, the command prints
Skip (exists)and leaves your configuration untouched.
macOS Details
- Each project gets
~/.zsh-profiles/<slug>/containing.zshrcand.zsh_history. - A slug maps 1:1 to a session scope:
ZDOTDIR=~/.zsh-profiles/<slug>is forced so every terminal using the same slug shares history and config, while other slugs stay fully isolated. .zshrcsources~/.zshrc.commonif present, so you can share aliases across projects.- History is unlimited up to 50k entries (
HISTSIZE+SAVEHIST). By defaultsetopt NO_SHARE_HISTORYkeeps per-window commands from syncing in real time, preventing cross-project bleed. If you prefer live history sync, edit the generated.zshrcand switch tosetopt SHARE_HISTORY. - Launch command:
/usr/bin/env ZDOTDIR="<project_zdotdir>" /bin/zsh -l. --isolate-cli codex,my-clidrops wrappers in~/.zsh-profiles/<slug>/bin/so those CLIs run with project-scoped HOME/XDG directories.- If you set a parent profile, the generated dynamic profile inherits colors, fonts, and other UI settings from it.
- Use
termprofiles setopt(ortermprofiles setopt --enable SHARE_HISTORY --disable NO_SHARE_HISTORY) to switch between history behaviors and toggle helpers likeHIST_IGNORE_SPACE; results propagate to every open tab instantly. termprofiles prompt on|off|toggleflips the prebuilt prompt snippet on demand; enabling it gives each profile a cyan[<slug>]prefix, while disabling it defers to the parent profile's prompt.
codex session sharing
- Running
termprofiles add <dir> --isolate-cli codexcreates wrappers so that every terminal on the same slug uses~/.zsh-profiles/<slug>/cli-homes/codexfor Codex CLI data. - Codex writes history when the process exits (or an explicit save happens), so simultaneous Codex sessions do not see each other's commands instantly. Exit one instance or trigger
codex historyto refresh the shared file. - Updating Codex simply replaces the binary on
PATH; because the wrapper calls the real executable (shutil.which("codex")), all profiles pick up the new version automatically. Re-runtermprofiles add <dir> --isolate-cli codexonly if the executable lives at a new path.
Windows Details
- Fragment JSON conforms to the Windows Terminal fragment spec and is auto-discovered on launch.
--shell wslrunswsl.exe -d <distro>; combine with--wsl-zdotdirto exportZDOTDIRand spawnzshviabash -lc.--shell git-bashpoints to the default Git for Windows install path ("C:\\Program Files\\Git\\bin\\bash.exe" -li). Adjust manually if you installed Git elsewhere.startingDirectoryis set to the project path; Windows Terminal respects it for local shells and translates for WSL.
Configuration & Environment Variables
Every CLI flag has an environment variable equivalent (useful for shell rc files or CI scripts):
| Purpose | Flag | Environment Variable | Default |
|---|---|---|---|
| iTerm2 parent GUID | --parent-guid |
TP_PARENT_GUID |
None |
| iTerm2 parent name | --parent-name |
TP_PARENT_NAME |
None |
| Windows color scheme | --color-scheme |
TP_COLOR_SCHEME |
None |
| Windows shell | --shell |
TP_SHELL |
powershell |
| WSL distro | --wsl-distro |
TP_WSL_DISTRO |
Ubuntu |
| WSL ZDOTDIR export | --wsl-zdotdir |
TP_WSL_ZDOTDIR |
None |
| CLI session isolation | --isolate-cli |
TP_ISOLATE_CLI |
None |
Command-line arguments take precedence over environment variables. Set them in your shell profile to create customized defaults; always pick names that exist in your setup:
# macOS example — choose from `termprofiles parents`
export TP_PARENT_NAME="DEFAULT"
# Windows example — choose from Windows Terminal `schemes`
export TP_COLOR_SCHEME="One Half Dark"
- Discover parent profile names on macOS with
termprofiles parents; it prints the names and GUIDs detected in iTerm2's preferences. - On Windows, open Windows Terminal settings (
wt settings) or inspectsettings.jsonto view theschemesarray and copy the color scheme name you want to export viaTP_COLOR_SCHEME.
Example Workflows
- Automate profile creation:
find ~/Code -maxdepth 1 -type d -not -path '*/.*' -print0 | xargs -0 termprofiles add. - Shared look & feel: on macOS set
TP_PARENT_NAMEto your favorite theme; on Windows setTP_COLOR_SCHEMEto keep colors consistent. - Isolate CLI state:
termprofiles add ~/dev/sample-app --isolate-cli codexkeeps Codex CLI data under~/.zsh-profiles/sample-app/cli-homes/codexinstead of the global~/.codex. - Verify Codex sharing:
termprofiles add . --isolate-cli codex→ open two iTerm2 windows using the sameproj-<slug>profile → run a Codex command in one → confirm it appears viacodex history --latestin the other after the first session exits or saves. - Tune zsh quickly:
termprofiles setoptto toggle history options, thentermprofiles prompt on(oroff) to adjust the shared prompt; the tool re-sources every open session automatically. - Spin up new shells:
termprofiles new --tabopens another tab with the same profile right away, ideal after changing configuration. - WSL development:
termprofiles add "/mnt/c/dev/app" --shell wsl --wsl-distro Ubuntu-22.04 --wsl-zdotdir "/home/user/.config/zsh/app"launches straight into WSL zsh with project-specific config. - Clean removal:
termprofiles remove ~/dev/sample-app --keep-zdotdirkeeps historical context while removing the dynamic profile.
Troubleshooting & FAQ
- Profiles are missing. Restart iTerm2/Windows Terminal so it reloads dynamic profiles/fragments.
- iTerm2 cannot read the JSON. Ensure Dynamic Profiles are enabled (
Preferences → Profiles → Other Actions → Import JSON Profiles). - Windows Terminal ignores the profile. Confirm fragments are enabled (
Settings → Open JSON fileshould listTermProfiles). Check%LOCALAPPDATA%\Microsoft\Windows Terminal\Fragments\TermProfilesfor the created JSON. - Parent profile not found (macOS). Use
termprofiles parentsto list available names and GUIDs. Remember that matching is case-insensitive and trims whitespace. - Custom shells. For Windows Git Bash installs in a different location, copy the generated fragment, edit
commandline, or pass a custom path by editing the JSON after creation. - Unrecognized directory.
termprofiles addskips paths that are not directories and printsSkip (not a dir).
Uninstalling
- Remove generated JSON: run
termprofiles remove <targets>(and optionally delete~/.zsh-profiles/<slug>). - Delete the package:
- pipx:
pipx uninstall termprofiles - pip/virtualenv:
python -m pip uninstall termprofiles
- pipx:
- Clean up leftover directories if desired:
rm -rf ~/Library/Application Support/iTerm2/DynamicProfiles/dp-*.json(macOS) or delete the fragments folder on Windows.
Contributing
- Issues and pull requests welcome at GitHub.
- Local setup:
git clone https://github.com/yaioyaio/termprofiles.git cd termprofiles python -m venv .venv source .venv/bin/activate python -m pip install --upgrade pip python -m pip install -e . termprofiles --help
- Run formatting and packaging checks as needed (
python -m build). - Follow conventional Python best practices and keep documentation updated.
License
MIT © yaioyaio
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file termprofiles-0.1.2.tar.gz.
File metadata
- Download URL: termprofiles-0.1.2.tar.gz
- Upload date:
- Size: 22.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9e50381509a0d309b4b86c6712e595ff7a4e594aea6324ab4af42c63ce257b38
|
|
| MD5 |
21eccc09ef250d1f120bf9a99be9d7ed
|
|
| BLAKE2b-256 |
f7cfd1fce548137c678e6f491d7fc02324e8d378850f3b75b9073e028ce3ad2d
|
File details
Details for the file termprofiles-0.1.2-py3-none-any.whl.
File metadata
- Download URL: termprofiles-0.1.2-py3-none-any.whl
- Upload date:
- Size: 17.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
09f158c9e6adb1e6c2588265a23dea3f0cc6674e18a382b39044b9604dcb1e37
|
|
| MD5 |
4a1e04edff45c53f7b24984a1e18d96d
|
|
| BLAKE2b-256 |
4b72c082ad4a1ff27389f1bcc03a661a0291f33a6cbab0893753f79907a9cbec
|