Personal dotfiles with a minimal macOS profile for occasional, container-based development. The default installer previews changes and installs no packages.
The profile keeps Oh My Zsh's git and macos plugins and robbyrussell theme when Oh My Zsh is installed. Until then, it works with plain zsh.
It adds useful navigation aliases, k for kubectl, and familiar Kubernetes
shortcuts (kgp, kdp, klo, klof, kex, kaf), plus Homebrew completion
paths and shared Git aliases. It has no native Go, Ruby, NVM, Python environment,
minikube, Vim-plugin, or tmux dependency. It does not start containers or clusters.
The original shell and Git files remain ordinary local files:
- A marked source block is appended to
~/.zshrc. Existing corporate hooks stay. - A marked Git include is prepended to
~/.gitconfig. Existing local settings take precedence, including 1Password signing, identities, credentials, aliases, and account-routing rules. ~/.zprofile, SSH, cloud credentials, Docker configuration and kubeconfig are untouched. The existing Dogbrew initialization is reapplied after PATH setup to preserve shim precedence.- A small global ignore file is selected unless the implicit XDG ignore file
already exists. An explicit local
core.excludesFilestill takes precedence.
The profile supplies no author name or email. user.useConfigOnly requires an
explicit Git identity instead of letting Git guess one from the machine.
Clone without recursive submodules and keep the repository at a stable location:
git clone https://github.com/wdhif/dotfiles.git
cd dotfiles
./installReview the preview before applying:
./install --applyOpen a new terminal afterward. Do not source the legacy zsh/zshrc or link it
over your live shell file.
The migration uses Python 3's standard library only; Python is not used at shell startup. The current Mac's Command Line Tools already provide Python 3. There are no Python packages to install. The minimal path does not initialize Dotbot or editor submodules: two additive includes need no plugin manager.
Applying saves original bytes and permissions in a private backup under
~/.local/state/dotfiles/backups/ and prints its exact path. Preview rollback
with that path, then add --apply to restore:
./install --rollback /path/printed/by/the/installer/backup.json
./install --rollback /path/printed/by/the/installer/backup.json --applyRollback refuses to overwrite a file changed since installation. Backups may contain private settings; keep them outside the repository. Rollback restores the two configuration files, not shell caches created later by zsh or Oh My Zsh.
Repeated installation makes no further changes or backups. Moving the repository requires another preview/apply to update its absolute include paths. Future edits to the included files take effect without rerunning the installer.
The migration refuses symlinked/hard-linked destinations, malformed markers,
custom ZDOTDIR/GIT_CONFIG_GLOBAL, and existing XDG Git configuration. Those
layouts need a manual review of source/include order rather than a forced link.
It preserves existing shell code; it does not remove old customizations already
present in a different machine's .zshrc.
Install Oh My Zsh using its official installer.
For a fresh machine, install it before applying this profile. Its installer
normally replaces .zshrc and preserves the previous file as
.zshrc.pre-oh-my-zsh. Review that backup when restoring an existing minimal
profile; retain corporate initialization and avoid loading Oh My Zsh twice.
The minimal profile selects the git and macos plugins when it loads Oh My
Zsh. If the official template already loaded it, that template controls the
plugin list instead. The profile disables automatic update checks; update
intentionally with omz update.
The profile uses macos/omz-custom/, so the legacy zsh/custom/ scripts are not
loaded. Completion comes from installed Homebrew packages and OMZ; no Docker,
Helm, Kubernetes, or Colima process is launched to generate completions when a
terminal opens. A package installed by another method may need its completion
file installed separately. Restart the shell after installing new completions.
Terminal choice is independent: Terminal.app, iTerm2, and Ghostty can all use this shell configuration. There is no terminal-app installation in this repo.
Keep host tools for authentication and controlling Linux development environments. Build and test inside Colima, devcontainers, Kubernetes, or cloud environments.
| Tool | Reason / scope |
|---|---|
| Existing Homebrew and corporate Dogbrew/Privileges | Preserve provisioning and authentication hooks; do not rerun the full laptop bootstrap. |
| Git and 1Password SSH agent/signing | Source control; retain local account selection and signing configuration. |
| Colima and Docker CLI | Linux container runtime. Lima is a Colima dependency, not an extra runtime to manage separately. |
| kubectl and Helm | Access Kubernetes and install charts. |
dda |
Agent development through its standard container environment. |
ddtool |
Add only for Datadog-specific access that requires it; prefer native login/SSO elsewhere. |
| AWS CLI and Google Cloud CLI | Standard cloud clients; configure accounts/projects when needed. Prefer native SSO. Add AWS Vault only for a workflow that requires it. |
| Oh My Zsh | Selected shell experience: two stock plugins and one theme. |
| Docker Buildx | Standard Docker build plugin used by the Dev Containers CLI. Follow Homebrew's cliPluginsExtraDirs configuration instructions. |
| Docker Compose | Add when a repository uses Compose; not required for an image-based devcontainer. |
| Dev Containers CLI | Official @devcontainers/cli npm package, installed with npm install --global @devcontainers/cli; requires Node.js. No editor is required. |
| 1Password CLI | Official Homebrew cask, connected through the desktop app's Developer settings. |
| minikube / kind | Deferred on the host unless a concrete test requires them. A devcontainer may already provide them. |
| Native build toolchains, extra editors/plugins, Terraform/Pulumi | Defer; use repository containers. Node.js for the Dev Containers CLI and Python dependencies of cloud clients are runtime requirements, not host build environments. |
There is deliberately no bulk Brewfile or automatic login command. The Agent's
required setup documents
brew install --cask dda; its development environment guide
describes the container workflow. The official macOS setup describes Docker
Desktop; validate Docker socket and SSH-agent access when using Colima instead.
Colima's Kubernetes documentation supports enabling k3s alongside Docker. When ready to start the VM deliberately:
colima start --runtime docker --kubernetes
docker context show
docker info
kubectl config get-contexts
kubectl --context colima get nodesThe context example assumes the default Colima profile; inspect the listed
contexts first if using a named profile. Avoid overriding DOCKER_HOST globally
or changing Kubernetes context at every shell startup. Container image access,
repository socket mounts, resources, and architecture still need validation for
the actual workload. Colima k3s is not a blanket substitute for kind/minikube
assumptions in test scripts.
The minimal profile loads macos/work.zsh. It provides deva for native dda,
plus ddap and ddo for the flat Agent and Operator checkouts under
~/Projects/work. Override DOTFILES_WORK_ROOT if that root differs.
Credentials are loaded only for an explicit command, using the official
1Password op run:
with-dd dev python3 my-script.py
with-dd prod python3 my-script.py
with-api github gh api user
with-api pulumi pulumi previewThese examples execute the supplied command; select its environment and effects
deliberately. with-dd requires dev, prod, staging, or ddstaging, exposing
that pair as DD_API_KEY / DD_APP_KEY plus its original named variables.
This selects credentials only; configure the matching API endpoint in your tool.
with-api supports github, context7, docker, gitlab, atlassian,
claude-api, claude-oauth, pulumi, and the four dd-ENV profiles.
The Claude modes are separate: claude-api retains the legacy CLAUDE_API_KEY
name for consumers expecting it; it does not reconfigure Claude's login/helper.
Pulumi uses its independently preserved passphrase reference, not a dynamic
alias to a Datadog key. Prefer existing native login/SSO when no token is needed.
Machine-specific files live outside Git, under
${XDG_CONFIG_HOME:-~/.config}/api-credentials/:
personal.accountandemployee.account: the relevant 1Password account URL, one plain line each; neither contains an authentication secret.profiles/PROFILE.env: only the selected tool'sop://references and non-secret settings, interpreted byop run, never sourced as shell code.
Keep those local files owner-readable/writable only. They are configured separately from the dotfiles installer. Missing configuration, an unknown profile, or a 1Password failure prevents the command from running. Each helper clears inherited migrated credential variables in its child environment; it leaves the calling shell unchanged. No secrets, account IDs, or vault/item references are stored in this repository, and shell startup does not invoke Keychain or 1Password. Use an executable command or an explicit shell/script after the helper; shell aliases and functions are not standalone executables. Do not print credentials.
The previous Minikube reset, image-push, fixed-container and deleted-checkout aliases are not restored. Use the standard CLI for the current environment.
Keep authentication separate from commit identity. An SSH host alias can select
the work account while includeIf selects the correct author identity.
For example, keep this in local Git configuration, using a work-identity file
that contains your verified name/email:
[includeIf "gitdir:~/Projects/work/"]
path = ~/.config/git/work.gitconfigDo not add the include before creating and reviewing the identity file: Git silently ignores a missing include. Check the effective identity inside both a personal repository and a work repository with:
git config --show-origin --get user.emailThe profile does not invent an email or copy credentials into Git. Keep only the repositories used for Agent/Kubernetes work. Shared devtools and cloud-test repositories can be obtained when needed; do not clone the bootstrap's entire repository list. Keep private corporate configuration and credentials outside this repository.
Use each tool's native login or SSO flow first. Keep manually managed work
secrets in the Datadog 1Password Employee vault or an appropriate shared vault.
Retrieve a secret only for the command that needs it, using op run or a
supported credential helper. Do not export API keys or tokens from shell startup
files. op run still exposes secrets to its subprocess environment; it limits
the scope and lifetime rather than eliminating exposure.
Connect the CLI in 1Password → Settings → Developer → Integrate with 1Password CLI. SSH authentication and Git signing use the separately configured 1Password SSH agent. Native CLI sessions do not need to be copied into 1Password or into shell variables.
For repositories with an existing devcontainer configuration, use the official CLI from the repository directory:
devcontainer up --workspace-folder .
devcontainer exec --workspace-folder . <command>These commands install and run the repository's development tools inside its
container. Follow the repository's own instructions for builds/tests. For the
Agent, prefer its documented dda env dev workflow. Avoid sharing host
credentials with a container unless its task requires them.
Cloud clients can be installed before selecting AWS accounts or Google Cloud projects. Recreate SSO sessions on demand; preserve any unique keys needed for existing resources separately before retiring an old laptop.
PYTHONDONTWRITEBYTECODE=1 python3 -m unittest discover -s tests -vThe tests use temporary homes and cover preview, repeated application, rollback, conflicts, Git identity/signing precedence, path quoting, and interactive/login shells with and without a simulated OMZ installation. They do not establish live GitHub authentication, cloud access, or working containers.
For a manual isolated migration, create an empty temporary directory and run
./install --home /path/to/temporary/home, adding --apply when ready. Never
point a test at the real home directory. GitHub Actions runs the isolated tests
on macOS; it does not apply the legacy setup to the runner.
./install --legacy explicitly runs the original Dotbot configuration. It
downloads submodules and force-replaces several shell, Git, Vim, and tmux
files. It is retained for older environments and is unsuitable for the minimal
Mac migration. Do not use it as an alternative way to apply this profile.
Legacy Vim plugins remain Pathogen submodules in vim/bundle/. Add a plugin
with git submodule add REPOSITORY_URL vim/bundle/NAME, or remove one with
git rm vim/bundle/NAME. Updating those submodules is separate from the minimal
profile.