Cross-platform development environment configuration for Windows 11 Pro and MacOS.
This repository uses symlinks to keep configuration files in version control while maintaining their expected locations in your system. Changes made to configs in this repo automatically reflect in your system, and vice versa.
Ensure your PowerShell execution policy allows scripts:
# Check current policy
Get-ExecutionPolicy
# If needed, allow local scripts to run (requires Administrator)
Set-ExecutionPolicy RemoteSigned -Scope CurrentUserNote: The installer may require Administrator privileges for certain paths (like Windows Terminal settings). You'll be prompted if elevation is needed.
Install Homebrew if not already present:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"dotfiles/
├── cursor/ # Cursor IDE configuration (shared)
│ ├── mcp.json # MCP server definitions
│ ├── settings.json # Cursor settings
│ ├── keybindings.json # Custom keyboard shortcuts
│ ├── cli-config.json # Cursor CLI configuration (agent modes, permissions)
│ ├── snippets/ # Custom code snippets (if used)
│ └── rules/ # Global cursor rules
├── claude/ # Claude Code global settings (shared)
│ └── settings.json # Model, plugins, and permission rules
├── vscode/ # VS Code configuration (shared)
│ ├── settings.json # VS Code settings
│ ├── keybindings.json # Custom keyboard shortcuts
│ └── snippets/ # Custom code snippets (if used)
├── shell/ # Shared shell config (sourced by bash/zsh)
│ └── common.sh # Aliases, functions, secrets loading
├── git/ # Git configuration (shared)
│ ├── .gitconfig
│ ├── .gitignore_global
│ └── hooks/ # Global git hooks
├── npm/ # npm configuration (shared)
│ └── .npmrc
├── starship/ # Starship cross-shell prompt (shared)
│ └── starship.toml # Catppuccin Mocha powerline preset
├── zsh/ # Zsh profile (macOS)
│ └── .zshrc # Sources shell/common.sh, adds zsh config
├── macos/ # macOS-specific
│ └── Brewfile # Homebrew packages
├── powershell/ # PowerShell profile (Windows)
│ └── profile.ps1
├── git-bash/ # Git Bash profile (Windows, Cursor terminal)
│ ├── .bashrc # Sources shell/common.sh, adds bash config
│ ├── .bash_profile # Login shell: sources .bashrc
│ └── .inputrc # Readline settings
├── windows-terminal/ # Windows Terminal settings (Windows)
│ └── settings.json
├── winget/ # WinGet package manager (Windows)
│ ├── settings.json # WinGet behavior settings
│ └── packages.json # Curated list of dev tools & apps
├── wsl/ # WSL-specific configs (if used)
│ └── .bashrc
├── scripts/ # Installation and utility scripts
│ ├── install.ps1 # Windows symlink installer
│ ├── install.sh # macOS/Linux symlink installer
│ ├── sync-secrets.ps1 # Sync secrets to Windows user environment
│ └── winget-packages.ps1 # Import/export WinGet packages
├── secrets/ # Local secrets (git-ignored)
│ ├── .env.cloudflare.example # Cloudflare API template
│ ├── .env.github.example # GitHub token template
│ └── .env.* # Your actual secrets (not in git)
└── .cursorrules # Rules for editing THIS repo
# Clone the repo
git clone https://github.com/vocino/dotfiles.git ~/dotfiles
# Run the installer
cd ~/dotfiles
.\scripts\install.ps1From Git Bash you can run the installer with:
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ~/dotfiles/scripts/install.ps1# Clone the repo
git clone https://github.com/vocino/dotfiles.git ~/dotfiles
# Run the installer
cd ~/dotfiles
./scripts/install.sh
# Install Homebrew packages
brew bundle --file=~/dotfiles/macos/BrewfileThe installer will:
- Create symbolic links from system paths to files in this repo
- Ask for confirmation before overwriting existing files (unless using
-Force)
- Cursor IDE: Settings, MCP servers, keybindings, CLI config, snippets, global rules
- VS Code: Settings, keybindings, snippets
- Claude Code: Global settings with generous permissions for autonomous hobby development
- Starship: Cross-shell prompt with Catppuccin Mocha powerline preset
- Git: Global config, aliases, ignore patterns, hooks
- npm: Global npm configuration
- Secrets Management: Service-organized dotenv files with automatic shell loading
- Shell aliases: Shared git/npm shortcuts via
shell/common.sh(gst, gco, gaa, gcm, gp, gl, nr, ni, etc.)
- Git Bash: Shell profile sourcing shared config + Starship. Used by Cursor's integrated terminal.
- PowerShell: Custom profile with aliases, functions, secrets loading, Starship prompt
- Windows Terminal: Settings with Catppuccin Mocha theme
- WinGet: Package manager settings and curated package list
- Zsh: Shell profile sourcing shared config + Starship + zsh-specific settings
- Homebrew:
Brewfilewith curated package list
Cursor reads MCP config from cursor/mcp.json (symlinked to %USERPROFILE%\.cursor\mcp.json). This repo configures:
| Server | Type | Purpose |
|---|---|---|
| openai-docs | HTTP | Read-only OpenAI developer docs (API, SDK, etc.) — docs |
| fetch | stdio (npx) | Fetch URLs and extract content as markdown for LLM context |
| filesystem | stdio (npx) | Read/write files under a configurable directory |
| Cloudflare | HTTP | Access Cloudflare APIs and services |
| github | HTTP | Access GitHub APIs (requires GITHUB_MCP_TOKEN) |
Customize: Edit cursor/mcp.json. For filesystem, set the args path to your allowed directory (e.g. C:\Users\YourName or a project root). Use double backslashes in JSON.
Tokens: MCP servers that require authentication use environment variables (e.g., ${GITHUB_MCP_TOKEN}). Add tokens to secrets/.env.github or other service files, run .\scripts\sync-secrets.ps1, then restart Cursor.
More servers: MCP Registry, modelcontextprotocol/servers (Git, Brave Search, etc.). Use url for HTTP servers, command/args for stdio. Restart Cursor after changes.
All applications are configured to use Catppuccin Mocha where available. Catppuccin is a community-driven pastel theme available for 400+ applications, providing a consistent, warm color scheme across the entire development environment.
Shell prompts use Starship with the Catppuccin powerline preset for a unified cross-shell experience (Git Bash, PowerShell, and Zsh).
Prerequisites: Install the Catppuccin theme extension (Catppuccin.catppuccin-vsc) in Cursor and VS Code. Install Starship via winget install --id Starship.Starship (Windows) or brew install starship (macOS).
# Full install (all configs)
.\scripts\install.ps1
# Selective install (only specific configs)
.\scripts\install.ps1 -Only cursor,git
# Force mode (overwrites existing files without prompting)
.\scripts\install.ps1 -ForceSelective Install: Use -Only to install specific configs. Available options: vscode, cursor, claude, powershell, git-bash, git, npm, windows-terminal, winget, starship, wsl.
# Full install (all configs)
./scripts/install.sh
# Selective install (only specific configs)
./scripts/install.sh --only cursor,git
# Force mode (overwrites existing files without prompting)
./scripts/install.sh --forceSelective Install: Use --only to install specific configs. Available options: git, npm, starship, claude, shell, cursor, vscode, zsh.
The winget/packages.json file contains a curated list of dev tools and apps. Use the helper script to manage packages:
# Install all packages from the curated list (skips already installed)
.\scripts\winget-packages.ps1 import
# Re-export current packages (overwrites packages.json - review afterward)
.\scripts\winget-packages.ps1 exportAfter making changes to config files in this repo:
# Symlinks automatically reflect changes - no reinstall needed!
# The repo files are already linked, so edits appear immediately
# However, if you need to re-link (e.g., after structure changes):
.\scripts\install.ps1 -ForceSince configs are symlinked, edits in either location (repo or system) are immediately reflected in both. No reinstall needed for content changes.
This repository includes a secure secrets management system that keeps tokens and API keys out of version control while making them available to your development tools and applications.
Secrets are organized by service using separate .env.* files in the secrets/ directory:
- Service-based organization: Each service gets its own file (e.g.,
.env.cloudflare,.env.github,.env.aws) - Related credentials together: All credentials for a service are kept in one place
- Easy to manage: Add or remove services without affecting others
- Git-ignored: All
.env.*files (except.exampletemplates) are ignored by git
-
Copy example files to create your local secret files:
Copy-Item secrets\.env.cloudflare.example secrets\.env.cloudflare Copy-Item secrets\.env.github.example secrets\.env.github
-
Add your actual values to the
.env.*files:# Edit with your preferred editor code secrets\.env.cloudflare code secrets\.env.github # or notepad secrets\.env.cloudflare notepad secrets\.env.github
-
Format: Each file uses standard dotenv format:
# Example: secrets/.env.cloudflare CLOUDFLARE_ACCOUNT_ID=your_actual_account_id CLOUDFLARE_API_TOKEN=your_actual_token # Example: secrets/.env.github GITHUB_TOKEN=your_github_token_here GITHUB_MCP_TOKEN=your_github_mcp_token_here
The PowerShell profile automatically loads all .env.* files from secrets/ on every shell startup. This means:
- CLI tools (git, npm, wrangler, etc.) launched from PowerShell have access
- Terminal-based workflows automatically get the environment variables
- No manual loading required - it happens automatically
The shared shell config (shell/common.sh) sources and exports all secrets/.env.* files (excluding .example) on every shell startup. Both Git Bash (Windows) and Zsh (macOS) source this file, so:
- CLI tools and terminal sessions automatically get environment variables
- No manual loading required - it happens when you open a new terminal
- GUI applications on Windows still need secrets in the Windows user environment; use
sync-secrets.ps1and restart the app
GUI applications need secrets in the Windows user environment variables. Use the sync script:
# Preview what will be synced (dry run)
.\scripts\sync-secrets.ps1 -WhatIf
# Actually sync secrets to Windows user environment
.\scripts\sync-secrets.ps1Important: After syncing, restart the application (e.g., Cursor) to pick up the new environment variables.
Cursor can access secrets in several ways:
-
Environment Variables (recommended for GUI):
- Run
.\scripts\sync-secrets.ps1to sync secrets to Windows user env - Restart Cursor
- Cursor's terminal, agents, and code can now access
$env:CLOUDFLARE_API_TOKEN, etc.
- Run
-
Terminal Commands in Cursor:
- Cursor's default terminal is Git Bash. The Git Bash profile loads secrets automatically on each new terminal.
- If you launch Cursor from PowerShell (e.g.,
cursor .), it inherits the shell's environment; the PowerShell profile loads secrets there too.
-
Agent Operations:
- When Cursor agents run terminal commands, they use the environment variables
- Commands like
curlwith API tokens work seamlessly
Example: Using Cloudflare API token in Cursor:
# In Cursor's terminal or agent commands:
curl "https://api.cloudflare.com/client/v4/accounts/$env:CLOUDFLARE_ACCOUNT_ID/tokens/verify" `
-H "Authorization: Bearer $env:CLOUDFLARE_API_TOKEN"To add secrets for a new service:
-
Create an example file:
# Create secrets\.env.newservice.example @" # NewService API Configuration NEWSERVICE_API_KEY=your_api_key_here NEWSERVICE_SECRET=your_secret_here "@ | Out-File -FilePath secrets\.env.newservice.example -Encoding utf8
-
Copy and fill in values:
Copy-Item secrets\.env.newservice.example secrets\.env.newservice # Edit secrets\.env.newservice with your actual values
-
Add to sync allowlist (if you want it synced to Windows user env):
# Edit scripts\sync-secrets.ps1 # Add "NEWSERVICE_API_KEY", "NEWSERVICE_SECRET" to the $AllowList array
-
The PowerShell and Git Bash profiles automatically load it - no changes needed!
- Update a secret: Edit the appropriate
.env.*file, then run.\scripts\sync-secrets.ps1if it's synced to user env - Add a new service: Create
.env.servicenamefile - it's automatically loaded - Remove a service: Delete the
.env.*file and remove from sync allowlist if needed - View loaded secrets: In PowerShell, run
Get-ChildItem Env: | Where-Object { $_.Name -like "*CLOUDFLARE*" -or $_.Name -like "*GITHUB*" }
- ✅ All
.env.*files are git-ignored (never committed) - ✅ Only
.exampletemplate files are tracked in git - ✅ Secrets are stored locally on your machine
- ✅ Sync script only writes to Windows user environment (not system-wide)
⚠️ Keep yoursecrets/directory secure and don't share it⚠️ Rotate tokens if they're ever exposed or shared
- Add the config file to the appropriate directory
- Update
scripts/install.ps1(Windows) and/orscripts/install.sh(macOS) with the symlink mapping - For new shell aliases/functions, add to
shell/common.sh(shared) rather than individual profiles - Document in this README (structure, What Gets Configured, Key Paths Reference, and any secrets/verification steps)
After installation, verify symlinks were created correctly:
# Check if files are symlinks (returns True if symlink, False if regular file)
(Get-Item $env:USERPROFILE\.gitconfig).LinkType -eq 'SymbolicLink'
(Get-Item $env:APPDATA\Cursor\User\settings.json).LinkType -eq 'SymbolicLink'
# View symlink targets
Get-Item $env:USERPROFILE\.gitconfig | Select-Object LinkType, TargetQuick Checklist:
- Symlinks created (check with commands above)
- Cursor IDE settings load correctly
- PowerShell profile loads on new session (
pwsh) - Git config is active (
git config --list --show-origin) - Windows Terminal uses new settings (if installed)
Cross-platform shells: Shared aliases, functions, and secrets loading live in shell/common.sh, sourced by both git-bash/.bashrc (Windows) and zsh/.zshrc (macOS). PowerShell has its own implementation. On Windows, Cursor's default terminal is Git Bash.
Dual installers: scripts/install.ps1 (Windows) and scripts/install.sh (macOS) are separate scripts with platform-idiomatic implementations. Both follow the same pattern: define symlink mappings, create links, handle conflicts.
Why Symlinks?
- Single source of truth: configs live in this repo
- Automatic sync: changes in repo or system reflect immediately
- Easy updates: edit once, works everywhere
- Version controlled: all config changes are tracked in git
What Happens to Existing Files?
- If a file already exists and isn't a symlink, you'll be prompted (unless using
-Force) - You can always restore previous versions from git history if needed
Administrator Requirements
- Some paths (like Windows Terminal) require admin privileges to create symlinks
- The installer will request elevation only when needed
- Most user profile paths don't require admin
- Some system paths require Administrator privileges (installer handles this)
- Paths use PowerShell environment variables:
$env:APPDATA,$env:USERPROFILE,$env:LOCALAPPDATA - GUI apps need secrets synced via
sync-secrets.ps1
- All symlinks are created in user space (no sudo required)
- Paths use
$HOMEand~/Library/Application Support/ - GUI apps pick up environment from shell profile (launchctl may be needed for some cases)
| Config | Path |
|---|---|
| Cursor Settings | %APPDATA%\Cursor\User\settings.json |
| Cursor Keybindings | %APPDATA%\Cursor\User\keybindings.json |
| Cursor MCP | %USERPROFILE%\.cursor\mcp.json |
| Cursor CLI Config | %USERPROFILE%\.cursor\cli-config.json |
| Cursor Snippets | %APPDATA%\Cursor\User\snippets\ |
| Claude Code Settings | %USERPROFILE%\.claude\settings.json |
| VS Code Settings | %APPDATA%\Code\User\settings.json |
| VS Code Keybindings | %APPDATA%\Code\User\keybindings.json |
| VS Code Snippets | %APPDATA%\Code\User\snippets\ |
| PowerShell Profile | %USERPROFILE%\Documents\PowerShell\Microsoft.PowerShell_profile.ps1 |
| Git Bash rc | %USERPROFILE%\.bashrc |
| Git Config | %USERPROFILE%\.gitconfig |
| npm Config | %USERPROFILE%\.npmrc |
| Starship Config | %USERPROFILE%\.config\starship.toml |
| Windows Terminal | %LOCALAPPDATA%\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json |
| WinGet Settings | %LOCALAPPDATA%\Packages\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe\LocalState\settings.json |
| Config | Path |
|---|---|
| Cursor Settings | ~/Library/Application Support/Cursor/User/settings.json |
| Cursor Keybindings | ~/Library/Application Support/Cursor/User/keybindings.json |
| Cursor MCP | ~/.cursor/mcp.json |
| Cursor CLI Config | ~/.cursor/cli-config.json |
| Claude Code Settings | ~/.claude/settings.json |
| VS Code Settings | ~/Library/Application Support/Code/User/settings.json |
| VS Code Keybindings | ~/Library/Application Support/Code/User/keybindings.json |
| Zsh Profile | ~/.zshrc |
| Git Config | ~/.gitconfig |
| npm Config | ~/.npmrc |
| Starship Config | ~/.config/starship.toml |
Note: These paths are where symlinks are created. The actual config files remain in this repository.