feat: major dotfiles refactor with documentation and multi-platform improvements

- Add comprehensive CLAUDE.md with chezmoi best practices and AI assistant guidelines
- Restructure TODO.md with prioritized tasks and detailed organization
- Add PowerShell profile template for Windows platform support
- Split git configs into identity-specific templates (ryan/xevion)
- Convert nushell env.nu and gitconfig to templates for cross-platform rendering
- Refactor chezmoi hooks to TypeScript (.init_pre.ts, .update_pre.ts)
- Update .chezmoiignore with better platform-specific file handling
- Remove deprecated shellchecker.sh and tasks.json from VS Code config
- Add mise integration to shell configs (bash, zsh, nushell, PowerShell)
- Clean up commonrc.sh.tmpl WSL-specific code
- Disable Deno in VS Code settings, enable simple dialog mode
- Add nushell extension recommendation to VS Code

This commit establishes better cross-platform support (Windows/WSL/Linux),
improves documentation for future maintenance, and standardizes configuration
management patterns across the repository.
This commit is contained in:
Ryan Walters
2025-10-26 17:01:45 -05:00
parent 8b718db155
commit 02b9236ecf
21 changed files with 951 additions and 361 deletions

5
.vscode/extensions.json vendored Normal file
View File

@@ -0,0 +1,5 @@
{
"recommendations": [
"thenuprojectcontributors.vscode-nushell-lang"
]
}

View File

@@ -19,5 +19,6 @@
"editor.formatOnPaste": false,
"editor.formatOnType": false,
"notebook.formatOnSave.enabled": false,
"deno.enable": true
"deno.enable": false,
"files.simpleDialog.enable": true
}

View File

@@ -1,51 +0,0 @@
#!/bin/bash
# set -u
ROOT="$1"
SHELLCHECK_OPTIONS="--color=never --format=gcc"
# Function to invoke shellcheck or chezmoi execute-template based on file type
invoke_checker() {
filepath="$1"
# If the file is a .tmpl file, use chezmoi execute-template
if [[ $filepath == *.tmpl ]]; then
# TODO: This still doesn't work, for some reason 'sed' just refuses to replace the 'stdin' placeholder with execute-template
if ! RENDERED_TEMPLATE=$(cat $filepath | chezmoi execute-template | sed -E "s|stdin|$filepath|"); then
# since stdin is used for this, the filepath appears as '-', and thus must be replaced
echo "$RENDERED_TEMPLATE" | shellcheck - $SHELLCHECK_OPTIONS | sed "s|^-|$filepath|"
else
echo $filepath
fi
else
# Otherwise, use shellcheck directly
shellcheck "$filepath" $SHELLCHECK_OPTIONS
fi
}
# chek that 'shellcheck' is available
if ! command -v shellcheck &> /dev/null; then
echo "shellcheck could not be found"
exit 1
fi
echo "initial shellcheck started"
# Run an initial scan of all shell scripts
while IFS= read -rd $'\0' file; do
invoke_checker "$file"
done < <(find "$ROOT" \( -name "*.sh" -o -name "*.sh.tmpl" \) -type f -print0)
echo "inotifywait started"
inotifywait -mr --quiet --format ' %w %f' -e modify $1 |
while read -r dir file; do
absolute_path=${dir}${file}
# Check if the changed file ends with .sh or .sh.tmpl
if [[ $absolute_path == *.sh || $absolute_path == *.sh.tmpl ]]; then
invoke_checker $absolute_path
fi
done
echo "inotify watcher stopped"

58
.vscode/tasks.json vendored
View File

@@ -1,58 +0,0 @@
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "Shellcheck",
"type": "shell",
"isBackground": true,
"command": "${workspaceFolder}/.vscode/shellchecker.sh ${workspaceFolder}",
"problemMatcher": [
{
"source": "shellcheck",
"owner": "bash",
"fileLocation": ["autoDetect", "${workspaceFolder}"],
"pattern": {
// info/style joined into 'note'
"regexp": "^(.*):(\\d+):(\\d+):\\s*(error|warning|note):\\s*(.*)$",
"file": 1,
"line": 2,
"column": 3,
"severity": 4,
"message": 5
},
"background": {
"activeOnStart": true,
"beginsPattern": "^inotify watcher started$",
"endsPattern": "^inotify watcher stopped$"
}
},
{
"source": "chezmoi",
"owner": "chezmoi",
"fileLocation": ["autoDetect", "${workspaceFolder}"],
"pattern": {
"regexp": "^chezmoi: template: (.*):(\\d+):(\\d+): executing \".+\" (at .*)$",
"file": 1,
"line": 2,
"column": 3,
"message": 4
}
}
],
"runOptions": {
"runOn": "folderOpen"
},
"presentation": {
"echo": true,
"reveal": "always",
"revealProblems": "never",
"focus": false,
"panel": "dedicated",
"clear": false
},
}
]
}

123
CLAUDE.md Normal file
View File

