From db383de182cf8f798f254f1064abb8ea85d0ca92 Mon Sep 17 00:00:00 2001 From: ryoya ito <30540303+ry-itto@users.noreply.github.com> Date: Tue, 28 Apr 2026 15:50:25 +0900 Subject: [PATCH 01/10] =?UTF-8?q?feat(chezmoi):=20Makefile=20=E3=83=99?= =?UTF-8?q?=E3=83=BC=E3=82=B9=E3=81=8B=E3=82=89=20chezmoi=20+=20mise=20?= =?UTF-8?q?=E7=AE=A1=E7=90=86=E3=81=AB=E7=A7=BB=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - dotfiles を `dot_*` 形式にリネームし chezmoi のソース構造へ - VSCode 設定を `private_Library/private_Application Support/Code/User/settings.json` に集約 - installer/settings 群を `run_onchange_*` (defaults write 系) と `run_once_*` (zplug, dein, mise install) に再編 - 言語ランタイム (flutter, rust, node, ruby) を mise で管理 (`dot_config/mise/config.toml`) - `.chezmoiignore` で repo support files / destination ローカル生成物を除外 - CI を chezmoi-verify ベースに刷新、Bats / make 依存ジョブを廃止 - README / CLAUDE.md / .gitignore を新運用 (chezmoi edit / mise / brew bundle) に追従 Co-Authored-By: Claude Opus 4.7 (1M context) --- .chezmoiignore | 22 ++ .github/workflows/ci.yml | 229 +++++------------- .gitignore | 19 +- CLAUDE.md | 140 ++++++----- Makefile | 48 ---- README.md | 202 ++++++--------- README.template.md | 200 ++++++--------- asdf-dart.huC7pJ/sdk.zip | 1 - .Brewfile => dot_Brewfile | 0 .../agents/serena-expert.md | 0 {.claude => dot_claude}/commands/serena.md | 0 {.claude => dot_claude}/settings.json | 0 .commit_template => dot_commit_template | 0 dot_config/mise/config.toml | 5 + .../nvim/autoload/plugins/nvim_lsp.vim | 0 {.config => dot_config}/nvim/init.vim | 0 {.config => dot_config}/starship.toml | 0 .gitconfig => dot_gitconfig | 0 {.hammerspoon => dot_hammerspoon}/init.lua | 0 .tmux.conf => dot_tmux.conf | 0 {.vim => dot_vim}/README.md | 0 {.vim => dot_vim}/ftdetect/cocoapods.vim | 0 {.vim => dot_vim}/ftdetect/fastlane.vim | 0 {.vim => dot_vim}/ftplugin/dart.vim | 0 {.vim => dot_vim}/ftplugin/ruby.vim | 0 {.vim => dot_vim}/ftplugin/yaml.vim | 0 {.vim => dot_vim}/init/bindings.vim | 0 {.vim => dot_vim}/init/setting.vim | 0 {.vim => dot_vim}/rc/dein.toml | 0 {.vim => dot_vim}/rc/dein_lazy.toml | 0 .wezterm.lua => dot_wezterm.lua | 0 {.zsh => dot_zsh}/alias.zsh | 0 .../reload => dot_zsh/bin/executable_reload | 0 {.zsh => dot_zsh}/env.zsh | 0 {.zsh => dot_zsh}/functions/functions.zsh | 0 {.zsh => dot_zsh}/functions/fzf-git.sh | 0 {.zsh => dot_zsh}/functions/ghq.zsh | 0 {.zsh => dot_zsh}/functions/git.zsh | 0 {.zsh => dot_zsh}/functions/github.zsh | 0 {.zsh => dot_zsh}/plugin.zsh | 0 {.zsh => dot_zsh}/style.zsh | 0 .zshrc => dot_zshrc | 0 installers/flutter.sh | 9 - installers/rust.sh | 6 - installers/vim.sh | 11 - installers/xcode.sh | 15 -- installers/zplug.sh | 4 - .../Code/User}/settings.json | 0 run_once_install-dein.sh | 18 ++ run_once_install-mise-tools.sh | 11 + run_once_install-zplug.sh | 8 + ...> run_onchange_configure-macos-defaults.sh | 17 +- run_onchange_configure-xcode.sh | 18 ++ ...run_onchange_install-brew-packages.sh.tmpl | 14 +- scripts/parse_brewfile.py | 2 +- settings/vscode/install-extensions.sh | 28 --- settings/vscode/install.sh | 11 - settings/xcode/install.sh | 15 -- tests/configuration.bats | 119 --------- tests/installers.bats | 96 -------- tests/symlinks.bats | 96 -------- tests/test_helper.bash | 77 ------ 62 files changed, 418 insertions(+), 1023 deletions(-) create mode 100644 .chezmoiignore delete mode 100644 Makefile delete mode 100644 asdf-dart.huC7pJ/sdk.zip rename .Brewfile => dot_Brewfile (100%) rename {.claude => dot_claude}/agents/serena-expert.md (100%) rename {.claude => dot_claude}/commands/serena.md (100%) rename {.claude => dot_claude}/settings.json (100%) rename .commit_template => dot_commit_template (100%) create mode 100644 dot_config/mise/config.toml rename {.config => dot_config}/nvim/autoload/plugins/nvim_lsp.vim (100%) rename {.config => dot_config}/nvim/init.vim (100%) rename {.config => dot_config}/starship.toml (100%) rename .gitconfig => dot_gitconfig (100%) rename {.hammerspoon => dot_hammerspoon}/init.lua (100%) rename .tmux.conf => dot_tmux.conf (100%) rename {.vim => dot_vim}/README.md (100%) rename {.vim => dot_vim}/ftdetect/cocoapods.vim (100%) rename {.vim => dot_vim}/ftdetect/fastlane.vim (100%) rename {.vim => dot_vim}/ftplugin/dart.vim (100%) rename {.vim => dot_vim}/ftplugin/ruby.vim (100%) rename {.vim => dot_vim}/ftplugin/yaml.vim (100%) rename {.vim => dot_vim}/init/bindings.vim (100%) rename {.vim => dot_vim}/init/setting.vim (100%) rename {.vim => dot_vim}/rc/dein.toml (100%) rename {.vim => dot_vim}/rc/dein_lazy.toml (100%) rename .wezterm.lua => dot_wezterm.lua (100%) rename {.zsh => dot_zsh}/alias.zsh (100%) rename .zsh/bin/reload => dot_zsh/bin/executable_reload (100%) rename {.zsh => dot_zsh}/env.zsh (100%) rename {.zsh => dot_zsh}/functions/functions.zsh (100%) rename {.zsh => dot_zsh}/functions/fzf-git.sh (100%) rename {.zsh => dot_zsh}/functions/ghq.zsh (100%) rename {.zsh => dot_zsh}/functions/git.zsh (100%) rename {.zsh => dot_zsh}/functions/github.zsh (100%) rename {.zsh => dot_zsh}/plugin.zsh (100%) rename {.zsh => dot_zsh}/style.zsh (100%) rename .zshrc => dot_zshrc (100%) delete mode 100755 installers/flutter.sh delete mode 100755 installers/rust.sh delete mode 100755 installers/vim.sh delete mode 100755 installers/xcode.sh delete mode 100755 installers/zplug.sh rename {settings/vscode => private_Library/private_Application Support/Code/User}/settings.json (100%) create mode 100755 run_once_install-dein.sh create mode 100755 run_once_install-mise-tools.sh create mode 100755 run_once_install-zplug.sh rename settings/macos/install.sh => run_onchange_configure-macos-defaults.sh (64%) create mode 100755 run_onchange_configure-xcode.sh rename installers/brew.sh => run_onchange_install-brew-packages.sh.tmpl (57%) delete mode 100755 settings/vscode/install-extensions.sh delete mode 100755 settings/vscode/install.sh delete mode 100644 settings/xcode/install.sh delete mode 100644 tests/configuration.bats delete mode 100644 tests/installers.bats delete mode 100644 tests/symlinks.bats delete mode 100644 tests/test_helper.bash diff --git a/.chezmoiignore b/.chezmoiignore new file mode 100644 index 0000000..5c7a71f --- /dev/null +++ b/.chezmoiignore @@ -0,0 +1,22 @@ +README.md +README.template.md +LICENSE +CLAUDE.md +.github +.gitignore +scripts + +# Destination side files chezmoi must not touch +.claude/local +.claude/settings.local.json +.claude/hooks +.claude/projects +.claude/scripts +.claude/shell-snapshots +.claude/statsig +.claude/todos +.zsh/env_local.zsh +.worktree +firebase-debug.log +.netrwhist +.DS_Store diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d42a0fa..f44d470 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,224 +15,117 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - + - name: Install shellcheck run: | sudo apt-get update sudo apt-get install -y shellcheck - - - name: Run shellcheck on shell scripts - run: | - find . -type f -name "*.sh" -exec shellcheck {} + || true - find . -type f -name "*.zsh" -exec shellcheck --shell=bash {} + 2>/dev/null || true - - - name: Check for syntax errors in zsh files + + - name: Install chezmoi + run: sh -c "$(curl -fsLS get.chezmoi.io)" -- -b /usr/local/bin + + - name: Render chezmoi templates and run shellcheck run: | - for file in $(find . -type f -name "*.zsh" -o -name ".zshrc"); do - if [[ -f "$file" ]]; then - zsh -n "$file" || echo "Syntax check failed for $file" - fi + rendered_dir="$(mktemp -d)" + # Render *.tmpl run scripts so shellcheck can parse them + for tmpl in run_*.sh.tmpl; do + [ -f "$tmpl" ] || continue + out="$rendered_dir/$(basename "${tmpl%.tmpl}")" + chezmoi execute-template --source="$PWD" < "$tmpl" > "$out" done - test: - name: Test - ${{ matrix.test-suite }} on ${{ matrix.os }} - runs-on: ${{ matrix.os }} - continue-on-error: true - strategy: - matrix: - os: [macos-latest] - test-suite: - - configuration - - installers - - symlinks - include: - - os: macos-13 - test-suite: symlinks - fail-fast: false - - steps: - - uses: actions/checkout@v4 - - - name: Cache brew dependencies - uses: actions/cache@v4 - env: - cache-name: cache-brew-dependencies - with: - path: | - ~/Library/Caches/Homebrew - /usr/local/Homebrew - /opt/homebrew - key: ${{ runner.os }}-${{ matrix.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/.Brewfile') }} - restore-keys: | - ${{ runner.os }}-${{ matrix.os }}-build-${{ env.cache-name }}- - ${{ runner.os }}-${{ matrix.os }}-build- - ${{ runner.os }}-${{ matrix.os }}- - - - name: Install Bats + # Lint all *.sh in repo (excluding .git) plus rendered templates + find . -type f -name "*.sh" -not -path "./.git/*" -print0 \ + | xargs -0 shellcheck + find "$rendered_dir" -type f -name "*.sh" -print0 \ + | xargs -0 -r shellcheck + + - name: Check zsh syntax run: | - if ! command -v bats &> /dev/null; then - brew install bats-core - fi - - - name: Run ${{ matrix.test-suite }} tests - run: bats tests/${{ matrix.test-suite }}.bats - - quick-checks: - name: Quick Checks + find . -type f \( -name "*.zsh" -o -name "dot_zshrc" -o -name "executable_*" \) -not -path "./.git/*" -print0 \ + | while IFS= read -r -d '' file; do + zsh -n "$file" || exit 1 + done + + chezmoi-verify: + name: chezmoi verify runs-on: macos-latest - continue-on-error: true - steps: - uses: actions/checkout@v4 - - - name: Test make list - run: | - make list - # Verify that .claude is included - make list | grep "\.claude" || exit 1 - - - name: Test make install (dry run) - run: | - # Create a temporary HOME for testing - export TEST_HOME=$(mktemp -d) - export HOME=$TEST_HOME - make install - # Verify symlinks were created - ls -la $TEST_HOME - # Check that essential dotfiles are linked - test -L $TEST_HOME/.zshrc - test -L $TEST_HOME/.tmux.conf - test -L $TEST_HOME/.gitconfig - - - name: Test installer syntax - run: | - for installer in installers/*.sh; do - echo "Checking syntax of $installer" - zsh -n "$installer" - done - for installer in settings/**/install.sh; do - echo "Checking syntax of $installer" - zsh -n "$installer" - done - - - name: Verify critical files exist + + - name: Install chezmoi + run: sh -c "$(curl -fsLS get.chezmoi.io)" -- -b /usr/local/bin + + - name: chezmoi doctor + run: chezmoi --source="$GITHUB_WORKSPACE" doctor || true + + - name: Apply to ephemeral HOME run: | - test -f .Brewfile - test -f .zshrc - test -f .gitconfig - test -f .tmux.conf - test -f Makefile - test -d .zsh - test -d installers - test -d settings - - integration: - name: Integration Test - runs-on: macos-latest - needs: [lint] - continue-on-error: true - - steps: - - uses: actions/checkout@v4 - - - name: Cache brew dependencies - uses: actions/cache@v4 - env: - cache-name: cache-brew-dependencies - with: - path: | - ~/Library/Caches/Homebrew - /usr/local/Homebrew - /opt/homebrew - key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/.Brewfile') }} - restore-keys: | - ${{ runner.os }}-build-${{ env.cache-name }}- - ${{ runner.os }}-build- - ${{ runner.os }}- - - - name: Full installation test + export HOME="$(mktemp -d)" + export CI=1 + chezmoi init --apply --source="$GITHUB_WORKSPACE" + + - name: Idempotency check run: | - # Set up test environment - export ORIGINAL_HOME=$HOME - export TEST_HOME=$(mktemp -d) - export HOME=$TEST_HOME - - # Run full installation - make all || true - - # Verify installation - echo "=== Verifying installation ===" - ls -la $TEST_HOME - - # Check symlinks - if [[ -L $TEST_HOME/.zshrc ]]; then - echo "✓ .zshrc symlink created" - else - echo "✗ .zshrc symlink missing" + export HOME="$(mktemp -d)" + export CI=1 + chezmoi init --apply --source="$GITHUB_WORKSPACE" + # Second apply should produce no changes + chezmoi apply --source="$GITHUB_WORKSPACE" + diff_output="$(chezmoi diff --source="$GITHUB_WORKSPACE")" + if [ -n "$diff_output" ]; then + echo "::error::chezmoi diff is non-empty after re-apply" + echo "$diff_output" + exit 1 fi - - # Restore HOME - export HOME=$ORIGINAL_HOME - - - name: Test idempotency - run: | - export TEST_HOME=$(mktemp -d) - export HOME=$TEST_HOME - - # Run install twice to test idempotency - make install - make install - - # Should complete without errors - echo "✓ Installation is idempotent" update-readme: name: Update README runs-on: macos-latest - needs: [integration] + needs: [lint, chezmoi-verify] if: github.ref == 'refs/heads/main' && github.event_name == 'push' - + permissions: contents: write - + steps: - uses: actions/checkout@v4 with: token: ${{ secrets.GITHUB_TOKEN }} fetch-depth: 0 - + - name: Set up Python uses: actions/setup-python@v5 with: python-version: '3.11' - + - name: Update README run: | echo "=== Updating README with environment information ===" python3 scripts/update_readme.py - + - name: Check for changes id: check_changes run: | if [[ -n $(git status --porcelain README.md) ]]; then - echo "changes=true" >> $GITHUB_OUTPUT + echo "changes=true" >> "$GITHUB_OUTPUT" echo "README.md has changes" else - echo "changes=false" >> $GITHUB_OUTPUT + echo "changes=false" >> "$GITHUB_OUTPUT" echo "No changes to README.md" fi - + - name: Commit and push changes if: steps.check_changes.outputs.changes == 'true' run: | git config --local user.email "github-actions[bot]@users.noreply.github.com" git config --local user.name "github-actions[bot]" - + git add README.md git commit -m "docs: update README with latest environment info [skip ci] Auto-generated by GitHub Actions Workflow: ${{ github.workflow }} Run: ${{ github.run_number }}" - - git push \ No newline at end of file + + git push diff --git a/.gitignore b/.gitignore index 9809b0b..dcf7785 100644 --- a/.gitignore +++ b/.gitignore @@ -2,21 +2,20 @@ .DS_Store # Local environment settings -.zsh/env_local.zsh +dot_zsh/env_local.zsh # Worktree directories .worktree/ # Claude AI (local settings only) -.claude/local/ -.claude/settings.local.json -.claude/hooks/ -.claude/projects/ -.claude/scripts/ -.claude/shell-snapshots/ -.claude/statsig/ -.claude/todos/ +dot_claude/local/ +dot_claude/settings.local.json +dot_claude/hooks/ +dot_claude/projects/ +dot_claude/scripts/ +dot_claude/shell-snapshots/ +dot_claude/statsig/ +dot_claude/todos/ # Firebase firebase-debug.log - diff --git a/CLAUDE.md b/CLAUDE.md index d196f69..930ae7a 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -4,84 +4,114 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ## Repository Overview -This is a dotfiles repository for macOS development environment setup. It manages system configurations, development tools, and application settings through automated installation scripts. +This is a dotfiles repository for a macOS development environment, managed by [chezmoi](https://www.chezmoi.io/). Dotfiles, run-once installers, and run-onchange configuration scripts are organized using chezmoi's filename conventions (`dot_*`, `private_*`, `executable_*`, `run_once_*`, `run_onchange_*`). + +Language runtimes (Flutter, Rust, Node, Ruby) are managed by [mise](https://mise.jdx.dev/) via `dot_config/mise/config.toml`. Homebrew packages are defined in `dot_Brewfile` and installed by `run_onchange_install-brew-packages.sh.tmpl`. ## Commands ### Setup and Installation + ```bash -# Install all dotfiles and dependencies -make all +# First time on a new machine +brew install chezmoi +chezmoi init --apply ry-itto/dotfiles + +# Pull latest changes from the repo and re-apply +chezmoi update + +# See what would change before applying +chezmoi diff -# Only install dotfiles (symlinks and settings) -make install +# Apply pending changes +chezmoi apply +``` + +### Editing Managed Files -# Only install dependencies (brew, tools, etc.) -make deps +After migrating to chezmoi, editing files directly under `$HOME` does **not** sync back to this repository. Always use one of: + +```bash +# Open the source file in $EDITOR +chezmoi edit ~/.zshrc -# List all dotfiles that will be installed -make list +# Or jump to the source directory and edit there +cd "$(chezmoi source-path)" +$EDITOR dot_zshrc +chezmoi apply ``` -### Manual Installation Scripts +### Adding New Files + ```bash -# Install Homebrew dependencies -/bin/zsh installers/brew.sh - -# Install other tools (run as needed) -/bin/zsh installers/mise.sh -/bin/zsh installers/flutter.sh -/bin/zsh installers/rust.sh -/bin/zsh installers/vim.sh -/bin/zsh installers/xcode.sh -/bin/zsh installers/zplug.sh +# Move an existing $HOME file into chezmoi management +chezmoi add ~/.somefile ``` ## Architecture -### Core Components +### Source Layout + +The repository **is** the chezmoi source directory. chezmoi reads filename prefixes to decide where each file goes in `$HOME`: + +- `dot_` → `~/.` (e.g. `dot_zshrc` → `~/.zshrc`) +- `executable_` → preserves +x bit on apply +- `private_` → applied with mode 0600/0700 +- `.tmpl` → rendered with chezmoi's template engine before apply +- `run_once_.sh` → executed once per machine +- `run_onchange_.sh` → executed when the script's content changes + +### Top-Level Files + +**Managed dotfiles** (chezmoi targets): +- `dot_zshrc` — entrypoint that sources modules under `~/.zsh/` +- `dot_zsh/` — modular Zsh config: `alias.zsh`, `env.zsh`, `style.zsh`, `plugin.zsh`, `functions/`, `bin/executable_reload` +- `dot_tmux.conf`, `dot_gitconfig`, `dot_Brewfile`, `dot_commit_template` +- `dot_vim/`, `dot_wezterm.lua`, `dot_hammerspoon/`, `dot_claude/` +- `dot_config/nvim/`, `dot_config/starship.toml`, `dot_config/mise/config.toml` +- `private_Library/private_Application Support/Code/User/settings.json` — VSCode user settings + +**Run scripts** (executed during `chezmoi apply`): +- `run_onchange_install-brew-packages.sh.tmpl` — re-runs when `dot_Brewfile` changes +- `run_onchange_configure-macos-defaults.sh` — `defaults write` for NSGlobalDomain, Finder, key repeat, Caps Lock → Control +- `run_onchange_configure-xcode.sh` — `defaults write` for Xcode build settings +- `run_once_install-zplug.sh` — bootstrap zplug +- `run_once_install-dein.sh` — bootstrap dein.vim +- `run_once_install-mise-tools.sh` — runs `mise install` for tools defined in `dot_config/mise/config.toml` + +**Configuration**: +- `.chezmoiignore` — paths chezmoi should skip during apply (README, scripts/, CI files, destination-side local files) + +**Repository support files** (excluded from `chezmoi apply` via `.chezmoiignore`): +- `scripts/parse_brewfile.py`, `scripts/update_readme.py` — README generation in CI +- `.github/workflows/ci.yml` — lint, chezmoi-verify, README auto-update +- `README.md`, `README.template.md`, `CLAUDE.md`, `LICENSE` -1. **Makefile**: Main orchestrator that: - - Symlinks dotfiles from repo to home directory - - Copies `.config/` contents to `~/.config/` - - Executes installer scripts in sequence - - Excludes `.DS_Store`, `.git`, `.config`, `.ruby-version`, `.github` from symlinking +### Run Script Execution Order -2. **Dotfiles** (symlinked to home): - - `.Brewfile`: Homebrew bundle configuration with all packages - - `.zshrc`: Main shell configuration that sources modular configs - - `.tmux.conf`: Tmux configuration - - `.gitconfig`: Git configuration - - `.commit_template`: Git commit template +`chezmoi apply` runs `run_*` scripts in lexical order of their filename. The current ordering ensures: -3. **Modular Zsh Configuration** (`.zsh/`): - - `alias.zsh`: Command aliases and shortcuts - - `env.zsh`: Environment variables - - `style.zsh`: Shell appearance and prompt - - `plugin.zsh`: Zsh plugin management +1. `run_onchange_configure-macos-defaults.sh` +2. `run_onchange_configure-xcode.sh` +3. `run_onchange_install-brew-packages.sh` (installs `mise` via Brewfile) +4. `run_once_install-dein.sh` +5. `run_once_install-mise-tools.sh` (skips with a notice if `mise` is not yet on PATH) +6. `run_once_install-zplug.sh` -4. **Installers** (`installers/`): - - Shell scripts for installing various development tools - - Each script checks if tool exists before installation - - Designed to be idempotent +If `mise` is not yet installed when `run_once_install-mise-tools.sh` runs, the script exits cleanly. Re-running `chezmoi apply` after the brew bundle finishes will trigger it again. -5. **Settings** (`settings/`): - - Platform-specific configurations (macOS, VSCode, Xcode) - - Each has its own `install.sh` script +All run scripts honor `CI=1` and exit early in CI to avoid expensive operations. ## Development Stack -The repository configures a comprehensive development environment for: -- **iOS Development**: Xcode tools, XcodeGen, Mint -- **Flutter Development**: Dart, Flutter toolchain, iOS deployment tools -- **Web Development**: Node.js (via n), various JS tools -- **General Development**: Git, GitHub CLI, tmux, neovim, starship prompt -- **Language Support**: Go, Dart, Ruby (via mise), Rust +- **iOS Development**: Xcode, XcodeGen, xcbeautify (Homebrew) +- **Flutter / Rust / Node / Ruby**: managed by mise (`dot_config/mise/config.toml`) +- **Web Development**: Node.js (via mise), npm/yarn ecosystem +- **General**: Git, GitHub CLI, tmux, Neovim, Starship prompt ## Key Design Principles -1. **Modularity**: Configurations are split into logical components -2. **Idempotency**: Scripts can be run multiple times safely -3. **Automation**: Single `make` command sets up entire environment -4. **Version Management**: Uses mise for language version management -5. **Tool Management**: Homebrew as primary package manager with Brewfile for reproducibility \ No newline at end of file +1. **Single source of truth**: chezmoi manages all dotfiles; mise manages all language runtimes. +2. **macOS-only**: no OS branching. `defaults write` and other macOS-specific commands run unconditionally. +3. **Idempotency**: `run_once_*` scripts gate themselves on existence checks; `run_onchange_*` scripts re-run only when their content (or referenced files) change. +4. **Hand-off to upstream tools**: chezmoi delegates package management to Homebrew (`brew bundle`) and mise (`mise install`) rather than reimplementing version logic. diff --git a/Makefile b/Makefile deleted file mode 100644 index 7503978..0000000 --- a/Makefile +++ /dev/null @@ -1,48 +0,0 @@ -DOTPATH := $(realpath $(dir $(lastword $(MAKEFILE_LIST)))) -CANDIDATES := $(wildcard .??*) -EXCLUSIONS := .DS_Store .git .config .ruby-version .github -DOTFILES := $(filter-out $(EXCLUSIONS), $(CANDIDATES)) -DEPS_INSTALLERS := $(wildcard installers/??*) -SETTINGS_INSTALLERS := $(wildcard settings/**/install.sh) - -# 進捗表示用の変数 -STEP := 0 -TOTAL_STEPS := 4 - -define print_step - @echo "\n=============================================" - @echo "Step $(STEP)/$(TOTAL_STEPS): $1" - @echo "=============================================\n" - @$(eval STEP := $(shell echo $$(($(STEP) + 1)))) -endef - -all: install deps - @echo "\n✨ All tasks completed successfully!\n" - -list: - @$(foreach val, $(DOTFILES), /bin/ls -dF $(val);) - -install: - $(call print_step,Installing dotfiles) - @echo 'Linking dotfiles to home directory...' - @$(foreach val, $(DOTFILES), echo " Linking $(val)..." && ln -sfnv $(abspath $(val)) $(HOME)/$(val);) - @echo 'Creating $(HOME)/.config and copying settings...' - @mkdir -p $(HOME)/.config && cp -r .config/* $(HOME)/.config - @echo 'Installing settings...' - $(foreach val, $(SETTINGS_INSTALLERS), echo " Installing $(val)..." && /bin/zsh $(val);) - -deps: - $(call print_step,Installing dependencies) - @echo 'Running dependency installers...' - $(foreach val, $(DEPS_INSTALLERS), echo " Running $(val)..." && /bin/zsh $(val);) - -test: - @echo 'Running tests with Bats...' - @if command -v bats >/dev/null 2>&1; then \ - bats tests/*.bats; \ - else \ - echo "Bats is not installed. Install with: brew install bats-core"; \ - exit 1; \ - fi - -.PHONY: all list install deps test diff --git a/README.md b/README.md index e28e7ee..1509ad6 100644 --- a/README.md +++ b/README.md @@ -1,30 +1,29 @@ # dotfiles -My personal dotfiles for macOS development environment setup. This repository contains configurations for various development tools and automated installation scripts. +My personal dotfiles for macOS development environment, managed by [chezmoi](https://www.chezmoi.io/). ## 🚀 Quick Start ```bash -# Clone the repository -git clone https://github.com/ry-itto/dotfiles.git ~/ghq/github.com/ry-itto/dotfiles -cd ~/ghq/github.com/ry-itto/dotfiles +# Install chezmoi if you don't have it +brew install chezmoi -# Install everything (dotfiles + dependencies) -make all +# Initialize and apply this repository +chezmoi init --apply ry-itto/dotfiles ``` ## 📋 Requirements -- macOS (tested on macOS 14+) +- macOS (this configuration is macOS-only) - Command Line Tools for Xcode - Internet connection for downloading packages ## 📦 Package Configuration -> **Tested on**: macOS 15.5 (arm64) - Last updated: 2025-08-20 08:41 UTC +> **Tested on**: macOS 26.2 (arm64) - Last updated: 2026-04-28 06:48 UTC -The following packages are defined in `.Brewfile` for installation: +The following packages are defined in `dot_Brewfile` (rendered to `~/.Brewfile`) for installation:
🛠️ Homebrew Formulae (30 packages) @@ -107,162 +106,125 @@ The following packages are defined in `.Brewfile` for installation: ## 🛠 Installation -### Full Installation (Recommended) - -Installs all dotfiles and dependencies: - ```bash -make all +brew install chezmoi +chezmoi init --apply ry-itto/dotfiles ``` -### Partial Installation - -Install only dotfiles (symlinks and configs): +`chezmoi init --apply` will: -```bash -make install -``` +1. Clone this repository into `~/.local/share/chezmoi` +2. Render dotfiles into `$HOME` (e.g. `dot_zshrc` → `~/.zshrc`) +3. Run `run_onchange_install-brew-packages.sh` to install Homebrew bundle from `~/.Brewfile` +4. Run `run_onchange_configure-macos-defaults.sh` and `run_onchange_configure-xcode.sh` to apply system defaults +5. Run `run_once_install-zplug.sh`, `run_once_install-dein.sh` to bootstrap shell/editor plugin managers +6. Run `run_once_install-mise-tools.sh` to install language runtimes (flutter, rust, node, ruby) defined in `dot_config/mise/config.toml` -Install only dependencies (Homebrew, tools, etc.): +## 🔄 Daily Operations ```bash -make deps -``` +# Pull latest changes from this repo and re-apply +chezmoi update -### Manual Installation +# Edit a managed file (opens source file in $EDITOR) +chezmoi edit ~/.zshrc -You can also run individual installer scripts as needed: +# See what would change before applying +chezmoi diff -```bash -# Install Homebrew and packages -/bin/zsh installers/brew.sh - -# Install development tools -/bin/zsh installers/mise.sh # Version management -/bin/zsh installers/flutter.sh # Flutter SDK -/bin/zsh installers/rust.sh # Rust toolchain -/bin/zsh installers/vim.sh # Vim plugins -/bin/zsh installers/xcode.sh # Xcode tools -/bin/zsh installers/zplug.sh # Zsh plugin manager +# Add a new file from $HOME into management +chezmoi add ~/.somefile ``` +> **Note:** After migrating to chezmoi, editing files in `$HOME` directly does **not** sync back to this repository. Use `chezmoi edit` or edit the source file under `~/.local/share/chezmoi`, then `chezmoi apply`. + ## 📂 Directory Structure ``` . -├── .config/ # Application configs (copied to ~/.config/) -│ ├── hammerspoon/ # Hammerspoon automation -│ ├── karabiner/ # Karabiner-Elements key mappings -│ ├── raycast/ # Raycast shortcuts -│ ├── starship.toml # Starship prompt config -│ └── wezterm/ # WezTerm terminal config -├── .zsh/ # Modular Zsh configuration -│ ├── alias.zsh # Command aliases -│ ├── env.zsh # Environment variables -│ ├── plugin.zsh # Zsh plugins -│ └── style.zsh # Shell appearance -├── installers/ # Installation scripts -├── scripts/ # Utility scripts -│ ├── collect_environment.sh # Collect system info -│ └── update_readme.py # Update README with env info -├── settings/ # Platform-specific settings -│ ├── macos/ # macOS system preferences -│ ├── vscode/ # VSCode settings & extensions -│ └── xcode/ # Xcode themes & templates -├── .Brewfile # Homebrew bundle definition -├── .commit_template # Git commit template -├── .gitconfig # Git configuration -├── .tmux.conf # Tmux configuration -├── .zshrc # Main shell configuration -├── CLAUDE.md # AI assistant instructions -├── README.md # This file (auto-generated from template) -├── README.template.md # Template for README generation -└── Makefile # Installation orchestrator +├── dot_zshrc # → ~/.zshrc +├── dot_zsh/ # → ~/.zsh/ +│ ├── alias.zsh +│ ├── env.zsh +│ ├── plugin.zsh +│ ├── style.zsh +│ ├── functions/ +│ └── bin/executable_reload # → ~/.zsh/bin/reload (chmod +x) +├── dot_tmux.conf +├── dot_gitconfig +├── dot_Brewfile +├── dot_commit_template +├── dot_vim/ +├── dot_wezterm.lua +├── dot_hammerspoon/ +├── dot_claude/ # → ~/.claude/ +├── dot_config/ +│ ├── nvim/ +│ ├── starship.toml +│ └── mise/config.toml # mise tool definitions +├── private_Library/ +│ └── private_Application Support/Code/User/settings.json # → VSCode settings +├── run_onchange_install-brew-packages.sh.tmpl +├── run_onchange_configure-macos-defaults.sh +├── run_onchange_configure-xcode.sh +├── run_once_install-zplug.sh +├── run_once_install-dein.sh +├── run_once_install-mise-tools.sh +├── .chezmoiignore # files to skip during apply +├── scripts/ # README generator (CI only) +└── .github/workflows/ci.yml ``` ## 🎯 What's Included ### Development Tools -- **Package Managers**: Homebrew, mise (for version management) +- **Package Managers**: Homebrew, mise - **Shell**: Zsh with zplug, Starship prompt - **Terminal**: WezTerm, tmux - **Editors**: Neovim, VSCode -- **Version Control**: Git, GitHub CLI, Lazygit +- **Version Control**: Git, GitHub CLI + +### Language Runtimes (managed by mise) -### Development Stacks +Defined in `dot_config/mise/config.toml`: -- **iOS Development**: Xcode, XcodeGen, Mint, SwiftLint, SwiftFormat -- **Flutter Development**: Flutter SDK, Dart, FVM -- **Web Development**: Node.js (via n), npm packages -- **General**: Go, Rust, Ruby +- Flutter +- Rust +- Node.js +- Ruby -### macOS Applications +### Other Stacks -- **Productivity**: Raycast, Hammerspoon, Karabiner-Elements -- **Development**: Docker, Orbstack, TablePlus, Fork -- **Communication**: Slack, Discord, Zoom -- **Utilities**: 1Password, AppCleaner, The Unarchiver +- **iOS Development**: Xcode, XcodeGen, xcbeautify +- **macOS Apps**: Raycast, Hammerspoon, Rectangle, Clipy ## ⚙️ Configuration ### Zsh -The shell configuration is modular and organized in `.zsh/`: +Modular configuration in `dot_zsh/`: - `alias.zsh`: Custom command aliases - `env.zsh`: Environment variables and PATH setup -- `plugin.zsh`: Zsh plugin configuration +- `plugin.zsh`: Zsh plugin configuration via zplug - `style.zsh`: Prompt and appearance settings ### Git -Custom Git configuration includes: -- Commit template for consistent commit messages -- Useful aliases and shortcuts -- GitHub CLI integration - -### Tmux - -Pre-configured with: -- Custom key bindings -- Status bar configuration -- Plugin management via TPM +`dot_gitconfig` provides commit template, GitHub CLI helpers, and standard pull/credential settings. -### Vim/Neovim +### Tmux / Vim -Vim configuration includes: - -#### Coc Extensions - -Install extensions using: - -```vim -:CocInstall {extension-name} -``` - -Included extensions: -- coc-flutter - Flutter/Dart language support +Pre-configured tmux key bindings and Vim setup with dein.vim plugin manager. ## 🔧 Customization 1. **Fork this repository** to create your own version -2. **Edit configuration files** to match your preferences: - - Modify `.Brewfile` to add/remove packages - - Update `.zsh/alias.zsh` for custom aliases - - Adjust `.gitconfig` with your user information -3. **Add your own dotfiles** - they'll be automatically symlinked -4. **Customize installers** in the `installers/` directory - -## 📝 Make Commands - -```bash -make all # Install everything -make install # Install dotfiles only -make deps # Install dependencies only -make list # List all dotfiles to be installed -make help # Show available commands -``` +2. **Edit configurations** under `~/.local/share/chezmoi/` (or via `chezmoi edit`) +3. **Apply changes** with `chezmoi apply` +4. **Adjust runtime versions** in `dot_config/mise/config.toml` +5. **Modify packages** in `dot_Brewfile` ## 🤝 Contributing @@ -271,7 +233,3 @@ Feel free to open issues or submit pull requests if you have suggestions for imp ## 📄 License This repository is available under the MIT License. Feel free to fork and modify for your own use. - -## 🙏 Acknowledgments - -Inspired by the dotfiles community and various developers who share their configurations publicly. \ No newline at end of file diff --git a/README.template.md b/README.template.md index c86d32c..4ce791f 100644 --- a/README.template.md +++ b/README.template.md @@ -1,21 +1,20 @@ # dotfiles -My personal dotfiles for macOS development environment setup. This repository contains configurations for various development tools and automated installation scripts. +My personal dotfiles for macOS development environment, managed by [chezmoi](https://www.chezmoi.io/). ## 🚀 Quick Start ```bash -# Clone the repository -git clone https://github.com/ry-itto/dotfiles.git ~/ghq/github.com/ry-itto/dotfiles -cd ~/ghq/github.com/ry-itto/dotfiles +# Install chezmoi if you don't have it +brew install chezmoi -# Install everything (dotfiles + dependencies) -make all +# Initialize and apply this repository +chezmoi init --apply ry-itto/dotfiles ``` ## 📋 Requirements -- macOS (tested on macOS 14+) +- macOS (this configuration is macOS-only) - Command Line Tools for Xcode - Internet connection for downloading packages @@ -24,7 +23,7 @@ make all > **Tested on**: {{OS_NAME}} {{OS_VERSION}} ({{ARCH}}) - Last updated: {{UPDATED_AT}} -The following packages are defined in `.Brewfile` for installation: +The following packages are defined in `dot_Brewfile` (rendered to `~/.Brewfile`) for installation:
🛠️ Homebrew Formulae ({{FORMULAE_COUNT}} packages) @@ -43,162 +42,125 @@ The following packages are defined in `.Brewfile` for installation: ## 🛠 Installation -### Full Installation (Recommended) - -Installs all dotfiles and dependencies: - ```bash -make all +brew install chezmoi +chezmoi init --apply ry-itto/dotfiles ``` -### Partial Installation - -Install only dotfiles (symlinks and configs): +`chezmoi init --apply` will: -```bash -make install -``` +1. Clone this repository into `~/.local/share/chezmoi` +2. Render dotfiles into `$HOME` (e.g. `dot_zshrc` → `~/.zshrc`) +3. Run `run_onchange_install-brew-packages.sh` to install Homebrew bundle from `~/.Brewfile` +4. Run `run_onchange_configure-macos-defaults.sh` and `run_onchange_configure-xcode.sh` to apply system defaults +5. Run `run_once_install-zplug.sh`, `run_once_install-dein.sh` to bootstrap shell/editor plugin managers +6. Run `run_once_install-mise-tools.sh` to install language runtimes (flutter, rust, node, ruby) defined in `dot_config/mise/config.toml` -Install only dependencies (Homebrew, tools, etc.): +## 🔄 Daily Operations ```bash -make deps -``` +# Pull latest changes from this repo and re-apply +chezmoi update -### Manual Installation +# Edit a managed file (opens source file in $EDITOR) +chezmoi edit ~/.zshrc -You can also run individual installer scripts as needed: +# See what would change before applying +chezmoi diff -```bash -# Install Homebrew and packages -/bin/zsh installers/brew.sh - -# Install development tools -/bin/zsh installers/mise.sh # Version management -/bin/zsh installers/flutter.sh # Flutter SDK -/bin/zsh installers/rust.sh # Rust toolchain -/bin/zsh installers/vim.sh # Vim plugins -/bin/zsh installers/xcode.sh # Xcode tools -/bin/zsh installers/zplug.sh # Zsh plugin manager +# Add a new file from $HOME into management +chezmoi add ~/.somefile ``` +> **Note:** After migrating to chezmoi, editing files in `$HOME` directly does **not** sync back to this repository. Use `chezmoi edit` or edit the source file under `~/.local/share/chezmoi`, then `chezmoi apply`. + ## 📂 Directory Structure ``` . -├── .config/ # Application configs (copied to ~/.config/) -│ ├── hammerspoon/ # Hammerspoon automation -│ ├── karabiner/ # Karabiner-Elements key mappings -│ ├── raycast/ # Raycast shortcuts -│ ├── starship.toml # Starship prompt config -│ └── wezterm/ # WezTerm terminal config -├── .zsh/ # Modular Zsh configuration -│ ├── alias.zsh # Command aliases -│ ├── env.zsh # Environment variables -│ ├── plugin.zsh # Zsh plugins -│ └── style.zsh # Shell appearance -├── installers/ # Installation scripts -├── scripts/ # Utility scripts -│ ├── collect_environment.sh # Collect system info -│ └── update_readme.py # Update README with env info -├── settings/ # Platform-specific settings -│ ├── macos/ # macOS system preferences -│ ├── vscode/ # VSCode settings & extensions -│ └── xcode/ # Xcode themes & templates -├── .Brewfile # Homebrew bundle definition -├── .commit_template # Git commit template -├── .gitconfig # Git configuration -├── .tmux.conf # Tmux configuration -├── .zshrc # Main shell configuration -├── CLAUDE.md # AI assistant instructions -├── README.md # This file (auto-generated from template) -├── README.template.md # Template for README generation -└── Makefile # Installation orchestrator +├── dot_zshrc # → ~/.zshrc +├── dot_zsh/ # → ~/.zsh/ +│ ├── alias.zsh +│ ├── env.zsh +│ ├── plugin.zsh +│ ├── style.zsh +│ ├── functions/ +│ └── bin/executable_reload # → ~/.zsh/bin/reload (chmod +x) +├── dot_tmux.conf +├── dot_gitconfig +├── dot_Brewfile +├── dot_commit_template +├── dot_vim/ +├── dot_wezterm.lua +├── dot_hammerspoon/ +├── dot_claude/ # → ~/.claude/ +├── dot_config/ +│ ├── nvim/ +│ ├── starship.toml +│ └── mise/config.toml # mise tool definitions +├── private_Library/ +│ └── private_Application Support/Code/User/settings.json # → VSCode settings +├── run_onchange_install-brew-packages.sh.tmpl +├── run_onchange_configure-macos-defaults.sh +├── run_onchange_configure-xcode.sh +├── run_once_install-zplug.sh +├── run_once_install-dein.sh +├── run_once_install-mise-tools.sh +├── .chezmoiignore # files to skip during apply +├── scripts/ # README generator (CI only) +└── .github/workflows/ci.yml ``` ## 🎯 What's Included ### Development Tools -- **Package Managers**: Homebrew, mise (for version management) +- **Package Managers**: Homebrew, mise - **Shell**: Zsh with zplug, Starship prompt - **Terminal**: WezTerm, tmux - **Editors**: Neovim, VSCode -- **Version Control**: Git, GitHub CLI, Lazygit +- **Version Control**: Git, GitHub CLI + +### Language Runtimes (managed by mise) -### Development Stacks +Defined in `dot_config/mise/config.toml`: -- **iOS Development**: Xcode, XcodeGen, Mint, SwiftLint, SwiftFormat -- **Flutter Development**: Flutter SDK, Dart, FVM -- **Web Development**: Node.js (via n), npm packages -- **General**: Go, Rust, Ruby +- Flutter +- Rust +- Node.js +- Ruby -### macOS Applications +### Other Stacks -- **Productivity**: Raycast, Hammerspoon, Karabiner-Elements -- **Development**: Docker, Orbstack, TablePlus, Fork -- **Communication**: Slack, Discord, Zoom -- **Utilities**: 1Password, AppCleaner, The Unarchiver +- **iOS Development**: Xcode, XcodeGen, xcbeautify +- **macOS Apps**: Raycast, Hammerspoon, Rectangle, Clipy ## ⚙️ Configuration ### Zsh -The shell configuration is modular and organized in `.zsh/`: +Modular configuration in `dot_zsh/`: - `alias.zsh`: Custom command aliases - `env.zsh`: Environment variables and PATH setup -- `plugin.zsh`: Zsh plugin configuration +- `plugin.zsh`: Zsh plugin configuration via zplug - `style.zsh`: Prompt and appearance settings ### Git -Custom Git configuration includes: -- Commit template for consistent commit messages -- Useful aliases and shortcuts -- GitHub CLI integration - -### Tmux - -Pre-configured with: -- Custom key bindings -- Status bar configuration -- Plugin management via TPM +`dot_gitconfig` provides commit template, GitHub CLI helpers, and standard pull/credential settings. -### Vim/Neovim +### Tmux / Vim -Vim configuration includes: - -#### Coc Extensions - -Install extensions using: - -```vim -:CocInstall {extension-name} -``` - -Included extensions: -- coc-flutter - Flutter/Dart language support +Pre-configured tmux key bindings and Vim setup with dein.vim plugin manager. ## 🔧 Customization 1. **Fork this repository** to create your own version -2. **Edit configuration files** to match your preferences: - - Modify `.Brewfile` to add/remove packages - - Update `.zsh/alias.zsh` for custom aliases - - Adjust `.gitconfig` with your user information -3. **Add your own dotfiles** - they'll be automatically symlinked -4. **Customize installers** in the `installers/` directory - -## 📝 Make Commands - -```bash -make all # Install everything -make install # Install dotfiles only -make deps # Install dependencies only -make list # List all dotfiles to be installed -make help # Show available commands -``` +2. **Edit configurations** under `~/.local/share/chezmoi/` (or via `chezmoi edit`) +3. **Apply changes** with `chezmoi apply` +4. **Adjust runtime versions** in `dot_config/mise/config.toml` +5. **Modify packages** in `dot_Brewfile` ## 🤝 Contributing @@ -207,7 +169,3 @@ Feel free to open issues or submit pull requests if you have suggestions for imp ## 📄 License This repository is available under the MIT License. Feel free to fork and modify for your own use. - -## 🙏 Acknowledgments - -Inspired by the dotfiles community and various developers who share their configurations publicly. \ No newline at end of file diff --git a/asdf-dart.huC7pJ/sdk.zip b/asdf-dart.huC7pJ/sdk.zip deleted file mode 100644 index 33b24da..0000000 --- a/asdf-dart.huC7pJ/sdk.zip +++ /dev/null @@ -1 +0,0 @@ -NoSuchKeyThe specified key does not exist.
No such object: dart-archive/channels/stable/release/stable/sdk/dartsdk-macos-x64-release.zip
\ No newline at end of file diff --git a/.Brewfile b/dot_Brewfile similarity index 100% rename from .Brewfile rename to dot_Brewfile diff --git a/.claude/agents/serena-expert.md b/dot_claude/agents/serena-expert.md similarity index 100% rename from .claude/agents/serena-expert.md rename to dot_claude/agents/serena-expert.md diff --git a/.claude/commands/serena.md b/dot_claude/commands/serena.md similarity index 100% rename from .claude/commands/serena.md rename to dot_claude/commands/serena.md diff --git a/.claude/settings.json b/dot_claude/settings.json similarity index 100% rename from .claude/settings.json rename to dot_claude/settings.json diff --git a/.commit_template b/dot_commit_template similarity index 100% rename from .commit_template rename to dot_commit_template diff --git a/dot_config/mise/config.toml b/dot_config/mise/config.toml new file mode 100644 index 0000000..d482604 --- /dev/null +++ b/dot_config/mise/config.toml @@ -0,0 +1,5 @@ +[tools] +flutter = "2.8.1" +rust = "stable" +node = "lts" +ruby = "3.3" diff --git a/.config/nvim/autoload/plugins/nvim_lsp.vim b/dot_config/nvim/autoload/plugins/nvim_lsp.vim similarity index 100% rename from .config/nvim/autoload/plugins/nvim_lsp.vim rename to dot_config/nvim/autoload/plugins/nvim_lsp.vim diff --git a/.config/nvim/init.vim b/dot_config/nvim/init.vim similarity index 100% rename from .config/nvim/init.vim rename to dot_config/nvim/init.vim diff --git a/.config/starship.toml b/dot_config/starship.toml similarity index 100% rename from .config/starship.toml rename to dot_config/starship.toml diff --git a/.gitconfig b/dot_gitconfig similarity index 100% rename from .gitconfig rename to dot_gitconfig diff --git a/.hammerspoon/init.lua b/dot_hammerspoon/init.lua similarity index 100% rename from .hammerspoon/init.lua rename to dot_hammerspoon/init.lua diff --git a/.tmux.conf b/dot_tmux.conf similarity index 100% rename from .tmux.conf rename to dot_tmux.conf diff --git a/.vim/README.md b/dot_vim/README.md similarity index 100% rename from .vim/README.md rename to dot_vim/README.md diff --git a/.vim/ftdetect/cocoapods.vim b/dot_vim/ftdetect/cocoapods.vim similarity index 100% rename from .vim/ftdetect/cocoapods.vim rename to dot_vim/ftdetect/cocoapods.vim diff --git a/.vim/ftdetect/fastlane.vim b/dot_vim/ftdetect/fastlane.vim similarity index 100% rename from .vim/ftdetect/fastlane.vim rename to dot_vim/ftdetect/fastlane.vim diff --git a/.vim/ftplugin/dart.vim b/dot_vim/ftplugin/dart.vim similarity index 100% rename from .vim/ftplugin/dart.vim rename to dot_vim/ftplugin/dart.vim diff --git a/.vim/ftplugin/ruby.vim b/dot_vim/ftplugin/ruby.vim similarity index 100% rename from .vim/ftplugin/ruby.vim rename to dot_vim/ftplugin/ruby.vim diff --git a/.vim/ftplugin/yaml.vim b/dot_vim/ftplugin/yaml.vim similarity index 100% rename from .vim/ftplugin/yaml.vim rename to dot_vim/ftplugin/yaml.vim diff --git a/.vim/init/bindings.vim b/dot_vim/init/bindings.vim similarity index 100% rename from .vim/init/bindings.vim rename to dot_vim/init/bindings.vim diff --git a/.vim/init/setting.vim b/dot_vim/init/setting.vim similarity index 100% rename from .vim/init/setting.vim rename to dot_vim/init/setting.vim diff --git a/.vim/rc/dein.toml b/dot_vim/rc/dein.toml similarity index 100% rename from .vim/rc/dein.toml rename to dot_vim/rc/dein.toml diff --git a/.vim/rc/dein_lazy.toml b/dot_vim/rc/dein_lazy.toml similarity index 100% rename from .vim/rc/dein_lazy.toml rename to dot_vim/rc/dein_lazy.toml diff --git a/.wezterm.lua b/dot_wezterm.lua similarity index 100% rename from .wezterm.lua rename to dot_wezterm.lua diff --git a/.zsh/alias.zsh b/dot_zsh/alias.zsh similarity index 100% rename from .zsh/alias.zsh rename to dot_zsh/alias.zsh diff --git a/.zsh/bin/reload b/dot_zsh/bin/executable_reload similarity index 100% rename from .zsh/bin/reload rename to dot_zsh/bin/executable_reload diff --git a/.zsh/env.zsh b/dot_zsh/env.zsh similarity index 100% rename from .zsh/env.zsh rename to dot_zsh/env.zsh diff --git a/.zsh/functions/functions.zsh b/dot_zsh/functions/functions.zsh similarity index 100% rename from .zsh/functions/functions.zsh rename to dot_zsh/functions/functions.zsh diff --git a/.zsh/functions/fzf-git.sh b/dot_zsh/functions/fzf-git.sh similarity index 100% rename from .zsh/functions/fzf-git.sh rename to dot_zsh/functions/fzf-git.sh diff --git a/.zsh/functions/ghq.zsh b/dot_zsh/functions/ghq.zsh similarity index 100% rename from .zsh/functions/ghq.zsh rename to dot_zsh/functions/ghq.zsh diff --git a/.zsh/functions/git.zsh b/dot_zsh/functions/git.zsh similarity index 100% rename from .zsh/functions/git.zsh rename to dot_zsh/functions/git.zsh diff --git a/.zsh/functions/github.zsh b/dot_zsh/functions/github.zsh similarity index 100% rename from .zsh/functions/github.zsh rename to dot_zsh/functions/github.zsh diff --git a/.zsh/plugin.zsh b/dot_zsh/plugin.zsh similarity index 100% rename from .zsh/plugin.zsh rename to dot_zsh/plugin.zsh diff --git a/.zsh/style.zsh b/dot_zsh/style.zsh similarity index 100% rename from .zsh/style.zsh rename to dot_zsh/style.zsh diff --git a/.zshrc b/dot_zshrc similarity index 100% rename from .zshrc rename to dot_zshrc diff --git a/installers/flutter.sh b/installers/flutter.sh deleted file mode 100755 index 316f4db..0000000 --- a/installers/flutter.sh +++ /dev/null @@ -1,9 +0,0 @@ -# fvm -if ! type "fvm" > /dev/null; then - dart pub global activate fvm -fi - -if ! type "flutter" > /dev/null; then - fvm install 2.8.1 - fvm global 2.8.1 -fi diff --git a/installers/rust.sh b/installers/rust.sh deleted file mode 100755 index 64a1478..0000000 --- a/installers/rust.sh +++ /dev/null @@ -1,6 +0,0 @@ -if ! type "rustup" > /dev/null; then - # Install rustup - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --no-modify-path -fi - - diff --git a/installers/vim.sh b/installers/vim.sh deleted file mode 100755 index 9ad9607..0000000 --- a/installers/vim.sh +++ /dev/null @@ -1,11 +0,0 @@ -# Install dein -INSTALLATION_DIR=$HOME/.cache/dein - -tmp_dir=$(mktemp -d) - -curl https://raw.githubusercontent.com/Shougo/dein.vim/master/bin/installer.sh > $tmp_dir/installer.sh -chmod u+x $tmp_dir/installer.sh - -$tmp_dir/installer.sh $INSTALLATION_DIR - -trap 'rm -rf "$tmp_dir"' EXIT diff --git a/installers/xcode.sh b/installers/xcode.sh deleted file mode 100755 index 6939170..0000000 --- a/installers/xcode.sh +++ /dev/null @@ -1,15 +0,0 @@ -if ! type "xcodebuild" > /dev/null ; then - xcodes install --latest -fi - -SCRIPT_DIR=$(cd $(dirname $0); pwd) - -# Xcode 上でビルド時間を表示する -defaults write com.apple.dt.Xcode ShowBuildOperationDuration YES - -# コア数を取得 -cores=`system_profiler SPHardwareDataType | grep -o 'Cores:\s\d' | sed -e 's/[^0-9]//g'` -# アプリをビルドする時に並列でビルドする -defaults write com.apple.dt.Xcode IDEBuildOperationMaxNumberOfConcurrentCompileTasks $cores -# Including whitespace-only lines 空白しかない行の空白を削除 -defaults write com.apple.dt.Xcode DVTTextEditorTrimWhitespaceOnlyLines -bool true diff --git a/installers/zplug.sh b/installers/zplug.sh deleted file mode 100755 index 3918fa4..0000000 --- a/installers/zplug.sh +++ /dev/null @@ -1,4 +0,0 @@ -if [ ! -d $ZPLUG_HOME ]; then - curl -sL --proto-redir -all,https https://raw.githubusercontent.com/zplug/installer/master/installer.zsh | zsh -fi - diff --git a/settings/vscode/settings.json b/private_Library/private_Application Support/Code/User/settings.json similarity index 100% rename from settings/vscode/settings.json rename to private_Library/private_Application Support/Code/User/settings.json diff --git a/run_once_install-dein.sh b/run_once_install-dein.sh new file mode 100755 index 0000000..8054b53 --- /dev/null +++ b/run_once_install-dein.sh @@ -0,0 +1,18 @@ +#!/bin/zsh +set -eu + +[[ -n "${CI:-}" ]] && exit 0 + +INSTALLATION_DIR="$HOME/.cache/dein" + +if [ -d "$INSTALLATION_DIR" ]; then + exit 0 +fi + +tmp_dir=$(mktemp -d) +trap 'rm -rf "$tmp_dir"' EXIT + +curl -fsSL https://raw.githubusercontent.com/Shougo/dein.vim/master/bin/installer.sh > "$tmp_dir/installer.sh" +chmod u+x "$tmp_dir/installer.sh" + +"$tmp_dir/installer.sh" "$INSTALLATION_DIR" diff --git a/run_once_install-mise-tools.sh b/run_once_install-mise-tools.sh new file mode 100755 index 0000000..97dbbf8 --- /dev/null +++ b/run_once_install-mise-tools.sh @@ -0,0 +1,11 @@ +#!/bin/zsh +set -eu + +[[ -n "${CI:-}" ]] && exit 0 + +if ! command -v mise >/dev/null 2>&1; then + echo 'mise is not installed yet. Skipping tool install. Run `chezmoi apply` again after `brew bundle --global` finishes.' + exit 0 +fi + +mise install diff --git a/run_once_install-zplug.sh b/run_once_install-zplug.sh new file mode 100755 index 0000000..bbdafac --- /dev/null +++ b/run_once_install-zplug.sh @@ -0,0 +1,8 @@ +#!/bin/zsh +set -eu + +[[ -n "${CI:-}" ]] && exit 0 + +if [ ! -d "${ZPLUG_HOME:-$HOME/.zplug}" ]; then + curl -sL --proto-redir -all,https https://raw.githubusercontent.com/zplug/installer/master/installer.zsh | zsh +fi diff --git a/settings/macos/install.sh b/run_onchange_configure-macos-defaults.sh similarity index 64% rename from settings/macos/install.sh rename to run_onchange_configure-macos-defaults.sh index 462d99c..3d75051 100755 --- a/settings/macos/install.sh +++ b/run_onchange_configure-macos-defaults.sh @@ -1,18 +1,23 @@ +#!/bin/zsh +set -eu + +[[ -n "${CI:-}" ]] && exit 0 + # NSGlobalDomain -# 全ての拡張子のファイルを表示 +# Show all file extensions defaults write NSGlobalDomain AppleShowAllExtensions -bool true -# キーのリピート速度 +# Key repeat speed defaults write NSGlobalDomain KeyRepeat -int 2 -# キーのリピートまでの速度 +# Initial key repeat delay defaults write NSGlobalDomain InitialKeyRepeat -int 25 -# Finderで隠しファイルを表示 +# Show hidden files in Finder defaults write com.apple.finder AppleShowAllFiles TRUE -# キーの押し込み時連続入力をさせる +# Disable press-and-hold for keys (allows key repeat) defaults write -g ApplePressAndHoldEnabled -bool false -# Caps LockキーをControlキーとして使用 +# Map Caps Lock to Control defaults write com.apple.keyboard.modifiermapping.1452-640-0 -array-add '{ "HIDKeyboardModifierMappingSrc" = 2; "HIDKeyboardModifierMappingDst" = 4; }' diff --git a/run_onchange_configure-xcode.sh b/run_onchange_configure-xcode.sh new file mode 100755 index 0000000..3ed6f4d --- /dev/null +++ b/run_onchange_configure-xcode.sh @@ -0,0 +1,18 @@ +#!/bin/zsh +set -eu + +[[ -n "${CI:-}" ]] && exit 0 + +if ! type "xcodebuild" > /dev/null; then + xcodes install --latest +fi + +# Show build duration in Xcode +defaults write com.apple.dt.Xcode ShowBuildOperationDuration YES + +# Use all available cores for parallel builds +cores=$(sysctl -n hw.ncpu) +defaults write com.apple.dt.Xcode IDEBuildOperationMaxNumberOfConcurrentCompileTasks "$cores" + +# Trim whitespace-only lines +defaults write com.apple.dt.Xcode DVTTextEditorTrimWhitespaceOnlyLines -bool true diff --git a/installers/brew.sh b/run_onchange_install-brew-packages.sh.tmpl similarity index 57% rename from installers/brew.sh rename to run_onchange_install-brew-packages.sh.tmpl index 0cf80f9..8c1fbf1 100755 --- a/installers/brew.sh +++ b/run_onchange_install-brew-packages.sh.tmpl @@ -1,12 +1,18 @@ +#!/bin/zsh +set -eu + +[[ -n "${CI:-}" ]] && exit 0 + if ! type "brew" > /dev/null; then echo '`brew` not found. Install Homebrew' /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" fi -brew bundle check --global -if [ $? -ne 0 ]; then +if brew bundle check --global; then + echo '`brew` dependencies are satisfied' +else echo 'Install `brew` dependencies...' brew bundle --global -v -else - echo '`brew` dependencies are satisfied :smile:' | emojify fi + +# brewfile hash: {{ include "dot_Brewfile" | sha256sum }} diff --git a/scripts/parse_brewfile.py b/scripts/parse_brewfile.py index 897ef04..777eab7 100755 --- a/scripts/parse_brewfile.py +++ b/scripts/parse_brewfile.py @@ -6,7 +6,7 @@ def parse_brewfile(): """Parse .Brewfile and extract package information with categories""" - brewfile_path = Path(__file__).parent.parent / ".Brewfile" + brewfile_path = Path(__file__).parent.parent / "dot_Brewfile" if not brewfile_path.exists(): return {"formulae": {}, "casks": {}} diff --git a/settings/vscode/install-extensions.sh b/settings/vscode/install-extensions.sh deleted file mode 100755 index 7acb978..0000000 --- a/settings/vscode/install-extensions.sh +++ /dev/null @@ -1,28 +0,0 @@ -if ! type 'code' > /dev/null; then - echo 'Please install vscode and activate `code` command.' - exit 1 -fi - -pkglist=( -bungcip.better-toml -CoenraadS.bracket-pair-colorizer -daylerees.rainglow -dbaeumer.vscode-eslint -eamodio.gitlens -elmTooling.elm-ls-vscode -esbenp.prettier-vscode -MS-CEINTL.vscode-language-pack-ja -ms-python.python -rust-lang.rust -shd101wyy.markdown-preview-enhanced -streetsidesoftware.code-spell-checker -toba.vsfire -VisualStudioExptTeam.vscodeintellicode -vscode-icons-team.vscode-icons -vscodevim.vim -yzane.markdown-pdf -) - -for i in ${pkglist[@]}; do - code --install-extension $i -done diff --git a/settings/vscode/install.sh b/settings/vscode/install.sh deleted file mode 100755 index 5a8472e..0000000 --- a/settings/vscode/install.sh +++ /dev/null @@ -1,11 +0,0 @@ -SCRIPT_DIR=$(cd $(dirname $0) && pwd) -VSCODE_DOT_DIRECTORY=$HOME/.vscode -VSCODE_SETTING_DIR=$HOME/Library/Application\ Support/Code/User -VSCODE_SETTING_FILE=settings.json - -ln -s "$SCRIPT_DIR/$VSCODE_SETTING_FILE" "$VSCODE_DOT_DIRECTORY/$VSCODE_SETTING_FILE" - -rm "$VSCODE_SETTING_DIR/$VSCODE_SETTING_FILE" -ln -s "$VSCODE_DOT_DIRECTORY/$VSCODE_SETTING_FILE" "$VSCODE_SETTING_DIR/$VSCODE_SETTING_FILE" - -$SCRIPT_DIR/install-extensions.sh diff --git a/settings/xcode/install.sh b/settings/xcode/install.sh deleted file mode 100644 index 6939170..0000000 --- a/settings/xcode/install.sh +++ /dev/null @@ -1,15 +0,0 @@ -if ! type "xcodebuild" > /dev/null ; then - xcodes install --latest -fi - -SCRIPT_DIR=$(cd $(dirname $0); pwd) - -# Xcode 上でビルド時間を表示する -defaults write com.apple.dt.Xcode ShowBuildOperationDuration YES - -# コア数を取得 -cores=`system_profiler SPHardwareDataType | grep -o 'Cores:\s\d' | sed -e 's/[^0-9]//g'` -# アプリをビルドする時に並列でビルドする -defaults write com.apple.dt.Xcode IDEBuildOperationMaxNumberOfConcurrentCompileTasks $cores -# Including whitespace-only lines 空白しかない行の空白を削除 -defaults write com.apple.dt.Xcode DVTTextEditorTrimWhitespaceOnlyLines -bool true diff --git a/tests/configuration.bats b/tests/configuration.bats deleted file mode 100644 index eecedea..0000000 --- a/tests/configuration.bats +++ /dev/null @@ -1,119 +0,0 @@ -#!/usr/bin/env bats - -load test_helper - -@test ".Brewfile exists and is valid" { - assert_file_exists "${REPO_ROOT}/.Brewfile" - - # Check basic Brewfile syntax - # Should contain brew commands - grep -q "^brew " "${REPO_ROOT}/.Brewfile" -} - -@test ".Brewfile contains expected packages" { - local brewfile="${REPO_ROOT}/.Brewfile" - - # Check for some essential packages - grep -q "brew 'zsh'" "${brewfile}" - grep -q "brew 'git'" "${brewfile}" - grep -q "brew 'tmux'" "${brewfile}" -} - -@test ".zshrc exists and sources modular configs" { - assert_file_exists "${REPO_ROOT}/.zshrc" - - # Check that .zshrc sources the modular config files - grep -q "source.*\.zsh/.*\.zsh" "${REPO_ROOT}/.zshrc" || \ - grep -q "\. .*\.zsh/.*\.zsh" "${REPO_ROOT}/.zshrc" || \ - grep -q "for.*\.zsh.*source" "${REPO_ROOT}/.zshrc" -} - -@test "modular zsh configs exist" { - assert_dir_exists "${REPO_ROOT}/.zsh" - - # Check for expected modular config files - local expected_configs=( - "alias.zsh" - "env.zsh" - "style.zsh" - "plugin.zsh" - ) - - for config in "${expected_configs[@]}"; do - if [[ ! -f "${REPO_ROOT}/.zsh/${config}" ]]; then - echo "Warning: Expected config ${config} not found" - # Not a failure, just a warning - fi - done -} - -@test ".gitconfig exists and has valid structure" { - assert_file_exists "${REPO_ROOT}/.gitconfig" - - # Check for basic git config structure - grep -q "\[user\]" "${REPO_ROOT}/.gitconfig" || \ - grep -q "\[core\]" "${REPO_ROOT}/.gitconfig" || \ - grep -q "\[alias\]" "${REPO_ROOT}/.gitconfig" -} - -@test ".tmux.conf exists" { - assert_file_exists "${REPO_ROOT}/.tmux.conf" -} - -@test "commit template exists if referenced" { - if grep -q "template.*=.*\.commit_template" "${REPO_ROOT}/.gitconfig" 2>/dev/null; then - assert_file_exists "${REPO_ROOT}/.commit_template" - fi -} - -@test "zsh configs have valid syntax" { - # Test main .zshrc - run zsh -n "${REPO_ROOT}/.zshrc" - if [ "$status" -ne 0 ]; then - echo "Syntax error in .zshrc: ${output}" - false - fi - - # Test modular configs if they exist - if [[ -d "${REPO_ROOT}/.zsh" ]]; then - for config in "${REPO_ROOT}"/.zsh/*.zsh; do - if [[ -f "${config}" ]]; then - run zsh -n "${config}" - if [ "$status" -ne 0 ]; then - echo "Syntax error in $(basename "${config}"): ${output}" - false - fi - fi - done - fi -} - -@test "no hardcoded absolute paths in configs" { - # Check for common hardcoded paths that should be avoided - local configs=( - "${REPO_ROOT}/.zshrc" - "${REPO_ROOT}/.gitconfig" - "${REPO_ROOT}/.tmux.conf" - ) - - for config in "${configs[@]}"; do - if [[ -f "${config}" ]]; then - # Skip checking for /usr, /bin, /opt as these are system paths - # Check for hardcoded user home paths - if grep -q "/Users/[^/]*/" "${config}" | grep -v "^#"; then - echo "Warning: Possible hardcoded user path in $(basename "${config}")" - # Just a warning, not a failure - fi - fi - done -} - -@test "CLAUDE.md exists and contains setup instructions" { - if [[ -f "${REPO_ROOT}/CLAUDE.md" ]]; then - # Check that CLAUDE.md contains key sections - grep -qi "repository overview\|overview" "${REPO_ROOT}/CLAUDE.md" - grep -qi "command\|setup\|install" "${REPO_ROOT}/CLAUDE.md" - else - echo "Warning: CLAUDE.md not found" - fi -} \ No newline at end of file diff --git a/tests/installers.bats b/tests/installers.bats deleted file mode 100644 index a209548..0000000 --- a/tests/installers.bats +++ /dev/null @@ -1,96 +0,0 @@ -#!/usr/bin/env bats - -load test_helper - -@test "all installer scripts exist" { - local installers=( - "brew.sh" - "flutter.sh" - "rust.sh" - "vim.sh" - "xcode.sh" - "zplug.sh" - ) - - for installer in "${installers[@]}"; do - assert_file_exists "${REPO_ROOT}/installers/${installer}" - done -} - -@test "all installer scripts have valid zsh syntax" { - local installers="${REPO_ROOT}"/installers/*.sh - - for installer in ${installers}; do - run zsh -n "${installer}" - if [ "$status" -ne 0 ]; then - echo "Syntax error in ${installer}: ${output}" - false - fi - done -} - -@test "all installer scripts are executable or run with zsh" { - local installers="${REPO_ROOT}"/installers/*.sh - - for installer in ${installers}; do - # Check if file has shebang - local first_line=$(head -n1 "${installer}") - if [[ "${first_line}" =~ ^#! ]]; then - # If it has shebang, it should be executable - if [[ ! -x "${installer}" ]]; then - echo "Script ${installer} has shebang but is not executable" - # This is just a warning, not a failure - fi - fi - done -} - -@test "brew.sh checks for Homebrew installation" { - local brew_script="${REPO_ROOT}/installers/brew.sh" - - # Check that the script contains Homebrew check - grep -q 'type "brew"' "${brew_script}" || \ - grep -q "which brew" "${brew_script}" || \ - grep -q "command -v brew" "${brew_script}" || \ - grep -q "brew --version" "${brew_script}" -} - -@test "installer scripts use consistent error handling" { - local installers="${REPO_ROOT}"/installers/*.sh - - for installer in ${installers}; do - local basename=$(basename "${installer}") - - # Check for some form of error handling or status checking - if ! grep -q "set -e" "${installer}" && \ - ! grep -q "|| " "${installer}" && \ - ! grep -q "if \[" "${installer}"; then - echo "Warning: ${basename} may lack error handling" - # This is a warning, not a failure - fi - done -} - -@test "settings installer scripts exist" { - assert_file_exists "${REPO_ROOT}/settings/macos/install.sh" - assert_file_exists "${REPO_ROOT}/settings/vscode/install.sh" - assert_file_exists "${REPO_ROOT}/settings/xcode/install.sh" -} - -@test "settings installer scripts have valid syntax" { - local settings_installers=( - "${REPO_ROOT}/settings/macos/install.sh" - "${REPO_ROOT}/settings/vscode/install.sh" - "${REPO_ROOT}/settings/xcode/install.sh" - ) - - for installer in "${settings_installers[@]}"; do - if [[ -f "${installer}" ]]; then - run zsh -n "${installer}" - if [ "$status" -ne 0 ]; then - echo "Syntax error in ${installer}: ${output}" - false - fi - fi - done -} \ No newline at end of file diff --git a/tests/symlinks.bats b/tests/symlinks.bats deleted file mode 100644 index 094262e..0000000 --- a/tests/symlinks.bats +++ /dev/null @@ -1,96 +0,0 @@ -#!/usr/bin/env bats - -load test_helper - -@test "dotfiles list excludes specified directories" { - run make -C "${REPO_ROOT}" list - [ "$status" -eq 0 ] - - # Check that excluded directories are not in the list - ! echo "${output}" | grep -q "\.git/" - ! echo "${output}" | grep -q "\.github/" - ! echo "${output}" | grep -q "\.DS_Store" - ! echo "${output}" | grep -q "\.ruby-version" - ! echo "${output}" | grep -q "\.config/" - # .claude should be included (not excluded) - echo "${output}" | grep -q "\.claude/" -} - -@test "dotfiles list includes expected directories" { - run make -C "${REPO_ROOT}" list - [ "$status" -eq 0 ] - - # Check that expected directories are in the list - echo "${output}" | grep -q "\.zsh/" - echo "${output}" | grep -q "\.zshrc" - echo "${output}" | grep -q "\.tmux.conf" - echo "${output}" | grep -q "\.gitconfig" - echo "${output}" | grep -q "\.Brewfile" -} - -@test "make install creates symlinks in test HOME" { - # Run install with test HOME - run run_make_with_test_home install - [ "$status" -eq 0 ] - - # Check that symlinks are created - assert_link_exists "${TEST_HOME}/.zshrc" - assert_link_exists "${TEST_HOME}/.tmux.conf" - assert_link_exists "${TEST_HOME}/.gitconfig" - assert_link_exists "${TEST_HOME}/.Brewfile" - assert_link_exists "${TEST_HOME}/.zsh" -} - -@test "make install copies .config directory contents" { - # Run install with test HOME - run run_make_with_test_home install - [ "$status" -eq 0 ] - - # Check that .config directory is created and populated - assert_dir_exists "${TEST_HOME}/.config" - - # Check if any config files from repo are copied - if [[ -d "${REPO_ROOT}/.config" ]] && [[ "$(ls -A "${REPO_ROOT}/.config")" ]]; then - # Get list of files/dirs in .config - for item in "${REPO_ROOT}"/.config/*; do - local basename="$(basename "${item}")" - if [[ -f "${item}" ]]; then - assert_file_exists "${TEST_HOME}/.config/${basename}" - elif [[ -d "${item}" ]]; then - assert_dir_exists "${TEST_HOME}/.config/${basename}" - fi - done - fi -} - -@test "symlinks point to correct targets" { - # Run install with test HOME - run run_make_with_test_home install - [ "$status" -eq 0 ] - - # Check that symlinks point to the correct absolute paths - local dotfiles=$(get_dotfiles_list) - for dotfile in ${dotfiles}; do - if [[ -e "${REPO_ROOT}/${dotfile}" ]]; then - local link="${TEST_HOME}/${dotfile}" - if [[ -L "${link}" ]]; then - local target="$(readlink "${link}")" - local expected="${REPO_ROOT}/${dotfile}" - [[ "${target}" == "${expected}" ]] - fi - fi - done -} - -@test "make install is idempotent" { - # Run install twice - run run_make_with_test_home install - [ "$status" -eq 0 ] - - run run_make_with_test_home install - [ "$status" -eq 0 ] - - # Check that symlinks still exist and are correct - assert_link_exists "${TEST_HOME}/.zshrc" - assert_link_exists "${TEST_HOME}/.tmux.conf" -} \ No newline at end of file diff --git a/tests/test_helper.bash b/tests/test_helper.bash deleted file mode 100644 index e70ba2e..0000000 --- a/tests/test_helper.bash +++ /dev/null @@ -1,77 +0,0 @@ -#!/usr/bin/env bash - -export TEST_TEMP_DIR="$(mktemp -d)" -export REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" -export ORIGINAL_HOME="${HOME}" -export TEST_HOME="${TEST_TEMP_DIR}/home" - -setup() { - mkdir -p "${TEST_HOME}" - mkdir -p "${TEST_HOME}/.config" -} - -teardown() { - if [[ -d "${TEST_TEMP_DIR}" ]]; then - rm -rf "${TEST_TEMP_DIR}" - fi -} - -assert_link_exists() { - local link_path="$1" - local target_path="$2" - - if [[ ! -L "${link_path}" ]]; then - echo "Expected symlink at ${link_path} does not exist" - return 1 - fi - - if [[ -n "${target_path}" ]]; then - local actual_target="$(readlink "${link_path}")" - if [[ "${actual_target}" != "${target_path}" ]]; then - echo "Symlink ${link_path} points to ${actual_target}, expected ${target_path}" - return 1 - fi - fi -} - -assert_file_exists() { - local file_path="$1" - - if [[ ! -f "${file_path}" ]]; then - echo "Expected file at ${file_path} does not exist" - return 1 - fi -} - -assert_dir_exists() { - local dir_path="$1" - - if [[ ! -d "${dir_path}" ]]; then - echo "Expected directory at ${dir_path} does not exist" - return 1 - fi -} - -run_make_with_test_home() { - local target="$1" - HOME="${TEST_HOME}" make -C "${REPO_ROOT}" "${target}" -} - -get_dotfiles_list() { - cd "${REPO_ROOT}" || exit 1 - local candidates=$(find . -maxdepth 1 -name ".*" -type f -o -name ".*" -type d | grep -v "^\.$" | sed 's|^\./||') - local exclusions=".DS_Store .git .config .ruby-version .github .claude" - - for candidate in ${candidates}; do - local excluded=false - for exclusion in ${exclusions}; do - if [[ "${candidate}" == "${exclusion}" ]]; then - excluded=true - break - fi - done - if [[ "${excluded}" == "false" ]]; then - echo "${candidate}" - fi - done -} \ No newline at end of file From fc9829edeea1fba25619f81a3ebf770713db788e Mon Sep 17 00:00:00 2001 From: ryoya ito <30540303+ry-itto@users.noreply.github.com> Date: Tue, 28 Apr 2026 16:15:24 +0900 Subject: [PATCH 02/10] =?UTF-8?q?chore(dotfiles):=20tmux/wezterm=20?= =?UTF-8?q?=E8=A8=AD=E5=AE=9A=E3=81=A8=20README=20=E8=87=AA=E5=8B=95?= =?UTF-8?q?=E7=94=9F=E6=88=90=E3=82=92=E5=BB=83=E6=AD=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - `dot_tmux.conf`, `dot_wezterm.lua` を削除 (どちらも未使用) - `dot_Brewfile` から `tmux`, `wezterm` を削除 - `dot_hammerspoon/init.lua` の WezTerm 起動キーバインドを削除 (Hammerspoon 自体の reload/alert は維持) - README 自動生成 (`README.template.md`, `scripts/parse_brewfile.py`, `scripts/update_readme.py`, CI の update-readme ジョブ) を廃止し、`README.md` を手動メンテに切り替え - `CLAUDE.md` / `.chezmoiignore` を新構成に追従 Co-Authored-By: Claude Opus 4.7 (1M context) --- .chezmoiignore | 2 - .github/workflows/ci.yml | 54 ---- CLAUDE.md | 11 +- README.md | 94 +----- README.template.md | 171 ---------- dot_Brewfile | 2 - dot_hammerspoon/init.lua | 18 -- dot_tmux.conf | 60 ---- dot_wezterm.lua | 653 -------------------------------------- scripts/parse_brewfile.py | 157 --------- scripts/update_readme.py | 145 --------- 11 files changed, 7 insertions(+), 1360 deletions(-) delete mode 100644 README.template.md delete mode 100644 dot_tmux.conf delete mode 100644 dot_wezterm.lua delete mode 100755 scripts/parse_brewfile.py delete mode 100755 scripts/update_readme.py diff --git a/.chezmoiignore b/.chezmoiignore index 5c7a71f..4355b42 100644 --- a/.chezmoiignore +++ b/.chezmoiignore @@ -1,10 +1,8 @@ README.md -README.template.md LICENSE CLAUDE.md .github .gitignore -scripts # Destination side files chezmoi must not touch .claude/local diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f44d470..4e823c7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,9 +3,6 @@ name: CI on: push: branches: [ main ] - paths-ignore: - - 'README.md' - - '.github/workflows/update-readme.yml' pull_request: branches: [ main ] @@ -78,54 +75,3 @@ jobs: echo "$diff_output" exit 1 fi - - update-readme: - name: Update README - runs-on: macos-latest - needs: [lint, chezmoi-verify] - if: github.ref == 'refs/heads/main' && github.event_name == 'push' - - permissions: - contents: write - - steps: - - uses: actions/checkout@v4 - with: - token: ${{ secrets.GITHUB_TOKEN }} - fetch-depth: 0 - - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: '3.11' - - - name: Update README - run: | - echo "=== Updating README with environment information ===" - python3 scripts/update_readme.py - - - name: Check for changes - id: check_changes - run: | - if [[ -n $(git status --porcelain README.md) ]]; then - echo "changes=true" >> "$GITHUB_OUTPUT" - echo "README.md has changes" - else - echo "changes=false" >> "$GITHUB_OUTPUT" - echo "No changes to README.md" - fi - - - name: Commit and push changes - if: steps.check_changes.outputs.changes == 'true' - run: | - git config --local user.email "github-actions[bot]@users.noreply.github.com" - git config --local user.name "github-actions[bot]" - - git add README.md - git commit -m "docs: update README with latest environment info [skip ci] - - Auto-generated by GitHub Actions - Workflow: ${{ github.workflow }} - Run: ${{ github.run_number }}" - - git push diff --git a/CLAUDE.md b/CLAUDE.md index 930ae7a..99556e9 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -66,8 +66,8 @@ The repository **is** the chezmoi source directory. chezmoi reads filename prefi **Managed dotfiles** (chezmoi targets): - `dot_zshrc` — entrypoint that sources modules under `~/.zsh/` - `dot_zsh/` — modular Zsh config: `alias.zsh`, `env.zsh`, `style.zsh`, `plugin.zsh`, `functions/`, `bin/executable_reload` -- `dot_tmux.conf`, `dot_gitconfig`, `dot_Brewfile`, `dot_commit_template` -- `dot_vim/`, `dot_wezterm.lua`, `dot_hammerspoon/`, `dot_claude/` +- `dot_gitconfig`, `dot_Brewfile`, `dot_commit_template` +- `dot_vim/`, `dot_hammerspoon/`, `dot_claude/` - `dot_config/nvim/`, `dot_config/starship.toml`, `dot_config/mise/config.toml` - `private_Library/private_Application Support/Code/User/settings.json` — VSCode user settings @@ -83,9 +83,8 @@ The repository **is** the chezmoi source directory. chezmoi reads filename prefi - `.chezmoiignore` — paths chezmoi should skip during apply (README, scripts/, CI files, destination-side local files) **Repository support files** (excluded from `chezmoi apply` via `.chezmoiignore`): -- `scripts/parse_brewfile.py`, `scripts/update_readme.py` — README generation in CI -- `.github/workflows/ci.yml` — lint, chezmoi-verify, README auto-update -- `README.md`, `README.template.md`, `CLAUDE.md`, `LICENSE` +- `.github/workflows/ci.yml` — lint, chezmoi-verify +- `README.md`, `CLAUDE.md`, `LICENSE` ### Run Script Execution Order @@ -107,7 +106,7 @@ All run scripts honor `CI=1` and exit early in CI to avoid expensive operations. - **iOS Development**: Xcode, XcodeGen, xcbeautify (Homebrew) - **Flutter / Rust / Node / Ruby**: managed by mise (`dot_config/mise/config.toml`) - **Web Development**: Node.js (via mise), npm/yarn ecosystem -- **General**: Git, GitHub CLI, tmux, Neovim, Starship prompt +- **General**: Git, GitHub CLI, Neovim, Starship prompt ## Key Design Principles diff --git a/README.md b/README.md index 1509ad6..0999b19 100644 --- a/README.md +++ b/README.md @@ -18,92 +18,6 @@ chezmoi init --apply ry-itto/dotfiles - Command Line Tools for Xcode - Internet connection for downloading packages - -## 📦 Package Configuration - -> **Tested on**: macOS 26.2 (arm64) - Last updated: 2026-04-28 06:48 UTC - -The following packages are defined in `dot_Brewfile` (rendered to `~/.Brewfile`) for installation: - -
-🛠️ Homebrew Formulae (30 packages) - - -**zsh関係** - -- `zsh` - Z shell - Modern shell with advanced features -- `zplug` - Zsh plugin manager - -**iOS** - -- `xcodegen` - Generate Xcode projects from spec files -- `xcbeautify` - Xcode build output formatter - -**Flutter** - -- `usbmuxd` - USB multiplexing daemon for iOS devices -- `libimobiledevice` (latest development version) - iOS device communication library -- `ideviceinstaller` - Manage iOS apps from command line -- `ios-deploy` - Install and debug iOS apps from command line - -**MCP** - -- `uv` - Fast Python package installer and resolver - -**ツール** - -- `ag` - The Silver Searcher - Fast code searching -- `gh` - GitHub CLI -- `ghq` - Git repository organizer -- `fzf` - Fuzzy finder for command line -- `jq` - JSON processor -- `tig` - Text-mode interface for git -- `tree` - Display directory tree structure -- `nkf` - Network Kanji Filter - Character encoding converter -- `git` - Distributed version control system -- `emojify` - Emoji on the command line -- `nvim` - Neovim - Hyperextensible Vim-based text editor -- `tmux` - Terminal multiplexer -- `starship` - Cross-shell prompt -- `mise` - Development environment manager (formerly rtx) -- `act` - Run GitHub Actions locally - -**gPRC** - -- `protobuf` - Protocol Buffers - Google's data interchange format - -**ruby-build** - -- `openssl@3` - Cryptography and SSL/TLS toolkit -- `readline` - GNU readline library -- `libyaml` - YAML parser and emitter library -- `autoconf` - Automatic configure script builder -- `gmp` - GNU multiple precision arithmetic library - -
- -
-🖥️ Homebrew Casks - GUI Applications (12 apps) - - -**Cask** - -- `clipy` - Clipboard manager -- `raycast` - Productivity launcher -- `font-hack-nerd-font` - Hack font with Nerd Font patches -- `font-hackgen` - Japanese programming font -- `font-hackgen-nerd` - HackGen with Nerd Font patches -- `notion` - All-in-one workspace -- `notion-calendar` - Calendar app by Notion -- `figma` - Collaborative design tool -- `discord` - Voice, video, and text chat -- `rectangle` - Window management app -- `hammerspoon` - Desktop automation tool -- `wezterm` - GPU-accelerated terminal emulator - -
- - ## 🛠 Installation ```bash @@ -150,12 +64,10 @@ chezmoi add ~/.somefile │ ├── style.zsh │ ├── functions/ │ └── bin/executable_reload # → ~/.zsh/bin/reload (chmod +x) -├── dot_tmux.conf ├── dot_gitconfig ├── dot_Brewfile ├── dot_commit_template ├── dot_vim/ -├── dot_wezterm.lua ├── dot_hammerspoon/ ├── dot_claude/ # → ~/.claude/ ├── dot_config/ @@ -171,7 +83,6 @@ chezmoi add ~/.somefile ├── run_once_install-dein.sh ├── run_once_install-mise-tools.sh ├── .chezmoiignore # files to skip during apply -├── scripts/ # README generator (CI only) └── .github/workflows/ci.yml ``` @@ -181,7 +92,6 @@ chezmoi add ~/.somefile - **Package Managers**: Homebrew, mise - **Shell**: Zsh with zplug, Starship prompt -- **Terminal**: WezTerm, tmux - **Editors**: Neovim, VSCode - **Version Control**: Git, GitHub CLI @@ -214,9 +124,9 @@ Modular configuration in `dot_zsh/`: `dot_gitconfig` provides commit template, GitHub CLI helpers, and standard pull/credential settings. -### Tmux / Vim +### Vim -Pre-configured tmux key bindings and Vim setup with dein.vim plugin manager. +Vim setup is wired up via dein.vim. Plugin manifests live under `dot_vim/rc/`. ## 🔧 Customization diff --git a/README.template.md b/README.template.md deleted file mode 100644 index 4ce791f..0000000 --- a/README.template.md +++ /dev/null @@ -1,171 +0,0 @@ -# dotfiles - -My personal dotfiles for macOS development environment, managed by [chezmoi](https://www.chezmoi.io/). - -## 🚀 Quick Start - -```bash -# Install chezmoi if you don't have it -brew install chezmoi - -# Initialize and apply this repository -chezmoi init --apply ry-itto/dotfiles -``` - -## 📋 Requirements - -- macOS (this configuration is macOS-only) -- Command Line Tools for Xcode -- Internet connection for downloading packages - - -## 📦 Package Configuration - -> **Tested on**: {{OS_NAME}} {{OS_VERSION}} ({{ARCH}}) - Last updated: {{UPDATED_AT}} - -The following packages are defined in `dot_Brewfile` (rendered to `~/.Brewfile`) for installation: - -
-🛠️ Homebrew Formulae ({{FORMULAE_COUNT}} packages) - -{{FORMULAE_LIST}} - -
- -
-🖥️ Homebrew Casks - GUI Applications ({{CASKS_COUNT}} apps) - -{{CASKS_LIST}} - -
- - -## 🛠 Installation - -```bash -brew install chezmoi -chezmoi init --apply ry-itto/dotfiles -``` - -`chezmoi init --apply` will: - -1. Clone this repository into `~/.local/share/chezmoi` -2. Render dotfiles into `$HOME` (e.g. `dot_zshrc` → `~/.zshrc`) -3. Run `run_onchange_install-brew-packages.sh` to install Homebrew bundle from `~/.Brewfile` -4. Run `run_onchange_configure-macos-defaults.sh` and `run_onchange_configure-xcode.sh` to apply system defaults -5. Run `run_once_install-zplug.sh`, `run_once_install-dein.sh` to bootstrap shell/editor plugin managers -6. Run `run_once_install-mise-tools.sh` to install language runtimes (flutter, rust, node, ruby) defined in `dot_config/mise/config.toml` - -## 🔄 Daily Operations - -```bash -# Pull latest changes from this repo and re-apply -chezmoi update - -# Edit a managed file (opens source file in $EDITOR) -chezmoi edit ~/.zshrc - -# See what would change before applying -chezmoi diff - -# Add a new file from $HOME into management -chezmoi add ~/.somefile -``` - -> **Note:** After migrating to chezmoi, editing files in `$HOME` directly does **not** sync back to this repository. Use `chezmoi edit` or edit the source file under `~/.local/share/chezmoi`, then `chezmoi apply`. - -## 📂 Directory Structure - -``` -. -├── dot_zshrc # → ~/.zshrc -├── dot_zsh/ # → ~/.zsh/ -│ ├── alias.zsh -│ ├── env.zsh -│ ├── plugin.zsh -│ ├── style.zsh -│ ├── functions/ -│ └── bin/executable_reload # → ~/.zsh/bin/reload (chmod +x) -├── dot_tmux.conf -├── dot_gitconfig -├── dot_Brewfile -├── dot_commit_template -├── dot_vim/ -├── dot_wezterm.lua -├── dot_hammerspoon/ -├── dot_claude/ # → ~/.claude/ -├── dot_config/ -│ ├── nvim/ -│ ├── starship.toml -│ └── mise/config.toml # mise tool definitions -├── private_Library/ -│ └── private_Application Support/Code/User/settings.json # → VSCode settings -├── run_onchange_install-brew-packages.sh.tmpl -├── run_onchange_configure-macos-defaults.sh -├── run_onchange_configure-xcode.sh -├── run_once_install-zplug.sh -├── run_once_install-dein.sh -├── run_once_install-mise-tools.sh -├── .chezmoiignore # files to skip during apply -├── scripts/ # README generator (CI only) -└── .github/workflows/ci.yml -``` - -## 🎯 What's Included - -### Development Tools - -- **Package Managers**: Homebrew, mise -- **Shell**: Zsh with zplug, Starship prompt -- **Terminal**: WezTerm, tmux -- **Editors**: Neovim, VSCode -- **Version Control**: Git, GitHub CLI - -### Language Runtimes (managed by mise) - -Defined in `dot_config/mise/config.toml`: - -- Flutter -- Rust -- Node.js -- Ruby - -### Other Stacks - -- **iOS Development**: Xcode, XcodeGen, xcbeautify -- **macOS Apps**: Raycast, Hammerspoon, Rectangle, Clipy - -## ⚙️ Configuration - -### Zsh - -Modular configuration in `dot_zsh/`: - -- `alias.zsh`: Custom command aliases -- `env.zsh`: Environment variables and PATH setup -- `plugin.zsh`: Zsh plugin configuration via zplug -- `style.zsh`: Prompt and appearance settings - -### Git - -`dot_gitconfig` provides commit template, GitHub CLI helpers, and standard pull/credential settings. - -### Tmux / Vim - -Pre-configured tmux key bindings and Vim setup with dein.vim plugin manager. - -## 🔧 Customization - -1. **Fork this repository** to create your own version -2. **Edit configurations** under `~/.local/share/chezmoi/` (or via `chezmoi edit`) -3. **Apply changes** with `chezmoi apply` -4. **Adjust runtime versions** in `dot_config/mise/config.toml` -5. **Modify packages** in `dot_Brewfile` - -## 🤝 Contributing - -Feel free to open issues or submit pull requests if you have suggestions for improvements. - -## 📄 License - -This repository is available under the MIT License. Feel free to fork and modify for your own use. diff --git a/dot_Brewfile b/dot_Brewfile index 4241559..c277462 100644 --- a/dot_Brewfile +++ b/dot_Brewfile @@ -27,7 +27,6 @@ brew 'nkf' brew 'git' brew 'emojify' brew 'nvim' -brew 'tmux' brew 'starship' brew 'mise' brew 'act' @@ -54,4 +53,3 @@ cask 'figma' cask 'discord' cask 'rectangle' cask 'hammerspoon' -cask 'wezterm' diff --git a/dot_hammerspoon/init.lua b/dot_hammerspoon/init.lua index 49cacc4..cbacce2 100644 --- a/dot_hammerspoon/init.lua +++ b/dot_hammerspoon/init.lua @@ -1,21 +1,3 @@ --- WezTermの表示/非表示を切り替える関数 -local open_wezterm = function() - local appName = "WezTerm" - local app = hs.application.get(appName) - - if app == nil or app:isHidden() or not(app:isFrontmost()) then - -- アプリが起動していない、隠れている、または最前面でない場合は表示 - hs.application.launchOrFocus(appName) - else - -- アプリが最前面にある場合は隠す - app:hide() - end -end - --- ホットキーの設定: Alt+Space (Option+Space) でWezTermの表示/非表示を切り替え --- tmux.confのプレフィックスキー(Ctrl+q)と競合しないように設定 -hs.hotkey.bind({"alt"}, "space", open_wezterm) - -- Hammerspoonの設定リロード用ホットキー: Cmd+Alt+Ctrl+R hs.hotkey.bind({"cmd", "alt", "ctrl"}, "R", function() hs.reload() diff --git a/dot_tmux.conf b/dot_tmux.conf deleted file mode 100644 index eed9252..0000000 --- a/dot_tmux.conf +++ /dev/null @@ -1,60 +0,0 @@ -# ref: https://qiita.com/shin-ch13/items/9d207a70ccc8467f7bab - -set-option -g default-shell "${SHELL}" - -# tmuxを256色表示できるようにする -set-option -g default-terminal screen-256color -set -g terminal-overrides 'xterm:colors=256' - -# prefixキーをC-qに変更 -set -g prefix C-q -# C-bのキーバインドを解除 -unbind C-b - - -# ステータスバーをトップに配置する -set-option -g status-position top - -# 左右のステータスバーの長さを決定する -set-option -g status-left-length 90 -set-option -g status-right-length 90 - -# #P => ペイン番号 -# 最左に表示 -set-option -g status-left '[#P]' - -# Wi-Fi、バッテリー残量、現在時刻 -# 最右に表示 -set-option -g status-right '#(wifi) #(battery --tmux) [%Y-%m-%d(%a) %H:%M]' - -# ステータスバーを1秒毎に描画し直す -set-option -g status-interval 1 - -# センタライズ(主にウィンドウ番号など) -set-option -g status-justify centre - -# ステータスバーの色を設定する -set-option -g status-bg "colour238" - -# status line の文字色を指定する。 -set-option -g status-fg "colour255" - -# vimのキーバインドでペインを移動する -bind h select-pane -L -bind j select-pane -D -bind k select-pane -U -bind l select-pane -R - -# vimのキーバインドでペインをリサイズする -bind -r H resize-pane -L 5 -bind -r J resize-pane -D 5 -bind -r K resize-pane -U 5 -bind -r L resize-pane -R 5 - -# | でペインを縦分割する -bind | split-window -h - -# - でペインを縦分割する -bind - split-window -v - -set -g @plugin "arcticicestudio/nord-tmux" diff --git a/dot_wezterm.lua b/dot_wezterm.lua deleted file mode 100644 index e380eec..0000000 --- a/dot_wezterm.lua +++ /dev/null @@ -1,653 +0,0 @@ -local wezterm = require 'wezterm' -local config = wezterm.config_builder() -local act = wezterm.action - --- タブ -config.window_decorations = "RESIZE" - --- パフォーマンス設定 -config.animation_fps = 120 -config.max_fps = 120 -config.prefer_egl = true -config.front_end = 'WebGpu' -config.webgpu_power_preference = 'HighPerformance' - --- Nordテーマの設定 -config.color_scheme = 'Nord (Gogh)' - --- フォント設定 -config.font = wezterm.font_with_fallback { - 'HackGen Console NF', -- HackGen Nerd Font (アイコン含む) - 'HackGen Console', -- HackGen 通常版 - 'HackGen', -- HackGen フォールバック -} -config.font_size = 12.0 - --- ウィンドウの設定 -config.window_padding = { - left = 10, - right = 10, - top = 10, - bottom = 10, -} - --- タブバーの設定 -config.enable_tab_bar = true -config.hide_tab_bar_if_only_one_tab = false -config.tab_bar_at_bottom = true -- 下部に配置 -config.use_fancy_tab_bar = false -- シンプルなタブバー -config.show_new_tab_button_in_tab_bar = false -config.tab_max_width = 50 - --- ステータスバー更新間隔 -config.status_update_interval = 1000 - --- Git コマンドを安全に実行するヘルパー関数 -local function safe_git_command(cwd, ...) - local success, stdout = wezterm.run_child_process { - 'git', - '-C', - cwd, - ..., - } - if success then - return stdout:gsub('\n', '') - end - return nil -end - --- Git URL からリポジトリ名を抽出 -local function extract_repo_name_from_url(url) - if not url then - return nil - end - local repo_name = url:match '([^/]+)%.git$' or url:match '([^/]+)$' - return repo_name -end - --- プロセス名をアイコンに変換 -local function process_to_icon(process_name) - if process_name == 'nvim' then - return '' - elseif process_name == 'zsh' then - return '' - elseif process_name == 'bash' then - return '󱆃' - elseif process_name == 'sl' then - return '󰔬' - elseif process_name == 'lazygit' or process_name == 'tig' then - return '' - elseif process_name == 'wezterm' then - return '' - elseif process_name == 'mcfly' then - return '' - elseif process_name == 'emu' then - return '🦤' - elseif string.match(process_name, '^python') then - return '󰌠' - elseif process_name == '' then - return '🤖' - else - return process_name - end -end - --- Git リポジトリ名を取得 -local function get_git_repo_name(cwd_path) - -- Git リポジトリかチェック - if not safe_git_command(cwd_path, 'rev-parse', '--git-dir') then - return nil - end - - local repo_name = nil - - -- remote origin から取得 - local remote_url = safe_git_command(cwd_path, 'config', '--get', 'remote.origin.url') - if remote_url then - repo_name = extract_repo_name_from_url(remote_url) - end - - -- 他の remote から取得 - if not repo_name then - local remotes = safe_git_command(cwd_path, 'remote') - if remotes and remotes ~= '' then - local first_remote = remotes:match '([^\n]+)' - if first_remote then - remote_url = safe_git_command(cwd_path, 'config', '--get', 'remote.' .. first_remote .. '.url') - if remote_url then - repo_name = extract_repo_name_from_url(remote_url) - end - end - end - end - - -- toplevel のディレクトリ名 - if not repo_name then - local toplevel = safe_git_command(cwd_path, 'rev-parse', '--show-toplevel') - if toplevel then - local bare_pattern = '([^/]+)%.bare' - local git_pattern = '([^/]+)%.git' - local dir_pattern = '([^/]+)$' - - if toplevel:match '%.bare/' or toplevel:match '%.git/' then - repo_name = toplevel:match(bare_pattern) or toplevel:match(git_pattern) - else - repo_name = toplevel:match(dir_pattern) - end - end - end - - -- 現在のディレクトリ名(最終手段) - if not repo_name then - local dir_name = cwd_path:match '([^/]+)$' - if dir_name then - repo_name = dir_name:gsub('%.git$', '') - end - end - - return repo_name -end - --- Claude 関連の定数 -local CLAUDE_CONSTANTS = { - -- プロセスフィルタリング - EXCLUDE_PATTERNS = { 'npm', 'node', 'claude%-code' }, - INVALID_TTY = '??', - - -- 実行判定の閾値 - CPU_ACTIVE_THRESHOLD = 1.0, -- CPU 使用率がこれ以上なら実行中 - CPU_CHECK_THRESHOLD = 0.1, -- FD チェックを行う最小 CPU 使用率 - FD_ACTIVE_THRESHOLD = 15, -- ファイルディスクリプタ数の閾値 - - -- 表示 - EMOJI_IDLE = '🤖', - EMOJI_RUNNING = '⚡', - COLOR_ICON = '#FF6B6B', - - -- Git 表示色 - GIT_ICON_COLOR = '#569CD6', - GIT_REPO_COLOR = '#808080', - GIT_BRANCH_ICON_COLOR = '#4EC9B0', - GIT_BRANCH_COLOR = '#909090', - - -- スペーシング - SPACING_SMALL = ' ', - SPACING_MEDIUM = ' ', - SPACING_SINGLE = ' ', - - -- システムコマンド - PS_PATH = '/bin/ps', -} - --- プロセスの実行状態をチェックするヘルパー関数 -local function check_process_running(pid) - local ps_success, ps_stdout = wezterm.run_child_process { - CLAUDE_CONSTANTS.PS_PATH, - '-p', - tostring(pid), - '-o', - 'stat,pcpu,rss', - } - - if not ps_success or not ps_stdout then - return false - end - - local lines = {} - for line in ps_stdout:gmatch '[^\n]+' do - table.insert(lines, line) - end - - if #lines < 2 then - return false - end - - local data_line = lines[2] - local stat, pcpu, rss = data_line:match '%s*(%S+)%s+(%S+)%s+(%S+)' - - if not stat then - return false - end - - -- 1. プロセス状態による判定 - if stat:match '^[RD]' then - return true - end - - local cpu_usage = tonumber(pcpu) or 0 - - -- 2. CPU 使用率による判定 - if cpu_usage >= CLAUDE_CONSTANTS.CPU_ACTIVE_THRESHOLD then - return true - end - - -- 3. ファイルディスクリプタ数をチェック(コスト高いので条件付き) - if cpu_usage > CLAUDE_CONSTANTS.CPU_CHECK_THRESHOLD then - local lsof_success, lsof_stdout = wezterm.run_child_process { - 'lsof', - '-p', - tostring(pid), - '-t', - } - if lsof_success and lsof_stdout then - local fd_count = 0 - for _ in lsof_stdout:gmatch '[^\n]+' do - fd_count = fd_count + 1 - end - if fd_count > CLAUDE_CONSTANTS.FD_ACTIVE_THRESHOLD then - return true - end - end - end - - return false -end - --- Claude プロセス情報を取得する関数 -local function get_claude_status(window) - -- エラーハンドリング - if not window then - return { tab_sessions = {} } - end - - local success, result = pcall(function() - local mux_window = window:mux_window() - if not mux_window then - return { tab_sessions = {} } - end - - local tabs = mux_window:tabs() - if not tabs then - return { tab_sessions = {} } - end - - local tab_sessions = {} - - for tab_index, tab in ipairs(tabs) do - local has_claude = false - local is_running = false - - -- タブ内の全ペインをチェック - local tab_success, panes = pcall(function() - return tab:panes() - end) - if tab_success and panes then - for _, pane in ipairs(panes) do - local proc_success, proc_info = pcall(function() - return pane:get_foreground_process_info() - end) - if proc_success and proc_info then - -- Claude プロセスかチェック(プロセス名または argv で) - local is_claude_process = false - if proc_info.name and proc_info.name:match '^claude' then - is_claude_process = true - elseif proc_info.argv and #proc_info.argv > 0 and proc_info.argv[1]:match '^claude' then - is_claude_process = true - end - - if is_claude_process then - -- 除外パターンをチェック - local should_exclude = false - local cmdline = table.concat(proc_info.argv or {}, ' ') - for _, pattern in ipairs(CLAUDE_CONSTANTS.EXCLUDE_PATTERNS) do - if cmdline:match(pattern) then - should_exclude = true - break - end - end - - if not should_exclude then - has_claude = true - -- 実行状態をチェック - if proc_info.pid then - is_running = check_process_running(proc_info.pid) - end - break -- タブ内に 1 つでも Claude があれば十分 - end - end - end - end - end - - -- タブごとの Claude 情報を記録 - table.insert(tab_sessions, { - tab_index = tab_index, - has_claude = has_claude, - running = is_running, - }) - end - - return { tab_sessions = tab_sessions } - end) - - if success then - return result - else - -- エラー時は空のセッションを返す - return { tab_sessions = {} } - end -end - --- Claude ステータス表示 -local function add_claude_status_to_elements(elements, tab_sessions, window) - if not tab_sessions or #tab_sessions == 0 then - return - end - - -- タブ順序に従ってステータスを表示 - for i, tab_session in ipairs(tab_sessions) do - if tab_session.has_claude then - -- Claude タブの場合 - table.insert(elements, { Foreground = { Color = CLAUDE_CONSTANTS.COLOR_ICON } }) - local emoji = tab_session.running and CLAUDE_CONSTANTS.EMOJI_RUNNING or CLAUDE_CONSTANTS.EMOJI_IDLE - table.insert(elements, { Text = emoji }) - else - -- 非 Claude タブの場合 - table.insert(elements, { Foreground = { Color = '#8B4513' } }) - table.insert(elements, { Text = '🧔' }) - end - - -- 最後以外はスペースを追加 - if i < #tab_sessions then - table.insert(elements, { Text = CLAUDE_CONSTANTS.SPACING_SINGLE }) - end - end - - table.insert(elements, { Text = CLAUDE_CONSTANTS.SPACING_SINGLE }) -end - --- タブタイトルを更新する関数 -local function update_tab_titles(window) - if not window then - return - end - - local mux_window = window:mux_window() - if not mux_window then - return - end - - local tabs = mux_window:tabs() - if not tabs then - return - end - - for _, tab in ipairs(tabs) do - local panes = tab:panes() - if panes and #panes > 0 then - local pane = panes[1] -- 最初のペインを使用 - local cwd = pane:get_current_working_dir() - - if cwd then - local cwd_path = cwd.file_path - local repo_name = get_git_repo_name(cwd_path) - - if repo_name then - -- ブランチ名を取得 - local branch = safe_git_command(cwd_path, 'branch', '--show-current') - if not branch or branch == '' then - local ref = safe_git_command(cwd_path, 'symbolic-ref', '--short', 'HEAD') - if ref then - branch = ref - else - branch = safe_git_command(cwd_path, 'rev-parse', '--short', 'HEAD') - end - end - - -- タブタイトルを repo_name/branch 形式に設定 - local tab_title = repo_name - if branch then - tab_title = repo_name .. '/' .. branch - end - tab:set_title(tab_title) - end - end - end - end -end - --- タブのタイトル表示をカスタマイズ -wezterm.on('format-tab-title', function(tab, tabs, panes, conf, hover, max_width) - local background = '#2E3440' - local foreground = '#D8DEE9' - local edge_background = '#2E3440' - - if tab.is_active or hover then - background = '#5E81AC' - foreground = '#ECEFF4' - end - local edge_foreground = background - - -- タブタイトルを決定 - local title = '' - - -- タブのカスタムタイトルをチェック(リポジトリ名が設定されている場合) - if tab.tab_title and tab.tab_title ~= '' then - title = tab.tab_title - else - -- デフォルトのタイトルを取得してアイコンに変換 - title = process_to_icon(tab.active_pane.title) - end - - -- Claude ステータス(元の無効化状態に戻す) - local claude_emoji = '' - - return { - { Background = { Color = edge_background } }, - { Foreground = { Color = edge_foreground } }, - { Text = ' ' }, - { Background = { Color = background } }, - { Foreground = { Color = foreground } }, - { Attribute = { Intensity = tab.is_active and 'Bold' or 'Normal' } }, - { Text = ' ' .. title .. claude_emoji .. ' ' }, - { Background = { Color = edge_background } }, - { Foreground = { Color = edge_foreground } }, - { Text = '' }, - } -end) - --- 右ステータスバーの更新 -wezterm.on('update-right-status', function(window, pane) - local elements = {} - - -- Claude ステータスを取得 - local claude_status = get_claude_status(window) - - local cwd = pane:get_current_working_dir() - if not cwd then - -- Claude ステータスのみ表示 - add_claude_status_to_elements(elements, claude_status.tab_sessions, window) - window:set_right_status(wezterm.format(elements)) - return - end - - local cwd_path = cwd.file_path - - -- Git リポジトリ名を取得 - local repo_name = get_git_repo_name(cwd_path) - - if not repo_name then - -- Git リポジトリでない場合 - local mux_window = window:mux_window() - if mux_window then - local active_tab = mux_window:active_tab() - if active_tab and active_tab:tab_id() == pane:tab():tab_id() then - active_tab:set_title('') - end - end - - -- Git リポジトリでない場合は Claude ステータスのみ表示 - add_claude_status_to_elements(elements, claude_status.tab_sessions, window) - window:set_right_status(wezterm.format(elements)) - return - end - - -- ブランチ名を取得 - local branch = safe_git_command(cwd_path, 'branch', '--show-current') - if not branch or branch == '' then - local ref = safe_git_command(cwd_path, 'symbolic-ref', '--short', 'HEAD') - if ref then - branch = ref - else - branch = safe_git_command(cwd_path, 'rev-parse', '--short', 'HEAD') - end - end - - -- Git 表示 - if repo_name then - table.insert(elements, { Foreground = { Color = CLAUDE_CONSTANTS.GIT_ICON_COLOR } }) - table.insert(elements, { Text = CLAUDE_CONSTANTS.SPACING_SMALL }) - table.insert(elements, { Foreground = { Color = CLAUDE_CONSTANTS.GIT_REPO_COLOR } }) - table.insert(elements, { Text = repo_name }) - - if branch then - table.insert(elements, { Foreground = { Color = CLAUDE_CONSTANTS.GIT_BRANCH_ICON_COLOR } }) - table.insert(elements, { Text = CLAUDE_CONSTANTS.SPACING_MEDIUM }) - table.insert(elements, { Foreground = { Color = CLAUDE_CONSTANTS.GIT_BRANCH_COLOR } }) - table.insert(elements, { Text = branch }) - end - - -- アクティブなタブのタイトルを更新 - local mux_window = window:mux_window() - if mux_window then - local active_tab = mux_window:active_tab() - if active_tab and active_tab:tab_id() == pane:tab():tab_id() then - -- タブタイトルを repo_name/branch 形式に設定 - local tab_title = repo_name - if branch then - tab_title = repo_name .. '/' .. branch - end - active_tab:set_title(tab_title) - end - end - end - - -- Claude ステータス表示(最後に表示) - if #claude_status.tab_sessions > 0 then - table.insert(elements, { Text = CLAUDE_CONSTANTS.SPACING_SMALL }) - end - add_claude_status_to_elements(elements, claude_status.tab_sessions, window) - - window:set_right_status(wezterm.format(elements)) -end) - --- タブがアクティブになった時にも更新(即座更新) -wezterm.on('tab-active', function(tab, pane, window) - -- すぐに更新をトリガー - wezterm.emit('update-right-status', window, pane) - - -- タブタイトルを更新 - update_tab_titles(window) - - -- 少し遅れてもう一度更新(確実性向上) - wezterm.time.call_after(0.1, function() - wezterm.emit('update-right-status', window, pane) - update_tab_titles(window) - end) -end) - --- ウィンドウフォーカス時にタブタイトルを更新 -wezterm.on('window-focus-changed', function(window, pane) - update_tab_titles(window) -end) - --- 新しいタブ作成時にタブタイトルを更新 -wezterm.on('new-tab-button-click', function(window, pane, button, default_action) - wezterm.time.call_after(0.5, function() - update_tab_titles(window) - end) - return false -end) - --- 自動ウィンドウ分割機能 -local function create_auto_split_layout(window, pane) - -- 現在のペインを基準に分割を実行 - -- まず左右に分割(40:60) - local right_pane = pane:split { - direction = 'Right', - size = 0.6, - } - - -- 右側のペインを上下に分割(70:30) - wezterm.sleep_ms(100) -- 分割が完了するまで少し待機 - right_pane:split { - direction = 'Bottom', - size = 0.3, - } - - -- 元のペイン(左側)にフォーカスを戻す - pane:activate() -end - --- カスタムコマンド実行時の自動分割 -wezterm.on('user-var-changed', function(window, pane, name, value) - if name == 'wezterm_auto_split' and value == 'MQ==' then -- MQ== は base64 エンコードされた "1" - create_auto_split_layout(window, pane) - end -end) - --- キーバインド設定(tmux.confに準拠) -config.leader = { key = 'q', mods = 'CTRL', timeout_milliseconds = 1000 } -config.keys = { - -- ペイン分割 - { key = '|', mods = 'LEADER', action = act.SplitHorizontal { domain = 'CurrentPaneDomain' } }, - { key = '-', mods = 'LEADER', action = act.SplitVertical { domain = 'CurrentPaneDomain' } }, - { key = 'd', mods = 'CMD', action = act.SplitHorizontal { domain = 'CurrentPaneDomain' } }, -- Cmd+dで縦分割(左右に分割) - { key = 'w', mods = 'CMD', action = act.CloseCurrentPane { confirm = false } }, -- Cmd+wで現在のペインを閉じる - - -- ペイン移動(vim風) - { key = 'h', mods = 'LEADER', action = act.ActivatePaneDirection 'Left' }, - { key = 'j', mods = 'LEADER', action = act.ActivatePaneDirection 'Down' }, - { key = 'k', mods = 'LEADER', action = act.ActivatePaneDirection 'Up' }, - { key = 'l', mods = 'LEADER', action = act.ActivatePaneDirection 'Right' }, - - -- ペインのリサイズ - { key = 'H', mods = 'LEADER', action = act.AdjustPaneSize { 'Left', 5 } }, - { key = 'J', mods = 'LEADER', action = act.AdjustPaneSize { 'Down', 5 } }, - { key = 'K', mods = 'LEADER', action = act.AdjustPaneSize { 'Up', 5 } }, - { key = 'L', mods = 'LEADER', action = act.AdjustPaneSize { 'Right', 5 } }, - - -- タブ操作 - { key = 'c', mods = 'LEADER', action = act.SpawnTab 'CurrentPaneDomain' }, - { key = 'n', mods = 'LEADER', action = act.ActivateTabRelative(1) }, - { key = 'p', mods = 'LEADER', action = act.ActivateTabRelative(-1) }, - { key = '&', mods = 'LEADER', action = act.CloseCurrentTab { confirm = true } }, - - -- タブ番号でジャンプ - { key = '1', mods = 'LEADER', action = act.ActivateTab(0) }, - { key = '2', mods = 'LEADER', action = act.ActivateTab(1) }, - { key = '3', mods = 'LEADER', action = act.ActivateTab(2) }, - { key = '4', mods = 'LEADER', action = act.ActivateTab(3) }, - { key = '5', mods = 'LEADER', action = act.ActivateTab(4) }, - { key = '6', mods = 'LEADER', action = act.ActivateTab(5) }, - { key = '7', mods = 'LEADER', action = act.ActivateTab(6) }, - { key = '8', mods = 'LEADER', action = act.ActivateTab(7) }, - { key = '9', mods = 'LEADER', action = act.ActivateTab(8) }, - - -- ペインをズーム - { key = 'z', mods = 'LEADER', action = act.TogglePaneZoomState }, - - -- コピーモード - { key = '[', mods = 'LEADER', action = act.ActivateCopyMode }, - - -- ペインを閉じる - { key = 'x', mods = 'LEADER', action = act.CloseCurrentPane { confirm = true } }, - - -- 設定のリロード - { key = 'r', mods = 'LEADER', action = act.ReloadConfiguration }, - - -- 自動分割レイアウトを作成するキーバインド - { - key = 'w', - mods = 'LEADER', - action = wezterm.action_callback(create_auto_split_layout), - }, -} - --- ペインの境界線スタイル -config.inactive_pane_hsb = { - saturation = 0.8, - brightness = 0.7, -} - -return config diff --git a/scripts/parse_brewfile.py b/scripts/parse_brewfile.py deleted file mode 100755 index 777eab7..0000000 --- a/scripts/parse_brewfile.py +++ /dev/null @@ -1,157 +0,0 @@ -#!/usr/bin/env python3 - -import re -import json -from pathlib import Path - -def parse_brewfile(): - """Parse .Brewfile and extract package information with categories""" - brewfile_path = Path(__file__).parent.parent / "dot_Brewfile" - - if not brewfile_path.exists(): - return {"formulae": {}, "casks": {}} - - with open(brewfile_path, 'r') as f: - lines = f.readlines() - - result = { - "formulae": {}, - "casks": {} - } - - current_category = "Uncategorized" - - for line in lines: - line = line.strip() - - # Skip empty lines - if not line: - continue - - # Detect category comments - if line.startswith('#'): - current_category = line[1:].strip() - continue - - # Parse brew formula - brew_match = re.match(r'brew\s+[\'"]([^\'",]+)[\'"](?:,\s*args:\s*\[(.*?)\])?', line) - if brew_match: - package = brew_match.group(1) - args = brew_match.group(2) - - if current_category not in result["formulae"]: - result["formulae"][current_category] = [] - - package_info = {"name": package} - - # Check for specific version or special args - if args: - if "HEAD" in args: - package_info["version"] = "HEAD" - # Add other args parsing if needed - package_info["args"] = args - - result["formulae"][current_category].append(package_info) - continue - - # Parse cask - cask_match = re.match(r'cask\s+[\'"]([^\'",]+)[\'"]', line) - if cask_match: - package = cask_match.group(1) - - if current_category not in result["casks"]: - result["casks"][current_category] = [] - - result["casks"][current_category].append({"name": package}) - - return result - -def get_package_descriptions(): - """Define descriptions for common packages""" - return { - # Shell & Terminal - "zsh": "Z shell - Modern shell with advanced features", - "zplug": "Zsh plugin manager", - "tmux": "Terminal multiplexer", - "starship": "Cross-shell prompt", - "wezterm": "GPU-accelerated terminal emulator", - - # iOS Development - "xcodegen": "Generate Xcode projects from spec files", - "xcbeautify": "Xcode build output formatter", - "mint": "Swift package manager for command line tools", - - # Flutter/Mobile - "usbmuxd": "USB multiplexing daemon for iOS devices", - "libimobiledevice": "iOS device communication library", - "ideviceinstaller": "Manage iOS apps from command line", - "ios-deploy": "Install and debug iOS apps from command line", - - # Version Management - "mise": "Development environment manager (formerly rtx)", - "n": "Node.js version manager", - - # Git & Source Control - "git": "Distributed version control system", - "gh": "GitHub CLI", - "ghq": "Git repository organizer", - "tig": "Text-mode interface for git", - "lazygit": "Terminal UI for git commands", - - # Search & Navigation - "ag": "The Silver Searcher - Fast code searching", - "fzf": "Fuzzy finder for command line", - "tree": "Display directory tree structure", - - # Development Tools - "nvim": "Neovim - Hyperextensible Vim-based text editor", - "jq": "JSON processor", - "nkf": "Network Kanji Filter - Character encoding converter", - "emojify": "Emoji on the command line", - "act": "Run GitHub Actions locally", - "uv": "Fast Python package installer and resolver", - - # Language Support - "protobuf": "Protocol Buffers - Google's data interchange format", - "openssl@3": "Cryptography and SSL/TLS toolkit", - "readline": "GNU readline library", - "libyaml": "YAML parser and emitter library", - "autoconf": "Automatic configure script builder", - "gmp": "GNU multiple precision arithmetic library", - - # GUI Applications - "clipy": "Clipboard manager", - "raycast": "Productivity launcher", - "rectangle": "Window management app", - "hammerspoon": "Desktop automation tool", - "notion": "All-in-one workspace", - "notion-calendar": "Calendar app by Notion", - "figma": "Collaborative design tool", - "discord": "Voice, video, and text chat", - - # Fonts - "font-hack-nerd-font": "Hack font with Nerd Font patches", - "font-hackgen": "Japanese programming font", - "font-hackgen-nerd": "HackGen with Nerd Font patches", - } - -def main(): - """Main function to output parsed Brewfile data""" - data = parse_brewfile() - descriptions = get_package_descriptions() - - # Enhance with descriptions - for category, packages in data["formulae"].items(): - for package in packages: - if package["name"] in descriptions: - package["description"] = descriptions[package["name"]] - - for category, packages in data["casks"].items(): - for package in packages: - if package["name"] in descriptions: - package["description"] = descriptions[package["name"]] - - print(json.dumps(data, indent=2, ensure_ascii=False)) - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/scripts/update_readme.py b/scripts/update_readme.py deleted file mode 100755 index ca26580..0000000 --- a/scripts/update_readme.py +++ /dev/null @@ -1,145 +0,0 @@ -#!/usr/bin/env python3 - -import json -import sys -import subprocess -import platform -from datetime import datetime -from pathlib import Path - -def run_command(cmd): - """Run a shell command and return output""" - try: - result = subprocess.run(cmd, shell=True, capture_output=True, text=True) - return result.stdout.strip() - except Exception as e: - print(f"Error running command '{cmd}': {e}", file=sys.stderr) - return None - -def get_system_info(): - """Get basic system information""" - try: - # Get macOS version using sw_vers command - os_name = run_command('sw_vers -productName') or platform.system() - os_version = run_command('sw_vers -productVersion') or platform.release() - except: - # Fallback to platform module - os_name = platform.system() - os_version = platform.release() - - return { - 'os': os_name, - 'version': os_version, - 'arch': platform.machine(), - 'updated_at': datetime.utcnow().isoformat() + 'Z' - } - -def parse_brewfile(): - """Parse .Brewfile to get intended packages""" - script_path = Path(__file__).parent / "parse_brewfile.py" - output = run_command(f"python3 {script_path}") - if output: - try: - return json.loads(output) - except json.JSONDecodeError as e: - print(f"Error parsing Brewfile JSON: {e}", file=sys.stderr) - return {"formulae": {}, "casks": {}} - -def format_brewfile_packages(brewfile_data, package_type="formulae"): - """Format packages from Brewfile with categories and descriptions""" - packages = brewfile_data.get(package_type, {}) - - if not packages: - return f"*No {package_type} defined*" - - lines = [] - - for category, items in packages.items(): - if not items: - continue - - # Add category header - lines.append(f"\n**{category}**\n") - - for item in items: - name = item['name'] - description = item.get('description', '') - version = item.get('version', '') - - # Format the line - if version and version != 'unknown': - if version == 'HEAD': - line = f"- `{name}` (latest development version)" - else: - line = f"- `{name}` (v{version})" - else: - line = f"- `{name}`" - - # Add description if available - if description: - line += f" - {description}" - - lines.append(line) - - return "\n".join(lines) - -def update_readme(system_info, brewfile_data): - """Update README.md with environment information""" - template_path = Path(__file__).parent.parent / "README.template.md" - readme_path = Path(__file__).parent.parent / "README.md" - - if not template_path.exists(): - print(f"Template file not found: {template_path}", file=sys.stderr) - return False - - # Read template - with open(template_path, 'r') as f: - content = f.read() - - # Count total packages from Brewfile - formulae_count = sum(len(items) for items in brewfile_data.get('formulae', {}).values()) - casks_count = sum(len(items) for items in brewfile_data.get('casks', {}).values()) - - # Prepare replacement values - replacements = { - "{{OS_NAME}}": system_info['os'], - "{{OS_VERSION}}": system_info['version'], - "{{ARCH}}": system_info['arch'], - "{{UPDATED_AT}}": datetime.fromisoformat(system_info['updated_at'].replace('Z', '+00:00')).strftime('%Y-%m-%d %H:%M UTC'), - "{{FORMULAE_COUNT}}": str(formulae_count), - "{{FORMULAE_LIST}}": format_brewfile_packages(brewfile_data, "formulae"), - "{{CASKS_COUNT}}": str(casks_count), - "{{CASKS_LIST}}": format_brewfile_packages(brewfile_data, "casks") - } - - # Replace placeholders - for placeholder, value in replacements.items(): - content = content.replace(placeholder, value) - - # Write updated README - with open(readme_path, 'w') as f: - f.write(content) - - print(f"✅ README.md updated successfully") - print(f" - Environment: {system_info['os']} {system_info['version']} ({system_info['arch']})") - print(f" - {formulae_count} Homebrew formulae defined in .Brewfile") - print(f" - {casks_count} Homebrew casks defined in .Brewfile") - - return True - -def main(): - """Main function""" - print("📊 Getting system information...") - system_info = get_system_info() - - print("📦 Parsing .Brewfile...") - brewfile_data = parse_brewfile() - - print("📝 Updating README.md...") - if update_readme(system_info, brewfile_data): - sys.exit(0) - else: - sys.exit(1) - -if __name__ == "__main__": - main() \ No newline at end of file From 4aa31cfab47f3e8fb2ffa9672e5a51b4a6229c3e Mon Sep 17 00:00:00 2001 From: ryoya ito <30540303+ry-itto@users.noreply.github.com> Date: Fri, 1 May 2026 14:46:01 +0900 Subject: [PATCH 03/10] chore(dotfiles): switch to Ghostty and project-local runtimes --- README.md | 43 +++++++++++++++++-------- dot_Brewfile | 4 +-- dot_commit_template | 19 ----------- dot_config/ghostty/config | 63 +++++++++++++++++++++++++++++++++++++ dot_config/mise/config.toml | 7 ++--- dot_gitconfig | 2 -- dot_hammerspoon/init.lua | 20 +++++++++++- 7 files changed, 115 insertions(+), 43 deletions(-) delete mode 100644 dot_commit_template create mode 100644 dot_config/ghostty/config diff --git a/README.md b/README.md index 0999b19..2ee81bd 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ chezmoi init --apply ry-itto/dotfiles 3. Run `run_onchange_install-brew-packages.sh` to install Homebrew bundle from `~/.Brewfile` 4. Run `run_onchange_configure-macos-defaults.sh` and `run_onchange_configure-xcode.sh` to apply system defaults 5. Run `run_once_install-zplug.sh`, `run_once_install-dein.sh` to bootstrap shell/editor plugin managers -6. Run `run_once_install-mise-tools.sh` to install language runtimes (flutter, rust, node, ruby) defined in `dot_config/mise/config.toml` +6. Run `run_once_install-mise-tools.sh` to install any tools defined in `dot_config/mise/config.toml` (グローバルでは言語ランタイムを固定しない方針 — 詳細は [プログラミング言語の管理方針](#-プログラミング言語の管理方針)) ## 🔄 Daily Operations @@ -66,14 +66,14 @@ chezmoi add ~/.somefile │ └── bin/executable_reload # → ~/.zsh/bin/reload (chmod +x) ├── dot_gitconfig ├── dot_Brewfile -├── dot_commit_template ├── dot_vim/ ├── dot_hammerspoon/ ├── dot_claude/ # → ~/.claude/ ├── dot_config/ +│ ├── ghostty/config │ ├── nvim/ │ ├── starship.toml -│ └── mise/config.toml # mise tool definitions +│ └── mise/config.toml # mise settings ├── private_Library/ │ └── private_Application Support/Code/User/settings.json # → VSCode settings ├── run_onchange_install-brew-packages.sh.tmpl @@ -95,19 +95,14 @@ chezmoi add ~/.somefile - **Editors**: Neovim, VSCode - **Version Control**: Git, GitHub CLI -### Language Runtimes (managed by mise) +### Language Runtimes -Defined in `dot_config/mise/config.toml`: - -- Flutter -- Rust -- Node.js -- Ruby +[mise](https://mise.jdx.dev/) でプロジェクトごとに管理する。詳細は [プログラミング言語の管理方針](#-プログラミング言語の管理方針) を参照。 ### Other Stacks - **iOS Development**: Xcode, XcodeGen, xcbeautify -- **macOS Apps**: Raycast, Hammerspoon, Rectangle, Clipy +- **macOS Apps**: Ghostty, Raycast, Hammerspoon, Rectangle ## ⚙️ Configuration @@ -133,8 +128,30 @@ Vim setup is wired up via dein.vim. Plugin manifests live under `dot_vim/rc/`. 1. **Fork this repository** to create your own version 2. **Edit configurations** under `~/.local/share/chezmoi/` (or via `chezmoi edit`) 3. **Apply changes** with `chezmoi apply` -4. **Adjust runtime versions** in `dot_config/mise/config.toml` -5. **Modify packages** in `dot_Brewfile` +4. **Modify packages** in `dot_Brewfile` + +## 🧭 プログラミング言語の管理方針 + +この dotfiles では **プログラミング言語ランタイムの共通設定(グローバルバージョン)を持たない** 方針を採る。 + +### ルール + +- **プロジェクト側で指定されている場合**: そのプロジェクトの `mise.toml` / `.tool-versions` / `.node-version` / `.ruby-version` などに従い、mise(または各プロジェクト指定の方法)で導入する。 +- **その他、ローカルで一時的に必要になった場合**: `mise use -g @` などで都度グローバルに入れる。dotfiles 側にはコミットしない。 +- **dotfiles 管理下の `dot_config/mise/config.toml`**: 言語ランタイムのバージョンは記述しない。mise 自体の設定(例: `idiomatic_version_file_enable_tools`)に限る。 + +### 理由 + +共通設定でランタイムのバージョンを固定すると、 + +- マシンごと・プロジェクトごとのバージョン差異に追従するために dotfiles 側を頻繁に更新することになる +- プロジェクト側の指定とグローバル指定が衝突したときの優先順位の調整が面倒 + +になる。プロジェクト側の指定を常に優先することで、dotfiles を「環境の土台」だけに保つ。 + +### 例外: Homebrew 経由で入る言語 + +Homebrew のフォーミュラの依存関係として Python・Ruby などが入ってしまうケースは許容する。`brew bundle` の出力や `/opt/homebrew/Cellar` 配下に入るものは、ツールの動作に必要な副産物とみなす(プロジェクト用途では mise 側を優先する)。 ## 🤝 Contributing diff --git a/dot_Brewfile b/dot_Brewfile index c277462..4dafa46 100644 --- a/dot_Brewfile +++ b/dot_Brewfile @@ -25,11 +25,9 @@ brew 'tig' brew 'tree' brew 'nkf' brew 'git' -brew 'emojify' brew 'nvim' brew 'starship' brew 'mise' -brew 'act' # gPRC brew 'protobuf' @@ -42,7 +40,7 @@ brew 'autoconf' brew 'gmp' # Cask -cask 'clipy' +cask 'ghostty' cask 'raycast' cask 'font-hack-nerd-font' cask 'font-hackgen' diff --git a/dot_commit_template b/dot_commit_template deleted file mode 100644 index e379e49..0000000 --- a/dot_commit_template +++ /dev/null @@ -1,19 +0,0 @@ - -# ==================== Emojis ==================== -# 🎉 :tada: 初めてのコミット(Initial Commit) -# 🔖 :bookmark: バージョンタグ(Version Tag) -# ✨ :sparkles: 新機能(New Feature) -# 🐛 :bug: バグ修正(Bugfix) -# ♻️ :recycle: リファクタリング(Refactoring) -# 📚 :books: ドキュメント(Documentation) -# 🎨 :art: デザインUI/UX(Accessibility) -# 🐎 :horse: パフォーマンス(Performance) -# 🔧 :wrench: ツール(Tooling) -# 🚨 :rotating_light: テスト(Tests) -# 💩 :hankey: 非推奨追加(Deprecation) -# 🗑️ :wastebasket: 削除(Removal) -# 🚧 :construction: WIP(Work In Progress) - - -# ==================== Format ==================== -# :emoji: Subject diff --git a/dot_config/ghostty/config b/dot_config/ghostty/config new file mode 100644 index 0000000..8424da6 --- /dev/null +++ b/dot_config/ghostty/config @@ -0,0 +1,63 @@ +# Ghostty configuration +# Reference: https://ghostty.org/docs/config/reference +# 全オプションとデフォルト値は `ghostty +show-config --default --docs` で確認できる。 +# リロード: cmd+shift+, + +# ── Font ───────────────────────────────────────────── +font-family = "HackGen Console NF" +font-size = 14 +# font-feature = -liga # リガチャを切りたい場合は有効化 + +# ── Theme / Colors ─────────────────────────────────── +# システムの appearance に追従して light/dark を切替 +theme = light:rose-pine-dawn,dark:rose-pine +background-opacity = 0.95 +background-blur = true +minimum-contrast = 1.1 + +# ── Window / Padding ───────────────────────────────── +window-padding-x = 8 +window-padding-y = 6 +window-padding-balance = true +window-save-state = always +macos-titlebar-style = tabs + +# ── Cursor ─────────────────────────────────────────── +cursor-style = bar +cursor-style-blink = false +mouse-hide-while-typing = true + +# ── Shell integration ──────────────────────────────── +shell-integration = detect +shell-integration-features = cursor,sudo,title + +# ── Clipboard / Scroll ─────────────────────────────── +copy-on-select = clipboard +clipboard-trim-trailing-spaces = true +clipboard-paste-protection = true +scrollback-limit = 10000000 + +# ── macOS specific ─────────────────────────────────── +macos-option-as-alt = true +macos-non-native-fullscreen = visible-menu + +# ── Misc ───────────────────────────────────────────── +mouse-scroll-multiplier = 2 +confirm-close-surface = false +window-inherit-working-directory = true +quit-after-last-window-closed = true + +# ── Keybinds ───────────────────────────────────────── +# Split / Tab を tmux 不要レベルに整える +keybind = cmd+d=new_split:right +keybind = cmd+shift+d=new_split:down +keybind = cmd+w=close_surface +keybind = cmd+shift+enter=toggle_split_zoom +keybind = cmd+alt+left=goto_split:left +keybind = cmd+alt+right=goto_split:right +keybind = cmd+alt+up=goto_split:up +keybind = cmd+alt+down=goto_split:down +keybind = cmd+t=new_tab +keybind = cmd+shift+]=next_tab +keybind = cmd+shift+[=previous_tab +keybind = cmd+k=clear_screen diff --git a/dot_config/mise/config.toml b/dot_config/mise/config.toml index d482604..47ea4f7 100644 --- a/dot_config/mise/config.toml +++ b/dot_config/mise/config.toml @@ -1,5 +1,2 @@ -[tools] -flutter = "2.8.1" -rust = "stable" -node = "lts" -ruby = "3.3" +[settings] +idiomatic_version_file_enable_tools = ["ruby"] diff --git a/dot_gitconfig b/dot_gitconfig index 7fe11c0..4c4b208 100644 --- a/dot_gitconfig +++ b/dot_gitconfig @@ -1,5 +1,3 @@ -[commit] - template=~/.commit_template [user] email = 30540303+ry-itto@users.noreply.github.com name = ryoya ito diff --git a/dot_hammerspoon/init.lua b/dot_hammerspoon/init.lua index cbacce2..d9979cf 100644 --- a/dot_hammerspoon/init.lua +++ b/dot_hammerspoon/init.lua @@ -1,7 +1,25 @@ +-- Terminal App の表示/非表示を切り替える関数 +local open_terminal = function() + local appName = "Ghostty" + local app = hs.application.get(appName) + + if app == nil or app:isHidden() or not(app:isFrontmost()) then + -- アプリが起動していない、隠れている、または最前面でない場合は表示 + hs.application.launchOrFocus(appName) + else + -- アプリが最前面にある場合は隠す + app:hide() + end +end + +-- ホットキーの設定: Alt+Space (Option+Space) でTerminalの表示/非表示を切り替え +-- tmux.confのプレフィックスキー(Ctrl+q)と競合しないように設定 +hs.hotkey.bind({"alt"}, "space", open_terminal) + -- Hammerspoonの設定リロード用ホットキー: Cmd+Alt+Ctrl+R hs.hotkey.bind({"cmd", "alt", "ctrl"}, "R", function() hs.reload() end) -- 設定がリロードされた時の通知 -hs.alert.show("Hammerspoon config loaded") \ No newline at end of file +hs.alert.show("Hammerspoon config loaded") From f726c7178674812782b4dfd811da4008d0b233a3 Mon Sep 17 00:00:00 2001 From: ryoya ito <30540303+ry-itto@users.noreply.github.com> Date: Fri, 1 May 2026 14:58:03 +0900 Subject: [PATCH 04/10] ci: strengthen chezmoi verification --- .github/workflows/ci.yml | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4e823c7..0d84d53 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -56,22 +56,42 @@ jobs: - name: chezmoi doctor run: chezmoi --source="$GITHUB_WORKSPACE" doctor || true - - name: Apply to ephemeral HOME + - name: Apply to ephemeral HOME and verify rendered files run: | export HOME="$(mktemp -d)" export CI=1 + export XDG_CACHE_HOME="$HOME/.cache" chezmoi init --apply --source="$GITHUB_WORKSPACE" + test -f "$HOME/.zshrc" + test -f "$HOME/.config/mise/config.toml" + test -f "$HOME/.config/ghostty/config" + test -f "$HOME/.hammerspoon/init.lua" + test -f "$HOME/Library/Application Support/Code/User/settings.json" + test -x "$HOME/.zsh/bin/reload" + + grep -F 'idiomatic_version_file_enable_tools = ["ruby"]' "$HOME/.config/mise/config.toml" + grep -F 'appName = "Ghostty"' "$HOME/.hammerspoon/init.lua" + + chezmoi verify --source="$GITHUB_WORKSPACE" + - name: Idempotency check run: | export HOME="$(mktemp -d)" export CI=1 + export XDG_CACHE_HOME="$HOME/.cache" chezmoi init --apply --source="$GITHUB_WORKSPACE" - # Second apply should produce no changes chezmoi apply --source="$GITHUB_WORKSPACE" + status_output="$(chezmoi status --source="$GITHUB_WORKSPACE")" + if [ -n "$status_output" ]; then + echo "::error::chezmoi status is non-empty after re-apply" + echo "$status_output" + exit 1 + fi diff_output="$(chezmoi diff --source="$GITHUB_WORKSPACE")" if [ -n "$diff_output" ]; then echo "::error::chezmoi diff is non-empty after re-apply" echo "$diff_output" exit 1 fi + chezmoi verify --source="$GITHUB_WORKSPACE" From 269b849a193acee991bfed52c993e148db0e8526 Mon Sep 17 00:00:00 2001 From: ryoya ito <30540303+ry-itto@users.noreply.github.com> Date: Fri, 15 May 2026 15:44:34 +0900 Subject: [PATCH 05/10] fix dein install url --- run_once_install-dein.sh | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/run_once_install-dein.sh b/run_once_install-dein.sh index 8054b53..a9fc50e 100755 --- a/run_once_install-dein.sh +++ b/run_once_install-dein.sh @@ -12,7 +12,4 @@ fi tmp_dir=$(mktemp -d) trap 'rm -rf "$tmp_dir"' EXIT -curl -fsSL https://raw.githubusercontent.com/Shougo/dein.vim/master/bin/installer.sh > "$tmp_dir/installer.sh" -chmod u+x "$tmp_dir/installer.sh" - -"$tmp_dir/installer.sh" "$INSTALLATION_DIR" +sh -c "$(curl -fsSL https://raw.githubusercontent.com/Shougo/dein-installer.vim/master/installer.sh)" From bb50576344117407e1a26ff32eb9b78d8ba29d85 Mon Sep 17 00:00:00 2001 From: ryoya ito <30540303+ry-itto@users.noreply.github.com> Date: Fri, 15 May 2026 18:54:01 +0900 Subject: [PATCH 06/10] chore(dotfiles): remove unused serena configs and ghostty theme override Co-Authored-By: Claude Opus 4.7 (1M context) --- dot_claude/agents/serena-expert.md | 119 ------------------- dot_claude/commands/serena.md | 178 ----------------------------- dot_config/ghostty/config | 1 - 3 files changed, 298 deletions(-) delete mode 100644 dot_claude/agents/serena-expert.md delete mode 100644 dot_claude/commands/serena.md diff --git a/dot_claude/agents/serena-expert.md b/dot_claude/agents/serena-expert.md deleted file mode 100644 index 31a87a0..0000000 --- a/dot_claude/agents/serena-expert.md +++ /dev/null @@ -1,119 +0,0 @@ ---- -name: serena-expert -description: Elite app development agent that uses /serena command for token-efficient, structured problem-solving. Specializes in creating applications, implementing components, APIs, systems, and tests with maximum efficiency. Examples: Context: User needs to create a new React component. user: 'I need to implement a data table with sorting and filtering' assistant: 'I'll use /serena to efficiently design and implement this component with all features' Component creation benefits from /serena's structured approach for clean, maintainable code. Context: User is building a new API endpoint. user: 'Help me create a REST API for user management' assistant: 'Let me use /serena to architect this API with proper patterns and security' API development requires systematic design that /serena provides efficiently. -model: sonnet -color: blue ---- - -You are Claude Code's premier app development specialist, optimized for token-efficient development through strategic use of the /serena command. Your expertise spans full-stack development with a focus on practical, production-ready implementations. - -## Core Development Focus: -- **Component Development**: React/Vue/Angular components with proper state management -- **API Implementation**: RESTful/GraphQL endpoints with authentication and validation -- **System Architecture**: Scalable, maintainable application structures -- **Test Creation**: Comprehensive unit/integration/E2E test suites -- **Performance Optimization**: Efficient code that scales - -## Automatic /serena Usage Triggers: -Always use /serena for these development tasks to maximize token efficiency: - -### Component Development -- Creating new UI components (buttons, forms, modals, tables) -- Implementing complex state management -- Building reusable component libraries -- Integrating third-party UI libraries - -### API Development -- Designing RESTful or GraphQL endpoints -- Implementing authentication/authorization -- Database schema design and queries -- API versioning and documentation - -### System Implementation -- Setting up project architecture -- Implementing design patterns (MVC, Repository, Factory) -- Creating microservices or modular systems -- Building real-time features (WebSocket, SSE) - -### Testing -- Writing comprehensive test suites -- Creating test utilities and mocks -- Setting up E2E test scenarios -- Implementing CI/CD pipelines - -## Token Optimization Strategy: - -### 1. Template-Based Development -Use /serena with predefined patterns: -```bash -/serena "create [component/api/test] for [feature]" -q # Quick 3-5 thoughts -/serena "implement [feature] with [requirements]" -c # Code-focused -/serena "optimize [system] for [metric]" --summary # Summary only -``` - -### 2. Efficient Problem Analysis -- Start with minimal context gathering -- Use /serena's structured thinking to avoid redundant analysis -- Focus on implementation over theory -- Provide code-first solutions - -### 3. Smart Defaults -Automatically apply these patterns: -- **Components**: Functional with hooks, TypeScript, CSS modules -- **APIs**: Express/FastAPI, JWT auth, validation middleware -- **Tests**: Jest/Pytest, high coverage, meaningful assertions -- **Architecture**: Clean architecture, SOLID principles - -## Development Workflow: - -### Phase 1: Rapid Analysis (1-2 thoughts via /serena) -- Understand requirements -- Identify key technical decisions - -### Phase 2: Efficient Implementation (3-5 thoughts via /serena) -- Generate boilerplate code -- Implement core functionality -- Add error handling and validation - -### Phase 3: Quality Assurance (1-2 thoughts via /serena) -- Create relevant tests -- Add documentation -- Suggest optimization opportunities - -## Practical Examples: - -### Component Creation -``` -User: "Create a user profile card" -Action: /serena "implement UserProfileCard component with avatar, name, bio, and action buttons" -c -q -Result: Complete component with styling and basic tests in minimal tokens -``` - -### API Implementation -``` -User: "Need a product CRUD API" -Action: /serena "implement product CRUD API with validation and auth" -api --summary -Result: Full API implementation with routes, controllers, and models -``` - -### Full Feature -``` -User: "Build a comment system" -Action: /serena "implement comment system with nested replies" -full -Result: Frontend components + API + database schema + tests -``` - -## Quality Guarantees: -- Every implementation includes error handling -- All code follows established patterns and best practices -- Tests are included by default -- Security considerations are built-in -- Performance is optimized from the start - -## Special Capabilities: -- **Auto-detection**: Recognizes development tasks and uses /serena automatically -- **Context inheritance**: Remembers previous development decisions -- **Progressive enhancement**: Builds upon existing code efficiently -- **Framework expertise**: Deep knowledge of React, Next.js, Node.js, Python, etc. - -You excel at delivering production-ready code with minimal token usage by leveraging /serena's structured approach for all development tasks. Your responses are always practical, implementable, and focused on real-world application development. diff --git a/dot_claude/commands/serena.md b/dot_claude/commands/serena.md deleted file mode 100644 index 9d25073..0000000 --- a/dot_claude/commands/serena.md +++ /dev/null @@ -1,178 +0,0 @@ ---- -allowed-tools: Read, Glob, Grep, Edit, MultiEdit, Write, Bash, TodoWrite, mcp__serena__check_onboarding_performed, mcp__serena__delete_memory, mcp__serena__find_file, mcp__serena__find_referencing_symbols, mcp__serena__find_symbol, mcp__serena__get_symbols_overview, mcp__serena__insert_after_symbol, mcp__serena__insert_before_symbol, mcp__serena__list_dir, mcp__serena__list_memories, mcp__serena__onboarding, mcp__serena__read_memory, mcp__serena__remove_project, mcp__serena__replace_regex, mcp__serena__replace_symbol_body, mcp__serena__restart_language_server, mcp__serena__search_for_pattern, mcp__serena__switch_modes, mcp__serena__think_about_collected_information, mcp__serena__think_about_task_adherence, mcp__serena__think_about_whether_you_are_done, mcp__serena__write_memory, mcp__context7__resolve-library-id, mcp__context7__get-library-docs -description: Token-efficient Serena MCP command for structured app development and problem-solving ---- - -## Quick Reference - -```bash -/serena [options] # Basic usage -/serena debug "memory leak in prod" # Debug pattern (5-8 thoughts) -/serena design "auth system" # Design pattern (8-12 thoughts) -/serena review "optimize this code" # Review pattern (4-7 thoughts) -/serena implement "add feature X" # Implementation (6-10 thoughts) -``` - -## Options - -| Option | Description | Usage | Use Case | -|--------|-------------|-------|----------| -| `-q` | Quick mode (3-5 thoughts/steps) | `/serena "fix button" -q` | Simple bugs, minor features | -| `-d` | Deep mode (10-15 thoughts/steps) | `/serena "architecture design" -d` | Complex systems, major decisions | -| `-c` | Code-focused analysis | `/serena "optimize performance" -c` | Code review, refactoring | -| `-s` | Step-by-step implementation | `/serena "build dashboard" -s` | Full feature development | -| `-v` | Verbose output (show process) | `/serena "debug issue" -v` | Learning, understanding process | -| `-r` | Include research phase | `/serena "choose framework" -r` | Technology decisions | -| `-t` | Create implementation todos | `/serena "new feature" -t` | Project management | - -## Usage Patterns - -### Basic Usage -```bash -# Simple problem solving -/serena "fix login bug" - -# Quick feature implementation -/serena "add search filter" -q - -# Code optimization -/serena "improve load time" -c -``` - -### Advanced Usage -```bash -# Complex system design with research -/serena "design microservices architecture" -d -r -v - -# Full feature development with todos -/serena "implement user dashboard with charts" -s -t -c - -# Deep analysis with documentation -/serena "migrate to new framework" -d -r -v --focus=frontend -``` - -## Context (Auto-gathered) -- Project files: !`find . -maxdepth 2 -name "package.json" -o -name "*.config.*" | head -5 2>/dev/null || echo "No config files"` -- Git status: !`git status --porcelain 2>/dev/null | head -3 || echo "Not git repo"` - -## Core Workflow - -### 1. Problem Detection & Template Selection -Automatically select thinking pattern based on keywords: -- **Debug**: error, bug, issue, broken, failing → 5-8 thoughts -- **Design**: architecture, system, structure, plan → 8-12 thoughts -- **Implement**: build, create, add, feature → 6-10 thoughts -- **Optimize**: performance, slow, improve, refactor → 4-7 thoughts -- **Review**: analyze, check, evaluate → 4-7 thoughts - -### 2. MCP Selection & Execution -``` -App Development Tasks → Serena MCP -- Component implementation -- API development -- Feature building -- System architecture - -All Tasks → Serena MCP -- Component implementation -- API development -- Feature building -- System architecture -- Problem solving and analysis -``` - -### 3. Output Modes -- **Default**: Key insights + recommended actions -- **Verbose (-v)**: Show thinking process -- **Implementation (-s)**: Create todos + start execution - -## Problem-Specific Templates - -### Debug Pattern (5-8 thoughts) -1. Symptom analysis & reproduction -2. Error context & environment check -3. Root cause hypothesis generation -4. Evidence gathering & validation -5. Solution design & risk assessment -6. Implementation plan -7. Verification strategy -8. Prevention measures - -### Design Pattern (8-12 thoughts) -1. Requirements clarification -2. Constraints & assumptions -3. Stakeholder analysis -4. Architecture options generation -5. Option evaluation (pros/cons) -6. Technology selection -7. Design decisions & tradeoffs -8. Implementation phases -9. Risk mitigation -10. Success metrics -11. Validation plan -12. Documentation needs - -### Implementation Pattern (6-10 thoughts) -1. Feature specification & scope -2. Technical approach selection -3. Component/module design -4. Dependencies & integration points -5. Implementation sequence -6. Testing strategy -7. Edge case handling -8. Performance considerations -9. Error handling & recovery -10. Deployment & rollback plan - -### Review/Optimize Pattern (4-7 thoughts) -1. Current state analysis -2. Bottleneck identification -3. Improvement opportunities -4. Solution options & feasibility -5. Implementation priority -6. Performance impact estimation -7. Validation & monitoring plan - -## Advanced Options - -**Thought Control:** -- `--max-thoughts=N`: Override default thought count -- `--focus=AREA`: Domain-specific analysis (frontend, backend, database, security) -- `--token-budget=N`: Optimize for token limit - -**Integration:** -- `-r`: Include Context7 research phase -- `-t`: Create implementation todos -- `--context=FILES`: Analyze specific files first - -**Output:** -- `--summary`: Condensed output only -- `--json`: Structured output for automation -- `--progressive`: Show summary first, details on request - -## Task Execution - -You are an expert app developer and problem-solver primarily using Serena MCP. For each request: - -1. **Auto-detect problem type** and select appropriate approach -2. **Use Serena MCP**: - - **All development tasks**: Use Serena MCP tools (https://github.com/oraios/serena) - - **Analysis, debugging, implementation**: Use Serena's semantic code tools -3. **Execute structured approach** with chosen MCP -4. **Research relevant docs** with Context7 MCP if needed -5. **Synthesize actionable solution** with specific next steps -6. **Create implementation todos** if `-s` flag used - -**Key Guidelines:** -- **Primary**: Use Serena MCP tools for all tasks (components, APIs, features, analysis) -- **Leverage**: Serena's semantic code retrieval and editing capabilities -- Start with problem analysis, end with concrete actions -- Balance depth with token efficiency -- Always provide specific, actionable recommendations -- Consider security, performance, and maintainability - -**Token Efficiency Tips:** -- Use `-q` for simple problems (saves ~40% tokens) -- Use `--summary` for overview-only needs -- Combine related problems in single session -- Use `--focus` to avoid irrelevant analysis diff --git a/dot_config/ghostty/config b/dot_config/ghostty/config index 8424da6..8abcb7b 100644 --- a/dot_config/ghostty/config +++ b/dot_config/ghostty/config @@ -10,7 +10,6 @@ font-size = 14 # ── Theme / Colors ─────────────────────────────────── # システムの appearance に追従して light/dark を切替 -theme = light:rose-pine-dawn,dark:rose-pine background-opacity = 0.95 background-blur = true minimum-contrast = 1.1 From 5d816f90c814e7c0c6fcf0a1d04515482036cf7f Mon Sep 17 00:00:00 2001 From: ryoya ito <30540303+ry-itto@users.noreply.github.com> Date: Mon, 18 May 2026 11:00:37 +0900 Subject: [PATCH 07/10] chore(claude): fix invalid permission rules in settings.json Reported by `/doctor`: - TodoRead(): empty parens; use bare `TodoRead` - WebSearch(**): wildcards unsupported; use bare `WebSearch` - Bash(:(){ :|:& };:): unrepresentable in rule syntax (parens collide with the rule format), the rule was always skipped; removed. Co-Authored-By: Claude Opus 4.7 --- dot_claude/settings.json | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/dot_claude/settings.json b/dot_claude/settings.json index f98e1a1..e2694a6 100644 --- a/dot_claude/settings.json +++ b/dot_claude/settings.json @@ -10,15 +10,14 @@ "LS(**)", "MultiEdit(**)", "Read(**)", - "TodoRead()", + "TodoRead", "TodoWrite(**)", "WebFetch(domain:*)", - "WebSearch(**)", + "WebSearch", "Write(**)", "mcp__sequentialthinking__sequentialthinking" ], "deny": [ - "Bash(:(){ :|:& };:)", "Bash(> /dev/sda*)", "Bash(apt-get install *)", "Bash(brew install *)", From dcd5a9bbc024dd2e0fa7383d970bc0a159902c44 Mon Sep 17 00:00:00 2001 From: ryoya ito <30540303+ry-itto@users.noreply.github.com> Date: Mon, 18 May 2026 11:12:14 +0900 Subject: [PATCH 08/10] =?UTF-8?q?feat(zsh):=20switch=20wt=20=E2=86=92=20wt?= =?UTF-8?q?p=20and=20add=20gcloud=20SDK=20to=20PATH?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - env.zsh: replace `wt shell-init` / WT_WORKTREE_DIR with `wtp shell-init zsh`; prepend `~/Applications/google-cloud-sdk/bin` to PATH. - functions/functions.zsh: source the new wtp.zsh. - functions/wtp.zsh: add `wtp-cd` (fzf picker over `wtp list -q -c`). Co-Authored-By: Claude Opus 4.7 --- dot_zsh/env.zsh | 6 +++--- dot_zsh/functions/functions.zsh | 1 + dot_zsh/functions/wtp.zsh | 11 +++++++++++ 3 files changed, 15 insertions(+), 3 deletions(-) create mode 100644 dot_zsh/functions/wtp.zsh diff --git a/dot_zsh/env.zsh b/dot_zsh/env.zsh index 343c47a..a46e742 100644 --- a/dot_zsh/env.zsh +++ b/dot_zsh/env.zsh @@ -130,7 +130,7 @@ export ANDROID_SDK_ROOT=$HOME/Library/Android/sdk export N_PREFIX=$HOME/.n export PATH="$PATH:$N_PREFIX/bin" -eval "$(wt shell-init)" -export WT_WORKTREE_DIR=.worktree - eval "$(mise activate zsh)" +eval "$(wtp shell-init zsh)" + +export PATH="$HOME/Applications/google-cloud-sdk/bin:$PATH" diff --git a/dot_zsh/functions/functions.zsh b/dot_zsh/functions/functions.zsh index 64dc70a..30b1f1e 100644 --- a/dot_zsh/functions/functions.zsh +++ b/dot_zsh/functions/functions.zsh @@ -2,3 +2,4 @@ source $HOME/.zsh/functions/fzf-git.sh source $HOME/.zsh/functions/git.zsh source $HOME/.zsh/functions/github.zsh source $HOME/.zsh/functions/ghq.zsh +source $HOME/.zsh/functions/wtp.zsh diff --git a/dot_zsh/functions/wtp.zsh b/dot_zsh/functions/wtp.zsh new file mode 100644 index 0000000..fe70e35 --- /dev/null +++ b/dot_zsh/functions/wtp.zsh @@ -0,0 +1,11 @@ +wtp-cd() { + local dir="$(wtp list -q -c | awk '!/worktree|..\//' | fzf)" + if [ -z "$dir" ] + then + echo "no directories found for $1" + return 1 + fi + + wtp cd "$dir" + return +} From c6fa7e1e630be522f96a8e439e74d55d487eb885 Mon Sep 17 00:00:00 2001 From: ryoya ito <30540303+ry-itto@users.noreply.github.com> Date: Mon, 18 May 2026 11:17:48 +0900 Subject: [PATCH 09/10] ci: filter zsh scripts from shellcheck targets shellcheck does not support zsh (SC1071). All run_*.sh in this repo use `#!/bin/zsh`, and dot_zsh/functions/fzf-git.sh is vendored from junegunn/fzf-git.sh with zsh-specific syntax. Filter them out via shebang detection so shellcheck only runs over actual bash/sh files (currently none, so the step reports that and passes cleanly). Co-Authored-By: Claude Opus 4.7 --- .github/workflows/ci.yml | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0d84d53..3e180fe 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,11 +31,27 @@ jobs: chezmoi execute-template --source="$PWD" < "$tmpl" > "$out" done - # Lint all *.sh in repo (excluding .git) plus rendered templates - find . -type f -name "*.sh" -not -path "./.git/*" -print0 \ - | xargs -0 shellcheck - find "$rendered_dir" -type f -name "*.sh" -print0 \ - | xargs -0 -r shellcheck + # shellcheck does not support zsh; filter zsh-shebanged scripts and + # the vendored fzf-git.sh out of the target set. + targets=() + while IFS= read -r -d '' f; do + case "$f" in + */dot_zsh/functions/fzf-git.sh) continue ;; + esac + if head -n1 "$f" | grep -qE '^#!.*\bzsh\b'; then + continue + fi + targets+=("$f") + done < <( + find . -type f -name "*.sh" -not -path "./.git/*" -print0 + find "$rendered_dir" -type f -name "*.sh" -print0 + ) + + if [ ${#targets[@]} -gt 0 ]; then + shellcheck "${targets[@]}" + else + echo "No shellcheck-eligible scripts in repo (all .sh files are zsh)." + fi - name: Check zsh syntax run: | From 498d0f72a384bb46d961925662afea253aaa4d0a Mon Sep 17 00:00:00 2001 From: ryoya ito <30540303+ry-itto@users.noreply.github.com> Date: Mon, 18 May 2026 11:27:04 +0900 Subject: [PATCH 10/10] ci: install zsh on the Lint runner The Check zsh syntax step calls `zsh -n` but the Ubuntu runner does not ship zsh by default, so the step exited with "zsh: command not found". Install zsh alongside shellcheck in the setup step. Co-Authored-By: Claude Opus 4.7 --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3e180fe..1d03c1e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,10 +13,10 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Install shellcheck + - name: Install shellcheck and zsh run: | sudo apt-get update - sudo apt-get install -y shellcheck + sudo apt-get install -y shellcheck zsh - name: Install chezmoi run: sh -c "$(curl -fsLS get.chezmoi.io)" -- -b /usr/local/bin