@@ -0,0 +1,123 @@
# Chezmoi Dotfiles Repository - AI Assistant Guidelines
## Repository Context
This is a **chezmoi source directory** for managing dotfiles across multiple machines. Files here are SOURCE files that get templated and deployed to the home directory.
### Key Concepts
**Source vs Target Pattern:**
- **Source**: `~/.local/share/chezmoi/home/dot_bashrc.tmpl` (what you edit)
- **Target**: `~/.bashrc` (what gets deployed after `chezmoi apply`)
- Edit source files only. DO NOT modify target files directly.
**File Naming Conventions:**
- `dot_` `.` (e.g., `dot_bashrc` becomes `~/.bashrc`)
- `.tmpl` suffix Go template file (rendered with platform detection)
- `private_` prefix 600 permissions
- `encrypted_*.age` age-encrypted files (safe to commit)
- `run_onchange_*` executable scripts that run during apply
**Template System:**
- Uses Go templates with platform detection
- Variables: `.chezmoi.os`, `.chezmoi.homeDir`, `.data.*`
- Conditional rendering for Windows/Linux/macOS/WSL
**Secret Management:**
- Age encryption for sensitive files (recipient: `age1s3ctpj9lafl6qwyvd89sn448us7gdzd53d8yyhsc7zny78c0k4sqerrkze`)
- Doppler integration for API keys/tokens
- Encryption key bootstrapped via hooks from Doppler
**Hooks:**
- `.init_pre.ts` and `.update_pre.ts` (TypeScript via Bun)
- Bootstrap encryption key from Doppler before apply
- Handle `chezmoi init` and `chezmoi update --init`
## Critical Restrictions
### NEVER Do These Actions
1. **DO NOT apply changes to filesystem**
- NO `chezmoi apply`
- NO direct file writes to `~/.bashrc`, `~/.gitconfig`, etc.
- Changes stay in source directory only
2. **DO NOT commit or push automatically**
- NO `git commit` without explicit user request
- NO `git push` on your own
- Let user review changes first
3. **DO NOT embed secrets in plaintext**
- NO API keys, tokens, or passwords in plain text
- Use Doppler variables: `{{ dopplerProjectJson.KEY_NAME }}`
- Use age encryption for sensitive files
- Reference encryption: `encrypted_private_*.age`
4. **DO NOT verify changes yourself**
- NO running build/test commands unless requested
- Let user test changes with `chezmoi diff` or `chezmoi apply --dry-run`
- Ask user to verify after making changes
### Recommended Actions
1. **Edit source files** in `home/` directory
- Modify `.tmpl` files with proper template syntax
- Respect platform conditionals (`{{ if eq .chezmoi.os "windows" }}`)
- Maintain existing template structure
2. **Explain impact** of changes
- Which target files will be affected
- Platform-specific behavior
- What the user should test
3. **Suggest verification commands**
- `chezmoi diff` - preview changes
- `chezmoi apply --dry-run` - simulate apply
- `chezmoi status` - see what's changed
4. **Use templates correctly**
- Platform detection: `.chezmoi.os`, `.data.wsl`, `.data.chassis`
- Doppler secrets: `{{ dopplerProjectJson.SECRET_NAME }}`
- Conditional logic: `{{ if }}...{{ else }}...{{ end }}`
## Common Tasks
**Add new dotfile:**
```bash
# DO NOT run - explain this to user instead
chezmoi add ~/.newconfig
# Edit: home/dot_newconfig or home/dot_newconfig.tmpl
```
**Add sensitive config:**
```bash
# DO NOT run - explain this to user instead
chezmoi add --encrypt ~/.ssh/config
# Creates: home/private_dot_ssh/encrypted_config.age
```
**Edit existing file:**
- Locate source: `home/dot_config/nushell/config.nu.tmpl`
- Make changes to source file
- User runs: `chezmoi apply` or `chezmoi apply ~/.config/nushell/config.nu`
## Platform Coverage
- **OS**: Windows, Linux (WSL/native), macOS
- **Shells**: bash, zsh, nushell, PowerShell
- **Tools**: 30+ development tools configured (pyenv, bun, cargo, etc.)
- **Secrets**: Doppler + age encryption
## When Uncertain
1. **Ask before modifying** templates with complex platform logic
2. **Clarify secret handling** before adding sensitive data
3. **Let user verify** all changes before suggesting next steps
4. **Prefer explanations** over automated actions
# Extended Documentation
@README.md
@TODO.md
@FAQ.md
@ONBOARDING.md

308
TODO.md
View File

@@ -1,8 +1,300 @@
- age executable is not installed on init
- rbw executable needs better configuration
- rbw config not tracked
- hishtory executable not available on init
- add GPG key to bw
- dracula theme tracking, kitty/micro
- lazygit fix difftool
- testing in github codespaces
# Dotfiles Repository TODO
## Overview
## Critical
*Must be done first - establishes the groundwork for everything else*
### 1. Create Installation Workflow Documentation
- [ ] Document bootstrap process for fresh Linux installations
- [ ] Document bootstrap process for WSL installations
- [ ] Document bootstrap process for Windows (including Bun requirement)
- [ ] Create pre-flight checklist (required tools: Bun, age encryption, chezmoi, etc.)
- [ ] Document hook system (`.init_pre.ts`, `.update_pre.ts`) and when they execute
- [ ] Add troubleshooting guide for common installation issues
- [ ] Document the relationship between source directory and target directory
- [ ] Add step-by-step first-time setup guide
- [ ] Document Doppler setup requirements
- [ ] Create quick reference card for emergency recovery
### 2. Standardize Encryption & Authentication Workflow
- [ ] Document age encryption setup and key management
- [ ] Create guide for Doppler integration (project setup, config selection)
- [ ] Document secret rotation process and schedule
- [ ] Create checklist for adding new encrypted values
- [ ] Consolidate all authentication tokens/keys into Doppler or age-encrypted files
- [ ] Document age recipient key storage and backup strategy
- [ ] Add encryption troubleshooting guide
- [ ] Create template for encrypted file naming conventions
- [ ] Document `.private_*` file pattern usage
- [ ] Audit existing secrets and migrate to standard locations
### 3. Define Cross-Platform Strategy
- [ ] Create platform detection reference (`.data.wsl`, `.data.chassis`, OS checks)
- [ ] Document template conditionals strategy (when to use OS-specific blocks)
- [ ] Define Windows vs WSL separation of concerns
- [ ] Create decision matrix for which tools go where (Windows native vs WSL)
- [ ] Document how to handle tools that exist on both platforms
- [ ] Define file path conventions for cross-platform compatibility
- [ ] Create testing strategy for multi-platform templates
- [ ] Document Windows-specific quirks and workarounds
---
## Important
*Affects daily use and prevents frustration*
### 4. Refactor Shell Configuration Architecture
- [ ] Consolidate PATH modifications into single, organized section in `commonrc.sh.tmpl`
- [ ] Create modular PATH loading system (one block per tool with conditional checks)
- [ ] Separate PATH, environment variables, and shell completions into logical sections
- [ ] Document load order (`.bashrc``.zshrc``commonrc.sh``.bash_aliases`)
- [ ] Add comments explaining each tool's PATH modification
- [ ] Eliminate duplicate PATH additions
- [ ] Create standard pattern for conditional tool loading
- [ ] Add PATH deduplication function
- [ ] Move WSL-specific settings to dedicated section (currently at commonrc.sh.tmpl:109-114)
- [ ] Organize tool sections alphabetically or by category
### 5. Shell Completions Cleanup
- [ ] Audit all completion sources in `commonrc.sh.tmpl` (lines 17-22, 35-39, 71-76)
- [ ] Create consistent pattern for conditional completion loading
- [ ] Move completions to dedicated section (after PATH, before aliases)
- [ ] Add error handling for missing completion files
- [ ] Document which tools provide completions
- [ ] Test completions on bash and zsh
- [ ] Add completion loading performance optimization
- [ ] Document how to add new tool completions
### 6. Windows PATH Management
- [ ] Create PowerShell script for Windows-only PATH modifications
- [ ] Document registry-based PATH vs user PATH vs chezmoi-managed PATH
- [ ] Create chezmoi hook for Windows PATH synchronization
- [ ] Add validation script to check PATH consistency
- [ ] Document how to add new Windows PATH entries
- [ ] Create backup/restore mechanism for Windows PATH
- [ ] Add Windows environment variable management strategy
- [ ] Test PATH length limits on Windows
### 7. Core Tool Standardization
**mise (development environment manager):**
- [ ] Add mise configuration file (`.mise.toml` or per-project configs)
- [ ] Document mise setup and installation
- [ ] Integrate mise activation with shell configs
- [ ] Document tool version management strategy
- [ ] Add mise to installation checklist
**bun (JavaScript runtime):**
- [ ] Document global install location and version management
- [ ] Add shell completions configuration
- [ ] Document bun vs npm vs pnpm strategy
- [ ] Add bun to PATH in standard location
- [ ] Test bun hooks (`.init_pre.ts`, `.update_pre.ts`) on all platforms
**Windows Terminal:**
- [ ] Add `settings.json` template to dotfiles
- [ ] Document theme/color scheme customization
- [ ] Add font configuration (Cascadia Code, Nerd Fonts, etc.)
- [ ] Configure profiles for PowerShell, WSL, cmd
- [ ] Document Windows Terminal installation method
**Claude (AI assistant):**
- [ ] Document Claude configuration location
- [ ] Add API key management strategy (Doppler?)
- [ ] Add global CLAUDE.md to dotfiles
- [ ] Create project-specific CLAUDE.md templates
- [ ] Document sync strategy across machines
---
## Nice to Have
*Important for consistency across machines*
### 8. IDE Configuration Management
**VS Code:**
- [ ] Migrate `settings.json` to dotfiles (separate user vs workspace settings)
- [ ] Add `keybindings.json` template
- [ ] Create extensions list and installation script
- [ ] Document settings sync strategy (Settings Sync vs chezmoi)
- [ ] Add snippets directory
- [ ] Configure language-specific settings
**Cursor:**
- [ ] Determine config overlap with VS Code
- [ ] Manage Cursor-specific settings
- [ ] Add Cursor AI configuration
- [ ] Document Cursor vs VS Code decision criteria
- [ ] Add Cursor to installation workflow
**JetBrains:**
- [ ] Add IDE configs for IntelliJ IDEA
- [ ] Add IDE configs for PyCharm
- [ ] Add IDE configs for other JetBrains IDEs if needed
- [ ] Identify portable vs machine-specific settings
- [ ] Document plugin installation strategy
- [ ] Add color scheme/theme configuration
**Meta:**
- [ ] Create sync strategy for each IDE (template vs symlink vs manual)
- [ ] Document extension/plugin installation automation
- [ ] Add IDE version tracking and update strategy
- [ ] Create IDE-specific .gitignore patterns
### 9. AI Tools Configuration
- [ ] Audit existing AI tool configs (`.claude/`, API keys, prompts)
- [ ] Add Claude Desktop configuration to dotfiles
- [ ] Add Gemini configuration (if applicable)
- [ ] Document per-project vs global AI configurations
- [ ] Create templates for common AI prompts/rules
- [ ] Integrate API keys into Doppler
- [ ] Add model preferences and settings
- [ ] Document AI tool usage workflows
### 10. Development Tool Configurations
**Git:**
- [ ] Expand `.gitconfig.tmpl` (currently at `home/dot_config/git/config-ryan.tmpl`)
- [ ] Add git aliases and shortcuts
- [ ] Configure diff and merge tools
- [ ] Add commit signing configuration
- [ ] Configure git credential helpers
- [ ] Add git hooks templates
**Language Tools:**
- [ ] Add Python development configs (pyproject.toml templates, .python-version)
- [ ] Add Node.js configs (.npmrc, .nvmrc templates)
- [ ] Add Rust configs (rustfmt.toml, clippy settings)
- [ ] Add Go configs (go.env, tool preferences)
- [ ] Add language-specific linter/formatter configs
**Terminal Emulators:**
- [ ] Expand Kitty configuration (currently at `home/dot_config/kitty/`)
- [ ] Add Alacritty config (if used)
- [ ] Document terminal color schemes
- [ ] Add font configuration and Nerd Fonts setup
**Other Tools:**
- [ ] Expand Wakatime config (currently at `home/dot_wakatime.cfg.tmpl`)
- [ ] Add tmux configuration
- [ ] Add vim/neovim basic config
- [ ] Add SSH config template
- [ ] Add GPG configuration
### 11. Package Management Strategy
- [ ] Audit `run_onchange_install-packages.sh.tmpl`
- [ ] Separate Linux, WSL, and Windows package lists
- [ ] Create idempotent package installation scripts
- [ ] Document package dependencies and installation order
- [ ] Add Windows package manager integration (winget/chocolatey/scoop)
- [ ] Add Homebrew package list for Linux
- [ ] Add platform-specific package selection logic
- [ ] Test package installation on clean system
- [ ] Document manual installation steps for proprietary tools
- [ ] Add package version pinning strategy
---
## Polishing
*Nice-to-have improvements and quality of life*
### 12. Enhanced Documentation
- [ ] Expand README.md with comprehensive sections
- [ ] Add ARCHITECTURE.md explaining repo structure
- [ ] Create CONTRIBUTING.md for your future self
- [ ] Add inline comments to all template files
- [ ] Document all chezmoi hooks and their purposes
- [ ] Create REFERENCE.md with template variable reference
- [ ] Add FAQ.md with common issues and solutions
- [ ] Document chezmoi commands cheat sheet
- [ ] Add diagrams for config flow and file organization
- [ ] Create video walkthrough or screenshots
### 13. Quality of Life Improvements
- [ ] Add chezmoi status checking script (detect drift)
- [ ] Create update reminder system (terminal startup notification)
- [ ] Implement "unmanaged files" workflow (mentioned in README.md:48-54)
- [ ] Add fuzzy search for config diffs (fzf integration)
- [ ] Create backup/snapshot system before applying changes
- [ ] Add interactive configuration wizard for new machines
- [ ] Create script to list all managed files
- [ ] Add change preview before applying updates
- [ ] Create rollback mechanism
- [ ] Add performance profiling for shell startup time
### 14. Advanced Features from README "Intended Goals"
- [ ] rbw auto-lock implementation (8hr sessions) (README.md:58-60)
- [ ] Lock rbw when computer sleeps, idle, or screen saver activates
- [ ] GitHub language attributes script (pre-commit hook for .gitattributes) (README.md:71-74)
- [ ] Terminal startup checks for out-of-date configs (README.md:69-70)
- [ ] VS Code automatic setup improvements (README.md:68)
- [ ] Neovim configuration management (README.md:67)
- [ ] Add timer-based update checking with low-latency startup
- [ ] Implement device-specific configuration system (README.md:65)
### 15. Testing & Validation
- [ ] Create test script for fresh installation simulation
- [ ] Add validation for encrypted secrets (age decrypt test)
- [ ] Create pre-commit hooks for template syntax checking
- [ ] Add CI/CD for template validation (GitHub Actions)
- [ ] Document rollback procedures
- [ ] Create test matrix for different platforms (Linux/WSL/Windows)
- [ ] Add shellcheck integration for shell scripts
- [ ] Test hook execution on all platforms
- [ ] Validate Doppler integration
- [ ] Add template rendering test suite
### 16. Cleanup & Maintenance
- [ ] Commit deletion of removed files (nushell/env.nu, dot_gitconfig, etc.)
- [ ] Clean up commented-out code in commonrc.sh.tmpl (lines 122-130)
- [ ] Review and update `.chezmoiignore` patterns
- [ ] Audit and remove unused templates
- [ ] Standardize file naming conventions across repo
- [ ] Remove deprecated hooks (old shell-based hooks if fully migrated to TS)
- [ ] Archive old/unused configuration files
- [ ] Update .gitattributes for proper file type detection
- [ ] Clean up temporary/test files
- [ ] Reorganize directory structure if needed
---
## Legacy Items from Original TODO
These items were in the original TODO.md and need to be categorized/completed:
- [ ] **age executable not installed on init** - Add to Priority 1, Item 1 (installation docs)
- [ ] **rbw executable needs better configuration** - Related to Priority 4, Item 14 (rbw auto-lock)
- [ ] **rbw config not tracked** - Add rbw config to dotfiles
- [ ] **hishtory executable not available on init** - Add to installation checklist
- [ ] **add GPG key to bw** - Add to Priority 1, Item 2 (authentication workflow)
- [ ] **dracula theme tracking, kitty/micro** - Add to Priority 3, Item 10 (dev tools)
- [ ] **lazygit fix difftool** - Add lazygit config to dotfiles
- [ ] **testing in github codespaces** - Add to Priority 4, Item 15 (testing)
---
## Notes
- Items can be worked on in any order within their priority level
- Some items have dependencies (e.g., documentation should reflect implemented changes)
- Use `chezmoi cd` to navigate to source directory when working on configs
- Test changes in WSL/Linux before applying to Windows (or vice versa)
- Keep encrypted secrets out of git history - use age encryption or Doppler

View File

@@ -54,18 +54,19 @@ args = [
cores = {{ $cpuCores }}
threads = {{ $cpuThreads }}
encryption = "age"
[age]
identity = "{{ .chezmoi.homeDir }}/key.txt"
recipient = "age1s3ctpj9lafl6qwyvd89sn448us7gdzd53d8yyhsc7zny78c0k4sqerrkze"
encryption = "age"
[doppler]
project = "dotfiles"
config = "production"
[hooks.init.pre]
command = "{{ .chezmoi.sourceDir }}/hooks/.init_pre.ts"
command = "bun"
args = ["{{ .chezmoi.sourceDir }}/hooks/.init_pre.ts"]
[hooks.update.pre]
command = "{{ .chezmoi.sourceDir }}/hooks/.update_pre.sh"
[hooks.read-source-state.pre]
command = "{{ .chezmoi.sourceDir }}/hooks/.read-source-state_pre.sh"
command = "bun"
args = ["{{ .chezmoi.sourceDir }}/hooks/.update_pre.ts"]

View File

@@ -14,21 +14,27 @@ tool-versions
.asdf/repository/**
{{ if eq .chezmoi.os "windows" }}
{{/* Ignore Linux/Unix-only files on Windows */}}
# Shell configs (Linux-only)
.oh-my-zsh
.scripts
*.zsh
.zshrc
.bashrc
.profile
.bash_aliases
key.txt
.passwd-s3fs.age
.profile
.tmux.conf
{{/* this may be pretty broad, will need to be adjusted */}}
.config
# Linux-only config directories
.config/kitty
{{ else }}
{{/* Ignore Windows-only files on Linux/macOS */}}
Documents
# Windows-only
Documents/PowerShell
{{ end }}

View File

@@ -128,8 +128,3 @@ fi
# else
# export EDITOR='nvim'
# fi
# If WSL, add SSH key on startup (once per WSL start)
{{- if .data.wsl }}
eval `keychain --quiet --eval --agents ssh ~/.ssh/id_rsa`
{{ end }}

View File

@@ -0,0 +1,134 @@
# {{ template "banner.tmpl" .}}
# PowerShell Profile for Windows
# Managed by chezmoi
# Disable PowerShell update notifications
$env:POWERSHELL_UPDATE_CHECK = "Off"
# Editor configuration
$env:EDITOR = "micro"
$env:MICRO_TRUECOLOR = 1
# OpenAI API Key
$env:OPENAI_API_KEY = "{{ dopplerProjectJson.OPENAI_CHATGPT_CLI }}"
# PATH additions - Windows style
# User local bin
$env:PATH = "$env:USERPROFILE\.local\bin;$env:PATH"
# Go
if (Test-Path "$env:USERPROFILE\go") {
$env:PATH = "$env:USERPROFILE\go\bin;$env:PATH"
}
if (Test-Path "C:\Program Files\Go") {
$env:PATH = "C:\Program Files\Go\bin;$env:PATH"
}
# Rust/Cargo
if (Test-Path "$env:USERPROFILE\.cargo") {
$env:PATH = "$env:USERPROFILE\.cargo\bin;$env:PATH"
}
# Deno
if (Test-Path "$env:USERPROFILE\.deno") {
$env:DENO_INSTALL = "$env:USERPROFILE\.deno"
$env:PATH = "$env:DENO_INSTALL\bin;$env:PATH"
}
# Node/pnpm
if (Test-Path "$env:LOCALAPPDATA\pnpm") {
$env:PNPM_HOME = "$env:LOCALAPPDATA\pnpm"
$env:PATH = "$env:PNPM_HOME;$env:PATH"
}
# Bun
if (Test-Path "$env:USERPROFILE\.bun") {
$env:BUN_INSTALL = "$env:USERPROFILE\.bun"
$env:PATH = "$env:BUN_INSTALL\bin;$env:PATH"
}
# Python/pyenv (Windows)
if (Test-Path "$env:USERPROFILE\.pyenv\pyenv-win") {
$env:PYENV = "$env:USERPROFILE\.pyenv\pyenv-win"
$env:PYENV_ROOT = "$env:PYENV"
$env:PYENV_HOME = "$env:PYENV"
$env:PATH = "$env:PYENV\bin;$env:PYENV\shims;$env:PATH"
}
# .NET
if (Test-Path "$env:USERPROFILE\.dotnet") {
$env:DOTNET_ROOT = "$env:USERPROFILE\.dotnet"
$env:PATH = "$env:DOTNET_ROOT;$env:DOTNET_ROOT\tools;$env:PATH"
}
# Java/jenv (if using jenv-for-windows or similar)
if (Test-Path "$env:USERPROFILE\.jenv") {
$env:PATH = "$env:USERPROFILE\.jenv\bin;$env:PATH"
}
# Bob (Neovim version manager)
if (Test-Path "$env:LOCALAPPDATA\bob\nvim-bin") {
$env:PATH = "$env:LOCALAPPDATA\bob\nvim-bin;$env:PATH"
}
# Spicetify
if (Test-Path "$env:USERPROFILE\.spicetify") {
$env:PATH = "$env:USERPROFILE\.spicetify;$env:PATH"
}
# Pulumi
if (Test-Path "$env:USERPROFILE\.pulumi\bin") {
$env:PATH = "$env:USERPROFILE\.pulumi\bin;$env:PATH"
}
# Scoop (if installed)
if (Test-Path "$env:USERPROFILE\scoop\shims") {
$env:PATH = "$env:USERPROFILE\scoop\shims;$env:PATH"
}
# Chocolatey profile (if exists)
$ChocolateyProfile = "$env:ChocolateyInstall\helpers\chocolateyProfile.psm1"
if (Test-Path $ChocolateyProfile) {
Import-Module $ChocolateyProfile
}
# mise - polyglot tool version manager
# Activates mise if installed (provides tools like vault, node, python, etc.)
if (Get-Command mise -ErrorAction SilentlyContinue) {
Invoke-Expression (& mise activate pwsh | Out-String)
}
# Aliases - PowerShell equivalents of bash aliases
Set-Alias -Name nano -Value micro
Set-Alias -Name vim -Value nvim
Set-Alias -Name lg -Value lazygit
# Functions
function ll { Get-ChildItem -Force | Format-Table -AutoSize }
function la { Get-ChildItem -Force }
function es { & $PROFILE } # Reload profile
# Chezmoi aliases
function cha { chezmoi apply --interactive }
Set-Alias -Name ch -Value chezmoi
# Git aliases
function ga { git add $args }
function gaa { git add . }
function gc { git commit $args }
function gcm { git commit -m $args }
function gco { git checkout $args }
function gd { git diff $args }
function gs { git status $args }
function gp { git pull $args }
function gst { git stash $args }
# Initialize completions if available
if (Get-Command chezmoi -ErrorAction SilentlyContinue) {
# Chezmoi completion can be set up if needed
}
# VSCode integration
if ($env:TERM_PROGRAM -eq "vscode") {
# VSCode shell integration
}

View File

@@ -0,0 +1,13 @@
# Ryan Walters identity override
# Use this for work/professional repositories
#
# To use in a repository, run:
# git config --local include.path ~/.config/git/config-ryan
[user]
name = Ryan Walters
email = ryan@walters.to
signingkey = 39538EC79ACF2597
{{ if eq .chezmoi.os "windows" }}
{{ else }}
{{ end }}

View File

@@ -0,0 +1,13 @@
# Xevion identity override
# Use this for personal/open-source repositories
#
# To use in a repository, run:
# git config --local include.path ~/.config/git/config-xevion
[user]
name = Xevion
email = xevion@xevion.dev
signingkey = C217005CF3C00672
{{ if eq .chezmoi.os "windows" }}
{{ else }}
{{ end }}

View File

@@ -897,3 +897,19 @@ $env.config = {
}
]
}
# mise - polyglot tool version manager
# Activates mise if installed (provides tools like vault, node, python, etc.)
# This adds mise-managed tool paths to $env.PATH dynamically based on the current directory
if (which mise | is-not-empty) {
$env.MISE_SHELL = "nu"
# Create the mise activation directory if it doesn't exist
let mise_cache = $"($nu.data-dir)/mise"
mkdir $mise_cache
# Run mise hook to setup environment for current directory
$env.PATH = ($env.PATH | split row (char esep))
mise hook-env -s nu | save --force $"($mise_cache)/hook-env.nu"
source $"($mise_cache)/hook-env.nu"
}

View File

@@ -1,101 +0,0 @@
# Nushell Environment Config File
#
# version = "0.98.0"
def create_left_prompt [] {
let dir = match (do --ignore-shell-errors { $env.PWD | path relative-to $nu.home-path }) {
null => $env.PWD
'' => '~'
$relative_pwd => ([~ $relative_pwd] | path join)
}
let path_color = (if (is-admin) { ansi red_bold } else { ansi green_bold })
let separator_color = (if (is-admin) { ansi light_red_bold } else { ansi light_green_bold })
let path_segment = $"($path_color)($dir)(ansi reset)"
$path_segment | str replace --all (char path_sep) $"($separator_color)(char path_sep)($path_color)"
}
def create_right_prompt [] {
# create a right prompt in magenta with green separators and am/pm underlined
let time_segment = ([
(ansi reset)
(ansi magenta)
(date now | format date '%x %X') # try to respect user's locale
] | str join | str replace --regex --all "([/:])" $"(ansi green)${1}(ansi magenta)" |
str replace --regex --all "([AP]M)" $"(ansi magenta_underline)${1}")
let last_exit_code = if ($env.LAST_EXIT_CODE != 0) {([
(ansi rb)
($env.LAST_EXIT_CODE)
] | str join)
} else { "" }
([$last_exit_code, (char space), $time_segment] | str join)
}
# Use nushell functions to define your right and left prompt
$env.PROMPT_COMMAND = {|| create_left_prompt }
# FIXME: This default is not implemented in rust code as of 2023-09-08.
$env.PROMPT_COMMAND_RIGHT = {|| create_right_prompt }
# The prompt indicators are environmental variables that represent
# the state of the prompt
$env.PROMPT_INDICATOR = {|| "> " }
$env.PROMPT_INDICATOR_VI_INSERT = {|| ": " }
$env.PROMPT_INDICATOR_VI_NORMAL = {|| "> " }
$env.PROMPT_MULTILINE_INDICATOR = {|| "::: " }
# If you want previously entered commands to have a different prompt from the usual one,
# you can uncomment one or more of the following lines.
# This can be useful if you have a 2-line prompt and it's taking up a lot of space
# because every command entered takes up 2 lines instead of 1. You can then uncomment
# the line below so that previously entered commands show with a single `🚀`.
# $env.TRANSIENT_PROMPT_COMMAND = {|| "🚀 " }
# $env.TRANSIENT_PROMPT_INDICATOR = {|| "" }
# $env.TRANSIENT_PROMPT_INDICATOR_VI_INSERT = {|| "" }
# $env.TRANSIENT_PROMPT_INDICATOR_VI_NORMAL = {|| "" }
# $env.TRANSIENT_PROMPT_MULTILINE_INDICATOR = {|| "" }
# $env.TRANSIENT_PROMPT_COMMAND_RIGHT = {|| "" }
# Specifies how environment variables are:
# - converted from a string to a value on Nushell startup (from_string)
# - converted from a value back to a string when running external commands (to_string)
# Note: The conversions happen *after* config.nu is loaded
$env.ENV_CONVERSIONS = {
"PATH": {
from_string: { |s| $s | split row (char esep) | path expand --no-symlink }
to_string: { |v| $v | path expand --no-symlink | str join (char esep) }
}
"Path": {
from_string: { |s| $s | split row (char esep) | path expand --no-symlink }
to_string: { |v| $v | path expand --no-symlink | str join (char esep) }
}
}
# Directories to search for scripts when calling source or use
# The default for this is $nu.default-config-dir/scripts
$env.NU_LIB_DIRS = [
($nu.default-config-dir | path join 'scripts') # add <nushell-config-dir>/scripts
($nu.data-dir | path join 'completions') # default home for nushell completions
]
# Directories to search for plugin binaries when calling register
# The default for this is $nu.default-config-dir/plugins
$env.NU_PLUGIN_DIRS = [
($nu.default-config-dir | path join 'plugins') # add <nushell-config-dir>/plugins
]
# To add entries to PATH (on Windows you might use Path), you can use the following pattern:
# $env.PATH = ($env.PATH | split row (char esep) | prepend '/some/path')
# An alternate way to add entries to $env.PATH is to use the custom command `path add`
# which is built into the nushell stdlib:
# use std "path add"
# $env.PATH = ($env.PATH | split row (char esep))
# path add /some/path
# path add ($env.CARGO_HOME | path join "bin")
# path add ($env.HOME | path join ".local" "bin")
# $env.PATH = ($env.PATH | uniq)
# To load from a custom file you can use:
# source ($nu.default-config-dir | path join 'custom.nu')

View File

@@ -0,0 +1,242 @@
# {{ template "banner.tmpl" .}}
# Nushell Environment Config File
# Cross-platform configuration for Windows and Linux
# version = "0.98.0"
def create_left_prompt [] {
let dir = match (try { $env.PWD | path relative-to $nu.home-path } catch { null }) {
null => $env.PWD
'' => '~'
$relative_pwd => ([~ $relative_pwd] | path join)
}
let path_color = (if (is-admin) { ansi red_bold } else { ansi green_bold })
let separator_color = (if (is-admin) { ansi light_red_bold } else { ansi light_green_bold })
let path_segment = $"($path_color)($dir)(ansi reset)"
$path_segment | str replace --all (char path_sep) $"($separator_color)(char path_sep)($path_color)"
}
def create_right_prompt [] {
let time_segment = ([
(ansi reset)
(ansi magenta)
(date now | format date '%x %X')
] | str join | str replace --regex --all "([/:])" $"(ansi green)${1}(ansi magenta)" |
str replace --regex --all "([AP]M)" $"(ansi magenta_underline)${1}")
let last_exit_code = if ($env.LAST_EXIT_CODE != 0) {([
(ansi rb)
($env.LAST_EXIT_CODE)
] | str join)
} else { "" }
([$last_exit_code, (char space), $time_segment] | str join)
}
$env.PROMPT_COMMAND = {|| create_left_prompt }
$env.PROMPT_COMMAND_RIGHT = {|| create_right_prompt }
$env.PROMPT_INDICATOR = {|| "> " }
$env.PROMPT_INDICATOR_VI_INSERT = {|| ": " }
$env.PROMPT_INDICATOR_VI_NORMAL = {|| "> " }
$env.PROMPT_MULTILINE_INDICATOR = {|| "::: " }
# Environment variable conversions
$env.ENV_CONVERSIONS = {
"PATH": {
from_string: { |s| $s | split row (char esep) | path expand --no-symlink }
to_string: { |v| $v | path expand --no-symlink | str join (char esep) }
}
"Path": {
from_string: { |s| $s | split row (char esep) | path expand --no-symlink }
to_string: { |v| $v | path expand --no-symlink | str join (char esep) }
}
}
# Library and plugin directories
$env.NU_LIB_DIRS = [
($nu.default-config-dir | path join 'scripts')
($nu.data-dir | path join 'completions')
]
$env.NU_PLUGIN_DIRS = [
($nu.default-config-dir | path join 'plugins')
]
# Editor configuration
$env.EDITOR = "micro"
$env.MICRO_TRUECOLOR = 1
# OpenAI API Key
$env.OPENAI_API_KEY = "{{ dopplerProjectJson.OPENAI_CHATGPT_CLI }}"
# Initialize PATH as a list for easier manipulation
$env.PATH = ($env.PATH | split row (char esep))
# Platform-specific PATH additions
{{ if eq .chezmoi.os "windows" }}
# Windows PATH additions
# User local bin
$env.PATH = ($env.PATH | prepend ($env.USERPROFILE | path join ".local" "bin"))
# Go
let go_user = ($env.USERPROFILE | path join "go" "bin")
let go_system = "C:\\Program Files\\Go\\bin"
if ($go_user | path exists) { $env.PATH = ($env.PATH | prepend $go_user) }
if ($go_system | path exists) { $env.PATH = ($env.PATH | prepend $go_system) }
# Rust/Cargo
let cargo_bin = ($env.USERPROFILE | path join ".cargo" "bin")
if ($cargo_bin | path exists) { $env.PATH = ($env.PATH | prepend $cargo_bin) }
# Deno
let deno_bin = ($env.USERPROFILE | path join ".deno" "bin")
if ($deno_bin | path exists) {
$env.DENO_INSTALL = ($env.USERPROFILE | path join ".deno")
$env.PATH = ($env.PATH | prepend $deno_bin)
}
# Node/pnpm
let pnpm_home = ($env.LOCALAPPDATA | path join "pnpm")
if ($pnpm_home | path exists) {
$env.PNPM_HOME = $pnpm_home
$env.PATH = ($env.PATH | prepend $pnpm_home)
}
# Bun
let bun_bin = ($env.USERPROFILE | path join ".bun" "bin")
if ($bun_bin | path exists) {
$env.BUN_INSTALL = ($env.USERPROFILE | path join ".bun")
$env.PATH = ($env.PATH | prepend $bun_bin)
}
# Python/pyenv
let pyenv_root = ($env.USERPROFILE | path join ".pyenv" "pyenv-win")
if ($pyenv_root | path exists) {
$env.PYENV_ROOT = $pyenv_root
$env.PATH = ($env.PATH | prepend ($pyenv_root | path join "bin"))
$env.PATH = ($env.PATH | prepend ($pyenv_root | path join "shims"))
}
# .NET
let dotnet_root = ($env.USERPROFILE | path join ".dotnet")
if ($dotnet_root | path exists) {
$env.DOTNET_ROOT = $dotnet_root
$env.PATH = ($env.PATH | prepend $dotnet_root)
$env.PATH = ($env.PATH | prepend ($dotnet_root | path join "tools"))
}
# Bob (Neovim version manager)
let bob_bin = ($env.LOCALAPPDATA | path join "bob" "nvim-bin")
if ($bob_bin | path exists) { $env.PATH = ($env.PATH | prepend $bob_bin) }
# Spicetify
let spicetify = ($env.USERPROFILE | path join ".spicetify")
if ($spicetify | path exists) { $env.PATH = ($env.PATH | prepend $spicetify) }
# Pulumi
let pulumi_bin = ($env.USERPROFILE | path join ".pulumi" "bin")
if ($pulumi_bin | path exists) { $env.PATH = ($env.PATH | prepend $pulumi_bin) }
# Scoop
let scoop_shims = ($env.USERPROFILE | path join "scoop" "shims")
if ($scoop_shims | path exists) { $env.PATH = ($env.PATH | prepend $scoop_shims) }
{{ else }}
# Linux/macOS PATH additions
# User local bin
$env.PATH = ($env.PATH | prepend ($env.HOME | path join ".local" "bin"))
# System bins
$env.PATH = ($env.PATH | prepend "/usr/local/bin")
$env.PATH = ($env.PATH | prepend ($env.HOME | path join "bin"))
# Go
let go_bin = "/usr/local/go/bin"
let go_user = ($env.HOME | path join "go" "bin")
if ($go_bin | path exists) { $env.PATH = ($env.PATH | prepend $go_bin) }
if ($go_user | path exists) { $env.PATH = ($env.PATH | prepend $go_user) }
# Rust/Cargo
let cargo_bin = ($env.HOME | path join ".cargo" "bin")
if ($cargo_bin | path exists) { $env.PATH = ($env.PATH | prepend $cargo_bin) }
# Deno
let deno_bin = ($env.HOME | path join ".deno" "bin")
if ($deno_bin | path exists) { $env.PATH = ($env.PATH | prepend $deno_bin) }
# Bob (Neovim version manager)
let bob_bin = ($env.HOME | path join ".local" "share" "bob" "nvim-bin")
if ($bob_bin | path exists) { $env.PATH = ($env.PATH | prepend $bob_bin) }
# Homebrew (Linux)
let brew_bin = "/home/linuxbrew/.linuxbrew/bin"
if ($brew_bin | path exists) {
$env.PATH = ($env.PATH | prepend $brew_bin)
$env.PATH = ($env.PATH | prepend "/home/linuxbrew/.linuxbrew/sbin")
}
# pnpm
let pnpm_home = ($env.HOME | path join ".local" "share" "pnpm")
if ($pnpm_home | path exists) {
$env.PNPM_HOME = $pnpm_home
$env.PATH = ($env.PATH | prepend $pnpm_home)
}
# Bun
let bun_bin = ($env.HOME | path join ".bun" "bin")
if ($bun_bin | path exists) {
$env.BUN_INSTALL = ($env.HOME | path join ".bun")
$env.PATH = ($env.PATH | prepend $bun_bin)
}
# pyenv
let pyenv_root = ($env.HOME | path join ".pyenv")
if ($pyenv_root | path exists) {
$env.PYENV_ROOT = $pyenv_root
$env.PATH = ($env.PATH | prepend ($pyenv_root | path join "bin"))
}
# jenv (Java)
let jenv_bin = ($env.HOME | path join ".jenv" "bin")
if ($jenv_bin | path exists) { $env.PATH = ($env.PATH | prepend $jenv_bin) }
# .NET
let dotnet_root = ($env.HOME | path join ".dotnet")
if ($dotnet_root | path exists) {
$env.DOTNET_ROOT = $dotnet_root
$env.PATH = ($env.PATH | prepend $dotnet_root)
$env.PATH = ($env.PATH | prepend ($dotnet_root | path join "tools"))
}
# Spicetify
let spicetify = ($env.HOME | path join ".spicetify")
if ($spicetify | path exists) { $env.PATH = ($env.PATH | prepend $spicetify) }
# Pulumi
let pulumi_bin = ($env.HOME | path join ".pulumi" "bin")
if ($pulumi_bin | path exists) { $env.PATH = ($env.PATH | prepend $pulumi_bin) }
# Perl (if installed)
let perl_bin = ($env.HOME | path join "perl5" "bin")
if ($perl_bin | path exists) {
$env.PATH = ($env.PATH | prepend $perl_bin)
$env.PERL5LIB = ($env.HOME | path join "perl5" "lib" "perl5")
$env.PERL_LOCAL_LIB_ROOT = ($env.HOME | path join "perl5")
}
# hishtory
let hishtory_bin = ($env.HOME | path join ".hishtory")
if ($hishtory_bin | path exists) { $env.PATH = ($env.PATH | prepend $hishtory_bin) }
{{ end }}
# Remove duplicates from PATH
$env.PATH = ($env.PATH | uniq)
# WSL-specific settings
{{ if .wsl }}
# Ensure CLI apps open URLs in Windows browser
$env.BROWSER = 'powershell.exe /c start'
{{ end }}

View File

@@ -1,16 +0,0 @@
[user]
name = Xevion
email = xevion@xevion.dev
# signingkey = C217005CF3C00672
# [commit]
# gpgsign = true
[credential "https://github.com"]
helper =
helper = !/usr/bin/gh auth git-credential
[credential "https://gist.github.com"]
helper =
helper = !/usr/bin/gh auth git-credential
[core]
editor = micro
[init]
defaultBranch = master

56
home/dot_gitconfig.tmpl Normal file
View File

@@ -0,0 +1,56 @@
# Git Configuration - Platform-aware
# Managed by chezmoi
{{ if eq .chezmoi.os "windows" }}
# Windows Configuration
[user]
name = Ryan Walters
email = ryan@walters.to
signingkey = 39538EC79ACF2597
[commit]
gpgsign = true
[gpg]
program = C:\\Users\\Xevion\\scoop\\apps\\gpg4win\\current\\GnuPG\\bin\\gpg.exe
[credential "https://github.com"]
helper =
helper = !'C:\\Program Files\\GitHub CLI\\gh.exe' auth git-credential
[credential "https://gist.github.com"]
helper =
helper = !'C:\\Program Files\\GitHub CLI\\gh.exe' auth git-credential
{{ else }}
# Linux/macOS Configuration
[user]
name = Xevion
email = xevion@xevion.dev
signingkey = C217005CF3C00672
[commit]
gpgsign = true
[credential "https://github.com"]
helper =
helper = !/usr/bin/gh auth git-credential
[credential "https://gist.github.com"]
helper =
helper = !/usr/bin/gh auth git-credential
{{ end }}
# Common configuration for all platforms
[core]
editor = micro
[init]
defaultBranch = master
[filter.lfs]
required = true
clean = git-lfs clean -- %f
smudge = git-lfs smudge -- %f
process = git-lfs filter-process

View File

@@ -1,28 +1,27 @@
#!/usr/bin/env -S deno run -A
#!/usr/bin/env bun
console.log("init_pre.ts");
import { resolve } from "https://deno.land/std/path/mod.ts";
import { exists } from "jsr:@std/fs";
import { exists } from "node:fs/promises";
import { join } from "node:path";
import { $, os } from "npm:zx@8.3.2";
import { homedir } from "node:os";
import { $ } from "bun";
const { exit } = Deno;
const filePath = join(os.homedir(), "key.txt");
const filePath = join(homedir(), "key.txt");
if (await exists(resolve(filePath))) {
if (await exists(filePath)) {
console.log("key.txt already exists");
Deno.exit(0);
process.exit(0);
}
// Acquire the secret from Doppler
const result = await $`doppler secrets get KEY_TXT --plain`;
const result = await $`doppler secrets get KEY_TXT --plain`.quiet();
// Check if the command was successful
if (result.exitCode !== 0) {
console.error("Failed to get secret KEY_TXT");
exit(1);
process.exit(1);
}
// Write the secret to a file
await Deno.writeTextFile(resolve(filePath), result.stdout);
await Bun.write(filePath, result.stdout);
console.log("key.txt bootstrapped");

View File

@@ -1,92 +0,0 @@
#!/bin/bash
set -eu
# Flag variables
LATE_FAIL_EXIT=false # Set to true if any installation fails, but only raise an exit at the end
DOPPLER_UNAVAILABLE=false # Set to true if Doppler is not available
apt_update() {
# Only run apt update once
if [ -f /tmp/.apt-updated ]; then
return
fi
sudo apt update >/dev/null
if [ $? -ne 0 ]; then
echo "chezmoi: Critical issue - failed to update apt!"
exit 1
else
touch /tmp/.apt-updated
fi
}
install_age() {
# Test if age is installed
command -v age >/dev/null 2>&1 && return
# Install age
apt_update
sudo apt install age
}
# install_cargo_binstall() {
# # Test if cargo binstall is installed
# cargo binstall --help >/dev/null 2>&1
# if [ $? -eq 0 ]; then
# return
# fi
# curl -L --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash
# # Test again
# cargo binstall --help
# if [ $? -ne 0 ]; then
# echo "Failed to install cargo binstall"
# exit 1
# fi
# }
install_inotify() {
if ! dpkg -l inotify-tools >/dev/null 2>&1; then
echo "Installing inotify-tools"
apt_update
sudo apt install inotify-tools
fi
}
install_doppler() {
if ! command -v doppler >/dev/null 2>&1; then
echo "You need to install the Doppler CLI manually (for security purposes)."
echo "https://docs.doppler.com/docs/cli#installation"
DOPPLER_UNAVAILABLE=true
LATE_FAIL_EXIT=true
fi
}
require_doppler_login() {
doppler me >/dev/null 2>&1
if [ $? -ne 0 ]; then
echo "You need to login to Doppler."
echo "https://docs.doppler.com/docs/cli#logging-in"
fi
}
install_deno() {
if ! command -v deno >/dev/null 2>&1; then
echo "Installing Deno"
curl -fsSL https://deno.land/install.sh | sh
fi
}
install_inotify
install_age
# install_cargo_binstall
if [ $DOPPLER_UNAVAILABLE = false ]; then
install_doppler
fi
if [ $LATE_FAIL_EXIT = true ]; then
echo "chezmoi: Some installation(s) failed. Please fix the issues detailed before trying again."
exit 1
fi

View File

@@ -1,7 +0,0 @@
#!/bin/bash
# chezmoi update --init does not invoke the 'hooks.init.pre' hook, so we do it ourselves
if grep -q 'init' <<<$CHEZMOI_ARGS; then
# CHEZMOI_UPDATE is just a hint in case we need to know if we're updating
CHEZMOI_UPDATE=1 $(dirname $0)/.init_pre.ts
fi

19
home/hooks/.update_pre.ts Normal file
View File

@@ -0,0 +1,19 @@
#!/usr/bin/env bun
// chezmoi update --init does not invoke the 'hooks.init.pre' hook, so we do it ourselves
const chezmoiArgs = process.env.CHEZMOI_ARGS || '';
if (chezmoiArgs.includes('init')) {
// CHEZMOI_UPDATE is just a hint in case we need to know if we're updating
const scriptDir = import.meta.dir;
const initPreScript = `${scriptDir}/.init_pre.ts`;
await Bun.spawn(['bun', initPreScript], {
env: {
...process.env,
CHEZMOI_UPDATE: '1'
},
stdout: 'inherit',
stderr: 'inherit'
});
}