diff --git a/.chezmoiroot b/.chezmoiroot new file mode 100644 index 0000000..73d74c2 --- /dev/null +++ b/.chezmoiroot @@ -0,0 +1 @@ +chezmoi diff --git a/.config/nixos/zsh/rc/functions/cx b/.config/nixos/zsh/rc/functions/cx deleted file mode 100644 index 2195f06..0000000 --- a/.config/nixos/zsh/rc/functions/cx +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env zsh -# 登録済みのアカウント名を最初の引数にすると、切り替えてから従来の cx を実行する。 - -emulate -L zsh - -local state_dir="${CLAUDEX_ACCOUNTS_DIR:-${XDG_STATE_HOME:-$HOME/.local/state}/claudex/accounts}" -local current_file="$state_dir/current" -local profile='' - -case "${1:-}" in - school | mitou) - profile="$1" - cx-account use "$profile" || return - shift - ;; - *) - if [[ -r "$current_file" ]]; then - profile=$(<"$current_file") - fi - case "$profile" in - school | mitou) ;; - *) - print -u2 'Usage: cx [school|mitou] [Claude Code の引数...]' - print -u2 '初回は cx-account login school または cx-account login mitou を実行してください。' - return 2 - ;; - esac - ;; -esac - -claudex run "$profile" -m opus -- --dangerously-skip-permissions "$@" diff --git a/.config/nixos/zsh/rc/functions/cx-account b/.config/nixos/zsh/rc/functions/cx-account deleted file mode 100644 index 65c95ca..0000000 --- a/.config/nixos/zsh/rc/functions/cx-account +++ /dev/null @@ -1,199 +0,0 @@ -#!/usr/bin/env zsh -# ChatGPT/Codex OAuth は Claudex の profile ごとではなく ~/.codex/auth.json に -# 保存される。その認証情報をアカウント名ごとに退避して、原子的に切り替える。 - -emulate -L zsh -setopt pipefail - -local command_name='cx-account' -local action="${1:-}" -local account="${2:-}" -local state_dir="${CLAUDEX_ACCOUNTS_DIR:-${XDG_STATE_HOME:-$HOME/.local/state}/claudex/accounts}" -local auth_file="${CLAUDEX_ACCOUNT_AUTH_FILE:-${CODEX_HOME:-$HOME/.codex}/auth.json}" -local current_file="$state_dir/current" - -function _cx_account_usage { - print -u2 "Usage: $command_name {login|use|list} [account] [--headless]" - print -u2 ' login [--headless] ブラウザで認証し、認証情報を保存する' - print -u2 ' use 保存済みアカウントへ切り替える' - print -u2 ' list 保存済みアカウントを表示する' -} - -function _cx_account_valid_name { - [[ "$1" =~ '^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$' ]] -} - -function _cx_account_prepare_state_dir { - mkdir -p -- "$state_dir" && chmod 700 -- "$state_dir" -} - -function _cx_account_save_auth { - local name="$1" - local source="$2" - local target="$state_dir/$name.json" - local temporary - - [[ -s "$source" ]] || return 1 - temporary=$(mktemp "$state_dir/.${name}.json.XXXXXX") || return 1 - if ! cp -- "$source" "$temporary" || ! chmod 600 -- "$temporary" || ! mv -f -- "$temporary" "$target"; then - rm -f -- "$temporary" - return 1 - fi -} - -function _cx_account_write_current { - local name="$1" - local temporary - - temporary=$(mktemp "$state_dir/.current.XXXXXX") || return 1 - if ! print -r -- "$name" >"$temporary" || ! chmod 600 -- "$temporary" || ! mv -f -- "$temporary" "$current_file"; then - rm -f -- "$temporary" - return 1 - fi -} - -function _cx_account_backup_current { - local current='' - local recovered_name - - [[ -s "$auth_file" ]] || return 0 - if [[ -r "$current_file" ]]; then - current=$(<"$current_file") - fi - - if _cx_account_valid_name "$current"; then - _cx_account_save_auth "$current" "$auth_file" - return - fi - - recovered_name="recovered-$(date +%Y%m%d-%H%M%S)" - _cx_account_save_auth "$recovered_name" "$auth_file" || return - print -u2 "$command_name: 現在の認証情報を $recovered_name として退避しました" -} - -case "$action" in - list) - if (( $# != 1 )); then - _cx_account_usage - return 2 - fi - - local file name current='' - local found=0 - [[ -r "$current_file" ]] && current=$(<"$current_file") - for file in "$state_dir"/*.json(N); do - name="${${file:t}%.json}" - if [[ "$name" == "$current" ]]; then - print -- "* $name" - else - print -- " $name" - fi - found=1 - done - (( found )) || print '保存済みアカウントはありません。cx-account login で追加してください。' - ;; - - use) - if (( $# != 2 )) || ! _cx_account_valid_name "$account"; then - _cx_account_usage - return 2 - fi - - local saved_auth="$state_dir/$account.json" - local temporary - if [[ ! -s "$saved_auth" ]]; then - print -u2 "$command_name: $account は未登録です。cx-account login $account を実行してください" - return 1 - fi - _cx_account_prepare_state_dir || return - _cx_account_backup_current || { - print -u2 "$command_name: 現在の認証情報を退避できないため切り替えません" - return 1 - } - mkdir -p -- "${auth_file:h}" || return - temporary=$(mktemp "${auth_file:h}/.auth.json.XXXXXX") || return - if ! cp -- "$saved_auth" "$temporary" || ! chmod 600 -- "$temporary" || ! mv -f -- "$temporary" "$auth_file"; then - rm -f -- "$temporary" - print -u2 "$command_name: 認証情報の切り替えに失敗しました" - return 1 - fi - if ! _cx_account_write_current "$account"; then - print -u2 "$command_name: 認証情報は切り替わりましたが、現在アカウントの記録に失敗しました" - return 1 - fi - print "ChatGPT アカウントを $account に切り替えました" - ;; - - login) - if (( $# != 2 && $# != 3 )) || ! _cx_account_valid_name "$account" || [[ "${3:-}" != '' && "${3:-}" != '--headless' ]]; then - _cx_account_usage - return 2 - fi - if ! command -v claudex >/dev/null 2>&1; then - print -u2 "$command_name: claudex が見つかりません" - return 127 - fi - _cx_account_prepare_state_dir || return - mkdir -p -- "${auth_file:h}" || return - local before_login='' - local before_auth_inode='' - if [[ -e "$auth_file" ]]; then - before_auth_inode=$(stat -c '%i' -- "$auth_file") || return - before_login=$(mktemp "${auth_file:h}/.auth.json.before-login.XXXXXX") || return - if ! cp -- "$auth_file" "$before_login" || ! chmod 600 -- "$before_login"; then - rm -f -- "$before_login" - return 1 - fi - _cx_account_backup_current || { - rm -f -- "$before_login" - print -u2 "$command_name: 現在の認証情報を退避できないためログインを開始しません" - return 1 - } - fi - - local -a login_args=(auth login chatgpt --profile "$account" --force) - [[ "${3:-}" == '--headless' ]] && login_args+=(--headless) - local login_status=0 - local auth_updated=0 - local after_auth_inode='' - claudex "${login_args[@]}" - login_status=$? - if [[ -s "$auth_file" ]]; then - after_auth_inode=$(stat -c '%i' -- "$auth_file") || return - if [[ -z "$before_login" ]] || ! cmp -s -- "$before_login" "$auth_file" || [[ "$before_auth_inode" != "$after_auth_inode" ]]; then - auth_updated=1 - fi - fi - if (( login_status != 0 && ! auth_updated )); then - if [[ -n "$before_login" ]]; then - mv -f -- "$before_login" "$auth_file" - fi - print -u2 "$command_name: ログインに失敗したため、以前の認証情報を復元しました" - return 1 - fi - if (( login_status != 0 )); then - print -u2 "$command_name: Claudex はエラー終了しましたが、認証情報が更新されているため続行します" - fi - if [[ ! -s "$auth_file" ]]; then - [[ -n "$before_login" ]] && mv -f -- "$before_login" "$auth_file" - print -u2 "$command_name: ログイン後の認証情報を確認できなかったため、以前の認証情報を復元しました" - return 1 - fi - if ! _cx_account_save_auth "$account" "$auth_file"; then - [[ -n "$before_login" ]] && mv -f -- "$before_login" "$auth_file" - print -u2 "$command_name: 認証情報の保存に失敗したため、以前の認証情報を復元しました" - return 1 - fi - rm -f -- "$before_login" - if ! _cx_account_write_current "$account"; then - print -u2 "$command_name: 認証情報は保存されましたが、現在アカウントの記録に失敗しました" - return 1 - fi - print "ChatGPT アカウント $account を保存しました" - ;; - - *) - _cx_account_usage - return 2 - ;; -esac diff --git a/.config/nixos/zsh/rc/tests/cx-account.test.zsh b/.config/nixos/zsh/rc/tests/cx-account.test.zsh deleted file mode 100644 index 2095881..0000000 --- a/.config/nixos/zsh/rc/tests/cx-account.test.zsh +++ /dev/null @@ -1,76 +0,0 @@ -#!/usr/bin/env zsh - -emulate -L zsh -setopt errexit nounset pipefail - -local root="${0:A:h:h}" -local temporary -temporary=$(mktemp -d) || exit 1 -trap 'rm -rf -- "$temporary"' EXIT - -export HOME="$temporary/home" -export XDG_STATE_HOME="$temporary/state" -export CLAUDEX_ACCOUNT_AUTH_FILE="$temporary/codex/auth.json" -mkdir -p "${CLAUDEX_ACCOUNT_AUTH_FILE:h}" - -fpath=("$root/functions" $fpath) -autoload -Uz cx cx-account - -function assert_file_contains { - [[ $(<"$2") == "$1" ]] -} - -function claudex { - print -r -- 'school-token' >"$CLAUDEX_ACCOUNT_AUTH_FILE" -} - -cx-account login school --headless >/dev/null -assert_file_contains 'school-token' "$XDG_STATE_HOME/claudex/accounts/school.json" -[[ $(stat -c '%a' "$XDG_STATE_HOME/claudex/accounts") == 700 ]] -[[ $(stat -c '%a' "$XDG_STATE_HOME/claudex/accounts/school.json") == 600 ]] - -print -r -- 'mitou-token' >"$XDG_STATE_HOME/claudex/accounts/mitou.json" -print -r -- 'school-token-updated' >"$CLAUDEX_ACCOUNT_AUTH_FILE" -cx-account use mitou >/dev/null -assert_file_contains 'mitou-token' "$CLAUDEX_ACCOUNT_AUTH_FILE" -assert_file_contains 'school-token-updated' "$XDG_STATE_HOME/claudex/accounts/school.json" - -print -r -- 'previous-token' >"$CLAUDEX_ACCOUNT_AUTH_FILE" -function claudex { return 1 } -if cx-account login school --headless >/dev/null 2>&1; then - print -u2 'cx-account login unexpectedly succeeded without an updated auth file' - exit 1 -fi -assert_file_contains 'previous-token' "$CLAUDEX_ACCOUNT_AUTH_FILE" - -function claudex { - local replacement - replacement=$(mktemp "${CLAUDEX_ACCOUNT_AUTH_FILE:h}/.auth.json.XXXXXX") - print -r -- 'previous-token' >"$replacement" - mv -- "$replacement" "$CLAUDEX_ACCOUNT_AUTH_FILE" - return 1 -} -cx-account login school --headless >/dev/null -assert_file_contains 'previous-token' "$XDG_STATE_HOME/claudex/accounts/school.json" - -function claudex { - print -r -- 'school-token-from-failed-keyring-save' >"$CLAUDEX_ACCOUNT_AUTH_FILE" - return 1 -} -cx-account login school --headless >/dev/null -assert_file_contains 'school-token-from-failed-keyring-save' "$CLAUDEX_ACCOUNT_AUTH_FILE" -assert_file_contains 'school-token-from-failed-keyring-save' "$XDG_STATE_HOME/claudex/accounts/school.json" - -typeset -ga claudex_args -function claudex { claudex_args=("$@") } -cx school 'continue from here' >/dev/null -[[ "${claudex_args[1]} ${claudex_args[2]} ${claudex_args[3]}" == 'run school -m' ]] -[[ "${claudex_args[-1]}" == 'continue from here' ]] - -rm -- "$XDG_STATE_HOME/claudex/accounts/current" -if cx >/dev/null 2>&1; then - print -u2 'cx without a selected account unexpectedly succeeded' - exit 1 -fi - -print 'cx-account tests passed' diff --git a/.config/shared/claude/sounds.mp3.bak b/.config/shared/claude/sounds.mp3.bak deleted file mode 100644 index 525c054..0000000 Binary files a/.config/shared/claude/sounds.mp3.bak and /dev/null differ diff --git a/.config/shared/claudex/config.toml b/.config/shared/claudex/config.toml deleted file mode 100644 index 36b39fd..0000000 --- a/.config/shared/claudex/config.toml +++ /dev/null @@ -1,27 +0,0 @@ -[[profiles]] -name = "school" -provider_type = "OpenAIResponses" -base_url = "https://chatgpt.com/backend-api/codex" -default_model = "gpt-5.6-terra" -reasoning_effort = "high" -auth_type = "oauth" -oauth_provider = "openai" - -[profiles.models] -haiku = "gpt-5.6-luna" -sonnet = "gpt-5.6-luna" -opus = "gpt-5.6-terra" - -[[profiles]] -name = "mitou" -provider_type = "OpenAIResponses" -base_url = "https://chatgpt.com/backend-api/codex" -default_model = "gpt-5.6-terra" -reasoning_effort = "high" -auth_type = "oauth" -oauth_provider = "openai" - -[profiles.models] -haiku = "gpt-5.6-luna" -sonnet = "gpt-5.6-luna" -opus = "gpt-5.6-terra" diff --git a/.config/shared/lazygit/LICENSE b/.config/shared/lazygit/LICENSE deleted file mode 100644 index 83121f5..0000000 --- a/.config/shared/lazygit/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2018 Jesse Duffield - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/.config/shared/lazygit/README.md b/.config/shared/lazygit/README.md deleted file mode 100644 index d840421..0000000 --- a/.config/shared/lazygit/README.md +++ /dev/null @@ -1,618 +0,0 @@ -
-Special thanks to: -
-
- -
- Warp -
- Warp, the intelligent terminal -
- Available for MacOS and Linux -
-
- Visit warp.dev to learn more. -
-
-
-
- -
- Tuple -
- Tuple, the premier screen sharing app for developers on macOS and Windows. -
-
-
-
- -
- Subble -
- I (Jesse) co-founded Subble to save your company time and money by finding unused and over-provisioned SaaS licences. Check it out! -
-
- -
-
- -

- -

- -
- -A simple terminal UI for git commands -
- -[![GitHub Releases](https://img.shields.io/github/downloads/jesseduffield/lazygit/total)](https://github.com/jesseduffield/lazygit/releases) [![Go Report Card](https://goreportcard.com/badge/github.com/jesseduffield/lazygit)](https://goreportcard.com/report/github.com/jesseduffield/lazygit) [![Codacy Badge](https://app.codacy.com/project/badge/Grade/f46416b715d74622895657935fcada21)](https://app.codacy.com/gh/jesseduffield/lazygit/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade) [![Codacy Badge](https://app.codacy.com/project/badge/Coverage/f46416b715d74622895657935fcada21)](https://app.codacy.com/gh/jesseduffield/lazygit/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_coverage) [![golangci-lint](https://img.shields.io/badge/linted%20by-golangci--lint-brightgreen)](https://golangci-lint.run/) [![GitHub tag](https://img.shields.io/github/v/tag/jesseduffield/lazygit?color=blue)](https://github.com/jesseduffield/lazygit/releases/latest) [![homebrew](https://img.shields.io/homebrew/v/lazygit?color=blue)](https://formulae.brew.sh/formula/lazygit) - -![commit_and_push](../assets/demo/commit_and_push-compressed.gif) - -
- -## Sponsors - -

- Maintenance of this project is made possible by all the contributors and sponsors. If you'd like to sponsor this project and have your avatar or company logo appear below click here. 💙 -

- -

-Mark LussierDean HerbertPeter BjorklundReilly WoodOliver GüntherPawan DhananjayCarsten GehlingChau TranmatejciktheAverageDev (Luca Tumedei)Nicholas CloudAliaksandr StelmachonakPedro PombeiroBurgy BenjaminJoe KlemmerTobias LütkeBen BeaumontHollyTom LanserCasey BoettcherJeff ForcierMaciej T. NowakJames HillyerdYuryOlivier 'reivilibre'Braden SteffaniakJordan GillardSebastianAndy SlezakMartin KockJesse AlamaDaniel KokottJan HeijmansKevin NowaldEthan LiRobert ForlerJan ZenknerFrederick MorlockMaximilian LangenfeldNeil LambertDavid Heinemeier HanssonEthan FischerTerry TaiAdam RoesnerTim MorganMax ShypulniakKovács ÁdámPatricio SerranoKiriJohn Even BjørnevikMichael OberstAdam TrepanierKenth FagerlundJulien TardotAaron ArredondoEllord TayagEdgar Post-BuijsPierre SpringZac ClayThomas MüllerCarl AssmannSergey OgnevMoody LiuMichael HowardLasse Bloch LauritsenLarry MarburgerDavid BrockmanAlexander SlavschikAidan GaulandMaksym BieńkowskiJimmy Sáenz RizoJoshua WootonnSimon Sandvik LeeThomas GilbertSzymon MuchaUnnawut LeepaisalsuwannaBret WortmanSimon CardonaAndré LameirinhasScott VelezjustinMayfieldSoma HolidaybizmythDessalinesSean Hong(홍성민)Alex DreymannFelipe OspinaRiccardo Novagliarxz -

- -## Elevator Pitch - -Rant time: You've heard it before, git is _powerful_, but what good is that power when everything is so damn hard to do? Interactive rebasing requires you to edit a goddamn TODO file in your editor? _Are you kidding me?_ To stage part of a file you need to use a command line program to step through each hunk and if a hunk can't be split down any further but contains code you don't want to stage, you have to edit an arcane patch file _by hand_? _Are you KIDDING me?!_ Sometimes you get asked to stash your changes when switching branches only to realise that after you switch and unstash that there weren't even any conflicts and it would have been fine to just checkout the branch directly? _YOU HAVE GOT TO BE KIDDING ME!_ - -If you're a mere mortal like me and you're tired of hearing how powerful git is when in your daily life it's a powerful pain in your ass, lazygit might be for you. - -## Table of contents - -- [Sponsors](#sponsors) -- [Elevator Pitch](#elevator-pitch) -- [Table of contents](#table-of-contents) -- [Features](#features) - - [Stage individual lines](#stage-individual-lines) - - [Interactive Rebase](#interactive-rebase) - - [Cherry-pick](#cherry-pick) - - [Bisect](#bisect) - - [Nuke the working tree](#nuke-the-working-tree) - - [Amend an old commit](#amend-an-old-commit) - - [Filter](#filter) - - [Invoke a custom command](#invoke-a-custom-command) - - [Worktrees](#worktrees) - - [Rebase magic (custom patches)](#rebase-magic-custom-patches) - - [Rebase from marked base commit](#rebase-from-marked-base-commit) - - [Undo](#undo) - - [Commit graph](#commit-graph) - - [Compare two commits](#compare-two-commits) -- [Tutorials](#tutorials) -- [Installation](#installation) - - [Binary Releases](#binary-releases) - - [Dev container](#dev-container-feature) - - [Homebrew](#homebrew) - - [MacPorts](#macports) - - [Void Linux](#void-linux) - - [Scoop (Windows)](#scoop-windows) - - [gah (Linux and Mac OS)](#gah-linux-and-mac-os) - - [Arch Linux](#arch-linux) - - [Fedora / Amazon Linux 2023 / CentOS Stream](#fedora--amazon-linux-2023--centos-stream) - - [Solus Linux](#solus-linux) - - [Debian and Ubuntu](#debian-and-ubuntu) - - [Funtoo Linux](#funtoo-linux) - - [Gentoo Linux](#gentoo-linux) - - [openSUSE](#opensuse) - - [NixOS](#nixos) - - [Flox](#flox) - - [FreeBSD](#freebsd) - - [Termux](#termux) - - [Conda](#conda) - - [Go](#go) - - [Chocolatey (Windows)](#chocolatey-windows) - - [Winget (Windows 10 1709 or later)](#winget-windows-10-1709-or-later) - - [Manual](#manual) -- [Usage](#usage) - - [Keybindings](#keybindings) - - [Changing Directory On Exit](#changing-directory-on-exit) - - [Undo/Redo](#undoredo) -- [Configuration](#configuration) - - [Custom Pagers](#custom-pagers) - - [Custom Commands](#custom-commands) - - [Git flow support](#git-flow-support) -- [Contributing](#contributing) - - [Debugging Locally](#debugging-locally) -- [Donate](#donate) -- [FAQ](#faq) - - [What do the commit colors represent?](#what-do-the-commit-colors-represent) -- [Shameless Plug](#shameless-plug) -- [Alternatives](#alternatives) - -Lazygit is not my fulltime job but it is a hefty part time job so if you want to support the project please consider [sponsoring me](https://github.com/sponsors/jesseduffield) - -## Features - -### Stage individual lines - -Press space on the selected line to stage it, or press `v` to start selecting a range of lines. You can also press `a` to select the entirety of the current hunk. - -![stage_lines](../assets/demo/stage_lines-compressed.gif) - -### Interactive Rebase - -Press `i` to start an interactive rebase. Then squash (`s`), fixup (`f`), drop (`d`), edit (`e`), move up (`ctrl+k`) or move down (`ctrl+j`) any of TODO commits, before continuing the rebase by bringing up the rebase options menu with `m` and then selecting `continue`. - -You can also perform any these actions as a once-off (e.g. pressing `s` on a commit to squash it) without explicitly starting a rebase. - -This demo also uses shift+down to select a range of commits to move and fixup. - -![interactive_rebase](../assets/demo/interactive_rebase-compressed.gif) - -### Cherry-pick - -Press `shift+c` on a commit to copy it and press `shift+v` to paste (cherry-pick) it. - -![cherry_pick](../assets/demo/cherry_pick-compressed.gif) - -### Bisect - -Press `b` in the commits view to mark a commit as good/bad in order to begin a git bisect. - -![bisect](../assets/demo/bisect-compressed.gif) - -### Nuke the working tree - -For when you really want to just get rid of anything that shows up when you run `git status` (and yes that includes dirty submodules) [kidpix style](https://www.youtube.com/watch?v=N4E2B_k2Bss), press `shift+d` to bring up the reset options menu and then select the 'nuke' option. - -![Nuke working tree](../assets/demo/nuke_working_tree-compressed.gif) - -### Amend an old commit - -Pressing `shift+a` on any commit will amend that commit with the currently staged changes (running an interactive rebase in the background). - -![amend_old_commit](../assets/demo/amend_old_commit-compressed.gif) - -### Filter - -You can filter a view with `/`. Here we filter down our branches view and then hit `enter` to view its commits. - -![filter](../assets/demo/filter-compressed.gif) - -### Invoke a custom command - -Lazygit has a very flexible [custom command system](docs/Custom_Command_Keybindings.md). In this example a custom command is defined which emulates the built-in branch checkout action. - -![custom_command](../assets/demo/custom_command-compressed.gif) - -### Worktrees - -You can create worktrees to have multiple branches going at once without the need for stashing or creating WIP commits when switching between them. Press `w` in the branches view to create a worktree from the selected branch and switch to it. - -![worktree_create_from_branches](../assets/demo/worktree_create_from_branches-compressed.gif) - -### Rebase magic (custom patches) - -You can build a custom patch from an old commit and then remove the patch from the commit, split out a new commit, apply the patch in reverse to the index, and more. - -In this example we have a redundant comment that we want to remove from an old commit. We hit `` on the commit to view its files, then `` on a file to focus the patch, then `` to add the comment line to our custom patch, and then `ctrl+p` to view the custom patch options; selecting to remove the patch from the current commit. - -Learn more in the [Rebase magic Youtube tutorial](https://youtu.be/4XaToVut_hs). - -![custom_patch](../assets/demo/custom_patch-compressed.gif) - -### Rebase from marked base commit - -Say you're on a feature branch that was itself branched off of the develop branch, and you've decided you'd rather be branching off the master branch. You need a way to rebase only the commits from your feature branch. In this demo we check to see which was the last commit on the develop branch, then press `shift+b` to mark that commit as our base commit, then press `r` on the master branch to rebase onto it, only bringing across the commits from our feature branch. Then we push our changes with `shift+p`. - -![rebase_onto](../assets/demo/rebase_onto-compressed.gif) - -### Undo - -You can undo the last action by pressing `z` and redo with `ctrl+z`. Here we drop a couple of commits and then undo the actions. -Undo uses the reflog which is specific to commits and branches so we can't undo changes to the working tree or stash. - -[More info](/docs/Undoing.md) - -![undo](../assets/demo/undo-compressed.gif) - -### Commit graph - -When viewing the commit graph in an enlarged window (use `+` and `_` to cycle screen modes), the commit graph is shown. Colours correspond to the commit authors, and as you navigate down the graph, the parent commits of the selected commit are highlighted. - -![commit_graph](../assets/demo/commit_graph-compressed.gif) - -### Compare two commits - -If you press `shift+w` on a commit (or branch/ref) a menu will open that allows you to mark that commit so that any other commit you select will be diffed against it. Once you've selected the second commit, you'll see the diff in the main view and if you press `` you'll see the files of the diff. You can press `shift+w` to view the diff menu again to see options like reversing the diff direction or exiting diff mode. You can also exit diff mode by pressing ``. - -![diff_commits](../assets/demo/diff_commits-compressed.gif) - -## Tutorials - -[](https://youtu.be/CPLdltN7wgE) - -- [15 Lazygit Features in 15 Minutes](https://youtu.be/CPLdltN7wgE) -- [Basics Tutorial](https://youtu.be/VDXvbHZYeKY) -- [Rebase Magic Tutorial](https://youtu.be/4XaToVut_hs) - -## Installation - -[![Packaging status](https://repology.org/badge/vertical-allrepos/lazygit.svg?columns=3)](https://repology.org/project/lazygit/versions) - -_Most of the above packages are maintained by third parties so be sure to vet them yourself and confirm that the maintainer is a trustworthy looking person who attends local sports games and gives back to their communities with barbeque fundraisers etc_ - -### Binary Releases - -For Windows, Mac OS(10.12+) or Linux, you can download a binary release [here](../../releases). - -### Dev container feature - -If you want to use lazygit in e.g. one of your GitHub Codespaces, there is a third-party [dev container feature](https://github.com/GeorgOfenbeck/features/tree/main/src/lazygit-linuxbinary) based on the binary releases mentioned above. - -### Homebrew - -It works with Linux, too. - -```sh -brew install lazygit -``` - -### MacPorts - -Latest version built from github releases. -Tap: - -``` -sudo port install lazygit -``` - -### Void Linux - -Packages for Void Linux are available in the distro repo - -They follow upstream latest releases - -```sh -sudo xbps-install -S lazygit -``` - -### Scoop (Windows) - -You can install `lazygit` using [scoop](https://scoop.sh/). It's in the `extras` bucket: - -```sh -# Add the extras bucket -scoop bucket add extras - -# Install lazygit -scoop install lazygit -``` - -### gah (Linux and Mac OS) - -You can install `lazygit` using [gah](https://github.com/marverix/gah/): - -```sh -gah install lazygit -``` - -### Arch Linux - -Packages for Arch Linux are available via pacman and AUR (Arch User Repository). - -There are two packages. The stable one which is built with the latest release -and the git version which builds from the most recent commit. - -- Stable: `sudo pacman -S lazygit` -- Development: - -Instruction of how to install AUR content can be found here: - - -### Fedora / Amazon Linux 2023 / CentOS Stream - -Packages for Fedora, Amazon Linux 2023 and CentOS Stream are available via -[Copr](https://copr.fedorainfracloud.org/coprs/dejan/lazygit/) (Cool Other Package Repo). - -```sh -sudo dnf copr enable dejan/lazygit -sudo dnf install lazygit -``` - -These packages are built using the RPM spec file located here: https://codeberg.org/dejan/rpm-lazygit - -You should be able to build RPMs for Fedora 41 or older, and other Fedora derivatives using the -SRPM (Source RPM) file that you can grab from the latest COPR build. - -### Solus Linux - -```sh -sudo eopkg install lazygit -``` - -### Debian and Ubuntu - -For **Debian 13 "Trixie", Sid**, and later, or **Ubuntu 25.10 "Questing Quokka"** and later: - -```sh -sudo apt install lazygit -``` - -For **Debian 12 "Bookworm", Ubuntu 25.04 "Plucky Puffin"** and earlier: - -```sh -LAZYGIT_VERSION=$(curl -s "https://api.github.com/repos/jesseduffield/lazygit/releases/latest" | \grep -Po '"tag_name": *"v\K[^"]*') -curl -Lo lazygit.tar.gz "https://github.com/jesseduffield/lazygit/releases/download/v${LAZYGIT_VERSION}/lazygit_${LAZYGIT_VERSION}_Linux_x86_64.tar.gz" -tar xf lazygit.tar.gz lazygit -sudo install lazygit -D -t /usr/local/bin/ -``` - -Verify the correct installation of lazygit: - -```sh -lazygit --version -``` - -### Funtoo Linux - -Funtoo Linux has an autogenerated lazygit package in [dev-kit](https://github.com/funtoo/dev-kit/tree/1.4-release/dev-vcs/lazygit): - -```sh -sudo emerge dev-vcs/lazygit -``` - -### Gentoo Linux - -Lazygit is not (yet) in main Gentoo portage, however an ebuild is available in [GURU overlay](https://github.com/gentoo-mirror/guru/tree/master/dev-vcs/lazygit) - -You can either add the overlay to your system and install lazygit as usual: - -```sh -sudo eselect repository enable guru -sudo emaint sync -r guru -sudo emerge dev-vcs/lazygit -``` - -### openSUSE - -The lazygit package is currently built in [devel:languages:go/lazygit](https://build.opensuse.org/package/show/devel:languages:go/lazygit). - -To install lazygit on openSUSE Tumbleweed run: - -```sh -sudo zypper ar https://download.opensuse.org/repositories/devel:/languages:/go/openSUSE_Factory/devel:languages:go.repo -sudo zypper ref && sudo zypper in lazygit -``` - -To install lazygit on openSUSE Leap run: - -```sh -source /etc/os-release -sudo zypper ar https://download.opensuse.org/repositories/devel:/languages:/go/$VERSION_ID/devel:languages:go.repo -sudo zypper ref && sudo zypper in lazygit -``` - -### NixOS - -#### Using lazygit from nixpkgs - -On NixOS, lazygit is packaged with nix and distributed via nixpkgs. -You can try lazygit without installing it with: - -```sh -nix-shell -p lazygit -# or with flakes enabled -nix run nixpkgs#lazygit -``` -Or you can add lazygit to your `configuration.nix` using the `environment.systemPackages` option. -More details can be found via NixOS search [page](https://search.nixos.org/). - -#### Using the official lazygit flake - -This repository includes a nix flake that provides the latest development version and additional development tools: - -**Run lazygit directly from the repository:** -```sh -nix run github:jesseduffield/lazygit -# or from a local clone -nix run . -``` - -**Build lazygit from source:** -```sh -nix build github:jesseduffield/lazygit -# or from a local clone -nix build . -``` - -**Development environment:** -For contributors, the flake provides a development shell with Go toolchain, development tools, and dependencies: -```sh -nix develop github:jesseduffield/lazygit -# or from a local clone -nix develop -``` - -The development shell includes: -- Go toolchain -- git and make -- Proper environment variables for development - -**Using in other flakes:** -The flake also provides an overlay for easy integration into other flake-based projects: -```nix -{ - inputs.lazygit.url = "github:jesseduffield/lazygit"; - - outputs = { self, nixpkgs, lazygit }: { - # Use the overlay - nixpkgs.overlays = [ lazygit.overlays.default ]; - }; -} -``` - -### Flox - -Lazygit can be installed into a Flox environment as follows. - -```sh -flox install lazygit -``` - -More details about Flox can be found on [their website](https://flox.dev/). - -### FreeBSD - -```sh -pkg install lazygit -``` - -### Termux - -```sh -apt install lazygit -``` - -### Conda - -Released versions are available for different platforms, see - -```sh -conda install -c conda-forge lazygit -``` - -### Go - -```sh -go install github.com/jesseduffield/lazygit@latest -``` - -Please note: -If you get an error claiming that lazygit cannot be found or is not defined, you -may need to add `~/go/bin` to your $PATH (MacOS/Linux), or `%HOME%\go\bin` -(Windows). Not to be mistaken for `C:\Go\bin` (which is for Go's own binaries, -not apps like lazygit). - -### Chocolatey (Windows) - -You can install `lazygit` using [Chocolatey](https://chocolatey.org/): - -```sh -choco install lazygit -``` - -### Winget (Windows 10 1709 or later) - -You can install `lazygit` using the `winget` command in the Windows Terminal with the following command: - -```powershell -winget install -e --id=JesseDuffield.lazygit -``` - -### Manual - -You'll need to [install Go](https://golang.org/doc/install) - -``` -git clone https://github.com/jesseduffield/lazygit.git -cd lazygit -go install -``` - -You can also use `go run main.go` to compile and run in one go (pun definitely intended) - -## Usage - -Call `lazygit` in your terminal inside a git repository. - -```sh -$ lazygit -``` - -If you want, you can -also add an alias for this with `echo "alias lg='lazygit'" >> ~/.zshrc` (or -whichever rc file you're using). - -### Keybindings - -You can check out the list of keybindings [here](/docs/keybindings). - -### Changing Directory On Exit - -If you change repos in lazygit and want your shell to change directory into that repo on exiting lazygit, add this to your `~/.zshrc` (or other rc file): - -``` -lg() -{ - export LAZYGIT_NEW_DIR_FILE=~/.lazygit/newdir - - lazygit "$@" - - if [ -f $LAZYGIT_NEW_DIR_FILE ]; then - cd "$(cat $LAZYGIT_NEW_DIR_FILE)" - rm -f $LAZYGIT_NEW_DIR_FILE > /dev/null - fi -} -``` - -Then `source ~/.zshrc` and from now on when you call `lg` and exit you'll switch directories to whatever you were in inside lazygit. To override this behaviour you can exit using `shift+Q` rather than just `q`. - -### Undo/Redo - -See the [docs](/docs/Undoing.md) - -## Configuration - -Check out the [configuration docs](docs/Config.md). - -### Custom Pagers - -See the [docs](docs/Custom_Pagers.md) - -### Custom Commands - -If lazygit is missing a feature, there's a good chance you can implement it yourself with a custom command! - -See the [docs](docs/Custom_Command_Keybindings.md) - -### Git flow support - -Lazygit supports [Gitflow](https://github.com/nvie/gitflow) if you have it installed. To understand how the Gitflow model works check out Vincent Driessen's original [post](https://nvie.com/posts/a-successful-git-branching-model/) explaining it. To view Gitflow options from within Lazygit, press `i` from within the branches view. - -## Contributing - -We love your input! Please check out the [contributing guide](CONTRIBUTING.md). -For contributor discussion about things not better discussed here in the repo, join the [discord channel](https://discord.gg/ehwFt2t4wt) - - - -Check out this [video](https://www.youtube.com/watch?v=kNavnhzZHtk) walking through the creation of a small feature in lazygit if you want an idea of where to get started. - -### Debugging Locally - -Run `lazygit --debug` in one terminal tab and `lazygit --logs` in another to view the program and its log output side by side - -## Donate - -If you would like to support the development of lazygit, consider [sponsoring me](https://github.com/sponsors/jesseduffield) (github is matching all donations dollar-for-dollar for 12 months) - -## FAQ - -### What do the commit colors represent? - -- Green: the commit is included in the master branch -- Yellow: the commit is not included in the master branch -- Red: the commit has not been pushed to the upstream branch - -## Shameless Plug - -If you want to see what I (Jesse) am up to in terms of development, follow me on -[twitter](https://twitter.com/DuffieldJesse) or check out my [blog](https://jesseduffield.com/) - -## Alternatives - -If you find that lazygit doesn't quite satisfy your requirements, these may be a better fit: - -- [GitUI](https://github.com/Extrawurst/gitui) -- [tig](https://github.com/jonas/tig) -- [GitArbor TUI](https://github.com/cadamsdev/gitarbor-tui) diff --git a/.config/shared/lazygit/lazygit.exe b/.config/shared/lazygit/lazygit.exe deleted file mode 100644 index aaec929..0000000 Binary files a/.config/shared/lazygit/lazygit.exe and /dev/null differ diff --git a/.config/windows/komorebi/applications.json b/.config/windows/komorebi/applications.json deleted file mode 100644 index c7168f4..0000000 --- a/.config/windows/komorebi/applications.json +++ /dev/null @@ -1,3272 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/LGUG2Z/komorebi/master/schema.asc.json", - "1Password": { - "ignore": [ - { - "kind": "Exe", - "id": "1Password.exe", - "matching_strategy": "Equals" - } - ] - }, - "Ableton Live": { - "ignore": [ - { - "kind": "Class", - "id": "AbletonVstPlugClass", - "matching_strategy": "Legacy" - }, - { - "kind": "Class", - "id": "Vst3PlugWindow", - "matching_strategy": "Legacy" - }, - [ - { - "kind": "Class", - "id": "Ableton Live Window Class", - "matching_strategy": "Equals" - }, - { - "kind": "Title", - "id": "Ableton", - "matching_strategy": "DoesNotContain" - } - ] - ] - }, - "Adobe Creative Cloud": { - "tray_and_multi_window": [ - { - "kind": "Class", - "id": "CreativeCloudDesktopWindowClass", - "matching_strategy": "Legacy" - } - ] - }, - "Adobe Photoshop": { - "ignore": [ - { - "kind": "Class", - "id": "PSDialogBox", - "matching_strategy": "Equals" - } - ] - }, - "Adobe Premiere Pro": { - "ignore": [ - { - "kind": "Class", - "id": "DroverLord - Window Class", - "matching_strategy": "Equals" - } - ] - }, - "Affinity Designer 2": { - "ignore": [ - { - "kind": "Exe", - "id": "Designer.exe", - "matching_strategy": "Equals" - } - ], - "manage": [ - { - "kind": "Title", - "id": "Affinity Designer 2", - "matching_strategy": "Equals" - } - ] - }, - "Affinity Photo 2": { - "ignore": [ - { - "kind": "Exe", - "id": "Photo.exe", - "matching_strategy": "Equals" - } - ], - "manage": [ - { - "kind": "Title", - "id": "Affinity Photo 2", - "matching_strategy": "Equals" - } - ] - }, - "Affinity Publisher 2": { - "ignore": [ - { - "kind": "Exe", - "id": "Publisher.exe", - "matching_strategy": "Equals" - } - ], - "manage": [ - { - "kind": "Title", - "id": "Affinity Publisher 2", - "matching_strategy": "Equals" - } - ] - }, - "Akiflow": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "Akiflow.exe", - "matching_strategy": "Equals" - } - ] - }, - "Amazon Chime": { - "ignore": [ - { - "kind": "Title", - "id": "Meeting Controls", - "matching_strategy": "EndsWith" - } - ] - }, - "Android Studio": { - "object_name_change": [ - { - "kind": "Exe", - "id": "studio64.exe", - "matching_strategy": "Equals" - } - ] - }, - "Anki": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "anki.exe", - "matching_strategy": "Equals" - } - ] - }, - "ApplicationFrameHost": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "ApplicationFrameHost.exe", - "matching_strategy": "Equals" - } - ] - }, - "Arc Browser": { - "ignore": [ - { - "kind": "Title", - "id": "Arc picture in picture", - "matching_strategy": "Equals" - }, - { - "kind": "Title", - "id": "Arc extension popup", - "matching_strategy": "Equals" - } - ] - }, - "ArmCord": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "ArmCord.exe", - "matching_strategy": "Equals" - } - ] - }, - "AutoDesk AutoCAD Suite": { - "ignore": [ - [ - { - "kind": "Class", - "id": "Afx:", - "matching_strategy": "Contains" - }, - { - "kind": "Exe", - "id": "acad.exe", - "matching_strategy": "Equals" - } - ], - [ - { - "kind": "Class", - "id": "HwndWrapper[DefaultDomain", - "matching_strategy": "StartsWith" - }, - { - "kind": "Exe", - "id": "acad.exe", - "matching_strategy": "Equals" - } - ], - [ - { - "kind": "Class", - "id": "WindowsForms10.Window", - "matching_strategy": "StartsWith" - }, - { - "kind": "Exe", - "id": "acad.exe", - "matching_strategy": "Equals" - } - ] - ] - }, - "AutoHotkey": { - "ignore": [ - { - "kind": "Title", - "id": "Window Spy", - "matching_strategy": "StartsWith" - }, - { - "kind": "Exe", - "id": "AutoHotkeyUX.exe", - "matching_strategy": "Equals" - } - ], - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "AutoHotkeyU64.exe", - "matching_strategy": "Equals" - } - ] - }, - "Ayugram": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "ayugram.exe", - "matching_strategy": "Equals" - } - ] - }, - "Balabolka": { - "ignore": [ - [ - { - "kind": "Exe", - "id": "balabolka.exe", - "matching_strategy": "Equals" - }, - { - "kind": "Class", - "id": "TBalabolkaForm", - "matching_strategy": "DoesNotEqual" - } - ] - ] - }, - "Barrier": { - "floating": [ - { - "kind": "Exe", - "id": "barrier.exe", - "matching_strategy": "Equals" - } - ] - }, - "Battlestate Games Launcher": { - "floating": [ - { - "kind": "Exe", - "id": "BsgLauncher.exe", - "matching_strategy": "Equals" - } - ] - }, - "Beeper": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "Beeper.exe", - "matching_strategy": "Equals" - } - ] - }, - "Bitwarden": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "Bitwarden.exe", - "matching_strategy": "Equals" - } - ] - }, - "Blender": { - "floating": [ - [ - { - "kind": "Exe", - "id": "blender.exe", - "matching_strategy": "Equals" - }, - { - "kind": "Title", - "id": "Blender", - "matching_strategy": "DoesNotContain" - } - ] - ], - "slow_application": [ - { - "kind": "Exe", - "id": "blender.exe", - "matching_strategy": "Equals" - } - ] - }, - "Blitz": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "Blitz.exe", - "matching_strategy": "Equals" - } - ] - }, - "Bloxstrap": { - "ignore": [ - { - "kind": "Exe", - "id": "Bloxstrap.exe", - "matching_strategy": "Equals" - } - ] - }, - "Brave Browser": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "brave.exe", - "matching_strategy": "Equals" - } - ] - }, - "Browser Tamer": { - "ignore": [ - { - "kind": "Exe", - "id": "bt.exe", - "matching_strategy": "Equals" - } - ] - }, - "Calculator": { - "ignore": [ - { - "kind": "Title", - "id": "Calculator", - "matching_strategy": "Equals" - } - ] - }, - "Citrix Receiver": { - "ignore": [ - { - "kind": "Exe", - "id": "SelfService.exe", - "matching_strategy": "Equals" - } - ], - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "SelfService.exe", - "matching_strategy": "Equals" - } - ] - }, - "Clash Verge": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "Clash Verge.exe", - "matching_strategy": "Equals" - } - ] - }, - "Clementine": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "clementine.exe", - "matching_strategy": "Equals" - } - ] - }, - "CLion": { - "ignore": [ - { - "kind": "Class", - "id": "SunAwtDialog", - "matching_strategy": "Equals" - } - ], - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "clion64.exe", - "matching_strategy": "Equals" - } - ], - "object_name_change": [ - { - "kind": "Exe", - "id": "clion64.exe", - "matching_strategy": "Equals" - } - ] - }, - "Clumsy": { - "floating": [ - { - "kind": "Exe", - "id": "clumsy.exe", - "matching_strategy": "Equals" - } - ] - }, - "CopyQ": { - "ignore": [ - { - "kind": "Exe", - "id": "copyq.exe", - "matching_strategy": "Equals" - } - ] - }, - "Core Temp": { - "ignore": [ - { - "kind": "Exe", - "id": "Core Temp.exe", - "matching_strategy": "Equals" - } - ] - }, - "Credential Manager UI Host": { - "ignore": [ - { - "kind": "Exe", - "id": "CredentialUIBroker.exe", - "matching_strategy": "Equals" - } - ] - }, - "Cron": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "Cron.exe", - "matching_strategy": "Equals" - } - ] - }, - "DataGrip": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "datagrip64.exe", - "matching_strategy": "Equals" - } - ], - "object_name_change": [ - { - "kind": "Exe", - "id": "datagrip64.exe", - "matching_strategy": "Equals" - } - ] - }, - "Dell Display Manager": { - "ignore": [ - { - "kind": "Exe", - "id": "DDM.exe", - "matching_strategy": "Equals" - } - ] - }, - "Delphi applications": { - "ignore": [ - { - "kind": "Class", - "id": "TApplication", - "matching_strategy": "Legacy" - }, - { - "kind": "Class", - "id": "TWizardForm", - "matching_strategy": "Legacy" - } - ] - }, - "DesktopMate": { - "ignore": [ - { - "kind": "Exe", - "id": "DesktopMate.exe", - "matching_strategy": "Equals" - } - ] - }, - "Discord": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "Discord.exe", - "matching_strategy": "Equals" - } - ], - "layered": [ - { - "kind": "Exe", - "id": "Discord.exe", - "matching_strategy": "Equals" - } - ] - }, - "DiscordCanary": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "DiscordCanary.exe", - "matching_strategy": "Equals" - } - ], - "layered": [ - { - "kind": "Exe", - "id": "DiscordCanary.exe", - "matching_strategy": "Equals" - } - ] - }, - "DiscordDevelopment": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "DiscordDevelopment.exe", - "matching_strategy": "Equals" - } - ], - "layered": [ - { - "kind": "Exe", - "id": "DiscordDevelopment.exe", - "matching_strategy": "Equals" - } - ] - }, - "DiscordPTB": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "DiscordPTB.exe", - "matching_strategy": "Equals" - } - ], - "layered": [ - { - "kind": "Exe", - "id": "DiscordPTB.exe", - "matching_strategy": "Equals" - } - ] - }, - "Dropbox": { - "ignore": [ - { - "kind": "Exe", - "id": "Dropbox.exe", - "matching_strategy": "Equals" - } - ] - }, - "DS4Windows": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "DS4Windows.exe", - "matching_strategy": "Equals" - } - ] - }, - "EA Desktop": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "EADesktop.exe", - "matching_strategy": "Equals" - } - ] - }, - "Eagle": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "Eagle.exe", - "matching_strategy": "Equals" - } - ] - }, - "Eclipse SWT": { - "object_name_change": [ - { - "kind": "Class", - "id": "SWT_Window", - "matching_strategy": "StartsWith" - } - ] - }, - "ElectronMail": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "ElectronMail.exe", - "matching_strategy": "Equals" - } - ] - }, - "Electrum": { - "ignore": [ - { - "kind": "Title", - "id": "Create/Restore wallet", - "matching_strategy": "Equals" - } - ] - }, - "Element": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "Element.exe", - "matching_strategy": "Equals" - } - ] - }, - "Elephicon": { - "ignore": [ - { - "kind": "Exe", - "id": "Elephicon.exe", - "matching_strategy": "Equals" - } - ] - }, - "ElevenClock": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "ElevenClock.exe", - "matching_strategy": "Equals" - } - ] - }, - "Elgato Camera Hub": { - "ignore": [ - { - "kind": "Exe", - "id": "Camera Hub.exe", - "matching_strategy": "Equals" - } - ] - }, - "Elgato Control Center": { - "ignore": [ - { - "kind": "Exe", - "id": "ControlCenter.exe", - "matching_strategy": "Equals" - } - ] - }, - "Elgato Wave Link": { - "ignore": [ - { - "kind": "Exe", - "id": "WaveLink.exe", - "matching_strategy": "Equals" - } - ] - }, - "Epic Games Launcher": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "EpicGamesLauncher.exe", - "matching_strategy": "Equals" - } - ] - }, - "Everything": { - "tray_and_multi_window": [ - { - "kind": "Class", - "id": "EVERYTHING", - "matching_strategy": "Legacy" - } - ] - }, - "Everything1.5a": { - "manage": [ - { - "kind": "Class", - "id": "EVERYTHING_(1.5a)", - "matching_strategy": "Legacy" - } - ], - "tray_and_multi_window": [ - { - "kind": "Class", - "id": "EVERYTHING_(1.5a)", - "matching_strategy": "Legacy" - } - ] - }, - "f.lux": { - "ignore": [ - { - "kind": "Exe", - "id": "flux.exe", - "matching_strategy": "Equals" - } - ], - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "flux.exe", - "matching_strategy": "Equals" - } - ] - }, - "FFMetrics": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "FFMetrics.exe", - "matching_strategy": "Equals" - } - ] - }, - "Files": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "Files.exe", - "matching_strategy": "Equals" - } - ] - }, - "Fork": { - "ignore": [ - [ - { - "kind": "Exe", - "id": "Fork.exe", - "matching_strategy": "Equals" - }, - { - "kind": "Title", - "id": "Fork -", - "matching_strategy": "DoesNotStartWith" - } - ] - ] - }, - "FreeCAD": { - "floating": [ - [ - { - "kind": "Exe", - "id": "freecad.exe", - "matching_strategy": "Equals" - }, - { - "kind": "Class", - "id": "Qt51515QWindowIcon", - "matching_strategy": "Equals" - } - ] - ] - }, - "FreeTube": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "FreeTube.exe", - "matching_strategy": "Equals" - } - ], - "ignore": [ - [ - { - "kind": "Exe", - "id": "FreeTube.exe", - "matching_strategy": "Equals" - }, - { - "kind": "Title", - "id": "Picture in picture", - "matching_strategy": "Equals" - } - ] - ] - }, - "GIMP": { - "floating": [ - [ - { - "kind": "Exe", - "id": "gimp", - "matching_strategy": "StartsWith" - }, - { - "kind": "Title", - "id": "GNU", - "matching_strategy": "DoesNotContain" - }, - { - "kind": "Title", - "id": "GIMP", - "matching_strategy": "DoesNotEndWith" - } - ], - [ - { - "kind": "Exe", - "id": "gimp", - "matching_strategy": "StartsWith" - }, - { - "kind": "Title", - "id": "About GIMP", - "matching_strategy": "Equals" - } - ] - ] - }, - "GitHub Credential Manager": { - "ignore": [ - { - "kind": "Exe", - "id": "git-credential-manager.exe", - "matching_strategy": "Equals" - } - ] - }, - "Godot Engine": { - "object_name_change": [ - { - "kind": "Exe", - "id": "Godot_v", - "matching_strategy": "StartsWith" - } - ] - }, - "Godot Manager": { - "manage": [ - { - "kind": "Exe", - "id": "GodotManager.exe", - "matching_strategy": "Equals" - } - ], - "object_name_change": [ - { - "kind": "Exe", - "id": "GodotManager.exe", - "matching_strategy": "Equals" - } - ] - }, - "GOG Galaxy": { - "ignore": [ - { - "kind": "Class", - "id": "Chrome_RenderWidgetHostHWND", - "matching_strategy": "Legacy" - } - ], - "manage": [ - { - "kind": "Exe", - "id": "GalaxyClient.exe", - "matching_strategy": "Equals" - } - ], - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "GalaxyClient.exe", - "matching_strategy": "Equals" - } - ] - }, - "GoLand": { - "ignore": [ - { - "kind": "Class", - "id": "SunAwtDialog", - "matching_strategy": "Equals" - } - ], - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "goland64.exe", - "matching_strategy": "Equals" - } - ], - "object_name_change": [ - { - "kind": "Exe", - "id": "goland64.exe", - "matching_strategy": "Equals" - } - ] - }, - "Golden Dict": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "GoldenDict.exe", - "matching_strategy": "Equals" - } - ] - }, - "Google Chrome": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "chrome.exe", - "matching_strategy": "Equals" - } - ] - }, - "Google Drive": { - "ignore": [ - { - "kind": "Exe", - "id": "GoogleDriveFS.exe", - "matching_strategy": "Equals" - } - ], - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "GoogleDriveFS.exe", - "matching_strategy": "Equals" - } - ] - }, - "Google Earth Pro": { - "ignore": [ - [ - { - "kind": "Class", - "id": "Qt5QWindowToolSaveBits", - "matching_strategy": "Equals" - }, - { - "kind": "Exe", - "id": "googleearth.exe", - "matching_strategy": "Equals" - } - ], - [ - { - "kind": "Class", - "id": "Qt5QWindowIcon", - "matching_strategy": "Equals" - }, - { - "kind": "Title", - "id": "Google Earth Pro", - "matching_strategy": "DoesNotEqual" - }, - { - "kind": "Exe", - "id": "googleearth.exe", - "matching_strategy": "Equals" - } - ] - ] - }, - "GoPro Webcam": { - "tray_and_multi_window": [ - { - "kind": "Class", - "id": "GoPro Webcam", - "matching_strategy": "Legacy" - } - ] - }, - "Grayjay": { - "manage": [ - [ - { - "kind": "Exe", - "id": "dotcefnative.exe", - "matching_strategy": "Equals" - }, - { - "kind": "Title", - "id": "Grayjay", - "matching_strategy": "Equals" - } - ], - [ - { - "kind": "Exe", - "id": "dotcefnative.exe", - "matching_strategy": "Equals" - }, - { - "kind": "Title", - "id": "Grayjay (Sub)", - "matching_strategy": "Equals" - } - ] - ] - }, - "Guitar Rig 7": { - "ignore": [ - { - "kind": "Exe", - "id": "Guitar Rig 7.exe", - "matching_strategy": "Equals" - } - ] - }, - "Hammer": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "hammer.exe", - "matching_strategy": "Equals" - } - ], - "ignore": [ - [ - { - "kind": "Exe", - "id": "hammer.exe", - "matching_strategy": "Equals" - }, - { - "kind": "Class", - "id": "Afx:", - "matching_strategy": "StartsWith" - } - ] - ], - "slow_application": [ - { - "kind": "Exe", - "id": "hammer.exe", - "matching_strategy": "Equals" - } - ] - }, - "Honkai Star Rail": { - "manage": [ - { - "kind": "Exe", - "id": "StarRail.Exe", - "matching_strategy": "Equals" - } - ] - }, - "HWiNFO64": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "HWiNFO64.EXE", - "matching_strategy": "Equals" - } - ] - }, - "HxD": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "HxD.exe", - "matching_strategy": "Equals" - } - ], - "ignore": [ - [ - { - "kind": "Exe", - "id": "HxD.exe", - "matching_strategy": "Equals" - }, - { - "kind": "Class", - "id": "TFormHexView", - "matching_strategy": "Equals" - } - ] - ] - }, - "IDA": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "ida.exe", - "matching_strategy": "Equals" - }, - { - "kind": "Exe", - "id": "ida64.exe", - "matching_strategy": "Equals" - } - ], - "floating": [ - [ - { - "kind": "Exe", - "id": "ida.exe", - "matching_strategy": "Equals" - }, - { - "kind": "Title", - "id": "IDA -", - "matching_strategy": "DoesNotStartWith" - }, - { - "kind": "Title", - "id": "IDA v", - "matching_strategy": "DoesNotStartWith" - } - ], - [ - { - "kind": "Exe", - "id": "ida64.exe", - "matching_strategy": "Equals" - }, - { - "kind": "Title", - "id": "IDA -", - "matching_strategy": "DoesNotStartWith" - }, - { - "kind": "Title", - "id": "IDA v", - "matching_strategy": "DoesNotStartWith" - } - ] - ] - }, - "IntelliJ IDEA": { - "ignore": [ - { - "kind": "Class", - "id": "SunAwtDialog", - "matching_strategy": "Equals" - } - ], - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "idea64.exe", - "matching_strategy": "Equals" - } - ], - "object_name_change": [ - { - "kind": "Exe", - "id": "idea64.exe", - "matching_strategy": "Equals" - } - ] - }, - "Itch.io": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "itch.exe", - "matching_strategy": "Equals" - } - ] - }, - "JavaFX": { - "object_name_change": [ - { - "kind": "Class", - "id": "GlassWndClass-GlassWindowClass", - "matching_strategy": "StartsWith" - } - ] - }, - "JetBrains Client": { - "ignore": [ - { - "kind": "Class", - "id": "SunAwtDialog", - "matching_strategy": "Equals" - } - ], - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "jetbrains_client64.exe", - "matching_strategy": "Equals" - } - ], - "object_name_change": [ - { - "kind": "Exe", - "id": "jetbrains_client64.exe", - "matching_strategy": "Equals" - } - ] - }, - "Keyviz": { - "ignore": [ - { - "kind": "Exe", - "id": "keyviz.exe", - "matching_strategy": "Equals" - } - ] - }, - "Kleopatra": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "kleopatra.exe", - "matching_strategy": "Equals" - } - ] - }, - "komorebi-bar": { - "ignore": [ - { - "kind": "Exe", - "id": "komorebi-bar.exe", - "matching_strategy": "Equals" - } - ] - }, - "komorebi-gui": { - "ignore": [ - { - "kind": "Exe", - "id": "komorebi-gui.exe", - "matching_strategy": "Equals" - } - ] - }, - "KOOK": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "KOOK.exe", - "matching_strategy": "Equals" - } - ] - }, - "Kotatogram": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "Kotatogram.exe", - "matching_strategy": "Equals" - } - ] - }, - "Lens": { - "ignore": [ - [ - { - "kind": "Exe", - "id": "Lens.exe", - "matching_strategy": "Equals" - }, - { - "kind": "Title", - "id": "Loading", - "matching_strategy": "Equals" - } - ] - ] - }, - "Libre Hardware Monitor": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "LibreHardwareMonitor.exe", - "matching_strategy": "Equals" - } - ] - }, - "LibreCAD": { - "ignore": [ - [ - { - "kind": "Title", - "id": "LibreCAD", - "matching_strategy": "DoesNotStartWith" - }, - { - "kind": "Exe", - "id": "LibreCAD.exe", - "matching_strategy": "Equals" - } - ] - ] - }, - "LibreOffice": { - "object_name_change": [ - { - "kind": "Exe", - "id": "soffice.bin", - "matching_strategy": "Equals" - } - ] - }, - "Line": { - "floating": [ - { - "kind": "Exe", - "id": "LineMediaPlayer.exe", - "matching_strategy": "Equals" - } - ] - }, - "LocalSend": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "localsend_app.exe", - "matching_strategy": "Equals" - } - ] - }, - "Logi Bolt": { - "ignore": [ - { - "kind": "Exe", - "id": "LogiBolt.exe", - "matching_strategy": "Equals" - } - ] - }, - "Logitech G HUB": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "lghub.exe", - "matching_strategy": "Equals" - } - ] - }, - "Logitech Options": { - "ignore": [ - { - "kind": "Exe", - "id": "LogiOptionsUI.exe", - "matching_strategy": "Equals" - } - ] - }, - "LogiTune": { - "ignore": [ - { - "kind": "Exe", - "id": "LogiTune.exe", - "matching_strategy": "Equals" - } - ], - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "LogiTune.exe", - "matching_strategy": "Equals" - } - ] - }, - "MacType": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "MacTray.exe", - "matching_strategy": "Equals" - } - ] - }, - "Mailspring": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "mailspring.exe", - "matching_strategy": "Equals" - } - ] - }, - "ManicTime": { - "manage": [ - { - "kind": "Exe", - "id": "ManicTimeClient.exe", - "matching_strategy": "Equals" - } - ], - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "ManicTimeClient.exe", - "matching_strategy": "Equals" - } - ], - "object_name_change": [ - { - "kind": "Exe", - "id": "ManicTimeClient.exe", - "matching_strategy": "Equals" - } - ] - }, - "ManyCam": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "ManyCam.exe", - "matching_strategy": "Equals" - } - ] - }, - "Mattermost": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "Mattermost.exe", - "matching_strategy": "Equals" - } - ] - }, - "MaxxAudioPro": { - "ignore": [ - [ - { - "kind": "Exe", - "id": "ApplicationFrameHost.exe", - "matching_strategy": "Equals" - }, - { - "kind": "Title", - "id": "MaxxAudioPro", - "matching_strategy": "Equals" - } - ] - ] - }, - "MicMute": { - "floating": [ - { - "kind": "Exe", - "id": "MicMute.exe", - "matching_strategy": "Equals" - } - ] - }, - "Microsoft Active Accessibility": { - "ignore": [ - { - "kind": "Class", - "id": "#32770", - "matching_strategy": "Legacy" - } - ] - }, - "Microsoft Edge": { - "ignore": [ - [ - { - "kind": "Exe", - "id": "msedge.exe", - "matching_strategy": "Equals" - }, - { - "kind": "Class", - "id": "Chrome_WidgetWin_2", - "matching_strategy": "Equals" - } - ] - ] - }, - "Microsoft Excel": { - "ignore": [ - { - "kind": "Class", - "id": "_WwB", - "matching_strategy": "Legacy" - } - ], - "layered": [ - { - "kind": "Exe", - "id": "EXCEL.EXE", - "matching_strategy": "Equals" - } - ] - }, - "Microsoft IME Pad": { - "floating": [ - { - "kind": "Exe", - "id": "IMEPADSV.EXE", - "matching_strategy": "Equals" - } - ] - }, - "Microsoft Outlook": { - "ignore": [ - { - "kind": "Class", - "id": "_WwB", - "matching_strategy": "Legacy" - }, - { - "kind": "Class", - "id": "MsoSplash", - "matching_strategy": "Equals" - } - ], - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "OUTLOOK.EXE", - "matching_strategy": "Equals" - } - ], - "layered": [ - { - "kind": "Exe", - "id": "OUTLOOK.EXE", - "matching_strategy": "Equals" - } - ] - }, - "Microsoft PC Manager": { - "ignore": [ - { - "kind": "Exe", - "id": "MSPCManager.exe", - "matching_strategy": "Equals" - } - ] - }, - "Microsoft PowerPoint": { - "ignore": [ - { - "kind": "Class", - "id": "_WwB", - "matching_strategy": "Legacy" - } - ], - "layered": [ - { - "kind": "Exe", - "id": "POWERPNT.EXE", - "matching_strategy": "Equals" - } - ] - }, - "Microsoft SQL Server Management Studio": { - "floating": [ - [ - { - "kind": "Exe", - "id": "Ssms.exe", - "matching_strategy": "Equals" - }, - { - "kind": "Class", - "id": "WindowsForms10.Window.8.app", - "matching_strategy": "StartsWith" - } - ] - ] - }, - "Microsoft Teams": { - "tray_and_multi_window": [ - { - "kind": "Class", - "id": "TeamsWebView", - "matching_strategy": "Equals" - } - ] - }, - "Microsoft Teams classic": { - "ignore": [ - { - "kind": "Title", - "id": "Microsoft Teams Notification", - "matching_strategy": "Legacy" - }, - { - "kind": "Title", - "id": "Microsoft Teams Call", - "matching_strategy": "Legacy" - } - ] - }, - "Microsoft Terminal Services Client": { - "ignore": [ - { - "kind": "Class", - "id": "OPContainerClass", - "matching_strategy": "Equals" - }, - { - "kind": "Class", - "id": "IHWindowClass", - "matching_strategy": "Equals" - } - ] - }, - "Microsoft Word": { - "ignore": [ - { - "kind": "Class", - "id": "_WwB", - "matching_strategy": "Legacy" - } - ], - "layered": [ - { - "kind": "Exe", - "id": "WINWORD.EXE", - "matching_strategy": "Equals" - } - ], - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "WINWORD.exe", - "matching_strategy": "Equals" - } - ] - }, - "MobaXterm": { - "manage": [ - [ - { - "kind": "Exe", - "id": "MobaXterm.exe", - "matching_strategy": "Equals" - }, - { - "kind": "Class", - "id": "TMobaXtermForm", - "matching_strategy": "Equals" - } - ] - ] - }, - "Mod Organizer 2": { - "ignore": [ - [ - { - "kind": "Exe", - "id": "ModOrganizer.exe", - "matching_strategy": "Equals" - }, - { - "kind": "Title", - "id": "Extracting files", - "matching_strategy": "Equals" - } - ] - ] - }, - "Modern Flyouts": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "ModernFlyoutsHost.exe", - "matching_strategy": "Equals" - } - ] - }, - "MOTU M-Series": { - "floating": [ - { - "kind": "Exe", - "id": "MOTUMSeries.exe", - "matching_strategy": "Equals" - } - ] - }, - "Mozilla Firefox": { - "ignore": [ - { - "kind": "Class", - "id": "MozillaDialogClass", - "matching_strategy": "Equals" - }, - { - "kind": "Class", - "id": "MozillaTaskbarPreviewClass", - "matching_strategy": "Legacy" - }, - [ - { - "kind": "Title", - "id": "Picture-in-Picture", - "matching_strategy": "Equals" - }, - { - "kind": "Exe", - "id": "firefox.exe", - "matching_strategy": "Equals" - } - ] - ], - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "firefox.exe", - "matching_strategy": "Equals" - } - ], - "object_name_change": [ - { - "kind": "Exe", - "id": "firefox.exe", - "matching_strategy": "Equals" - } - ], - "slow_application": [ - { - "kind": "Exe", - "id": "firefox.exe", - "matching_strategy": "Equals" - } - ] - }, - "mpv": { - "object_name_change": [ - { - "kind": "Class", - "id": "mpv", - "matching_strategy": "Legacy" - } - ] - }, - "mpv.net": { - "object_name_change": [ - { - "kind": "Exe", - "id": "mpvnet.exe", - "matching_strategy": "Equals" - } - ] - }, - "NetEase Cloud Music": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "cloudmusic.exe", - "matching_strategy": "Equals" - } - ] - }, - "NiceHash Miner": { - "manage": [ - { - "kind": "Exe", - "id": "nhm_app.exe", - "matching_strategy": "Equals" - } - ] - }, - "NohBoard": { - "ignore": [ - { - "kind": "Exe", - "id": "NohBoard.exe", - "matching_strategy": "Equals" - } - ] - }, - "Notion": { - "ignore": [ - { - "kind": "Title", - "id": "Notion - Command Search", - "matching_strategy": "Equals" - } - ], - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "Notion.exe", - "matching_strategy": "Equals" - } - ] - }, - "Notion Calendar": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "Notion Calendar.exe", - "matching_strategy": "Equals" - } - ] - }, - "Notion Enhanced": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "Notion Enhanced.exe", - "matching_strategy": "Equals" - } - ] - }, - "NZXT CAM": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "NZXT CAM.exe", - "matching_strategy": "Equals" - } - ] - }, - "OBS Studio (32-bit)": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "obs32.exe", - "matching_strategy": "Equals" - } - ] - }, - "OBS Studio (64-bit)": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "obs64.exe", - "matching_strategy": "Equals" - } - ] - }, - "OneDrive": { - "ignore": [ - { - "kind": "Class", - "id": "OneDriveReactNativeWin32WindowClass", - "matching_strategy": "Legacy" - } - ] - }, - "OneQuick": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "OneQuick.exe", - "matching_strategy": "Equals" - } - ] - }, - "ONLYOFFICE Editors": { - "tray_and_multi_window": [ - { - "kind": "Class", - "id": "DocEditorsWindowClass", - "matching_strategy": "Legacy" - } - ] - }, - "OpenRGB": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "OpenRGB.exe", - "matching_strategy": "Equals" - } - ] - }, - "paint.net": { - "ignore": [ - { - "kind": "Exe", - "id": "paintdotnet.exe", - "matching_strategy": "Equals" - } - ] - }, - "Paradox Launcher": { - "ignore": [ - { - "kind": "Exe", - "id": "Paradox Launcher.exe", - "matching_strategy": "Equals" - } - ] - }, - "PAYDAY 2": { - "ignore": [ - { - "kind": "Exe", - "id": "payday2_win32_release.exe", - "matching_strategy": "Equals" - } - ] - }, - "PhpStorm": { - "ignore": [ - { - "kind": "Class", - "id": "SunAwtDialog", - "matching_strategy": "Equals" - } - ], - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "phpstorm64.exe", - "matching_strategy": "Equals" - } - ], - "object_name_change": [ - { - "kind": "Exe", - "id": "phpstorm64.exe", - "matching_strategy": "Equals" - } - ] - }, - "pinentry": { - "ignore": [ - { - "kind": "Exe", - "id": "pinentry.exe", - "matching_strategy": "Equals" - } - ] - }, - "Playnite": { - "ignore": [ - { - "kind": "Exe", - "id": "Playnite.FullscreenApp.exe", - "matching_strategy": "Equals" - } - ], - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "Playnite.DesktopApp.exe", - "matching_strategy": "Equals" - } - ] - }, - "PowerToys": { - "ignore": [ - { - "kind": "Exe", - "id": "PowerToys.ColorPickerUI.exe", - "matching_strategy": "Equals" - }, - { - "kind": "Exe", - "id": "PowerToys.CropAndLock.exe", - "matching_strategy": "Equals" - }, - { - "kind": "Exe", - "id": "PowerToys.ImageResizer.exe", - "matching_strategy": "Equals" - }, - { - "kind": "Exe", - "id": "PowerToys.Peek.UI.exe", - "matching_strategy": "Equals" - }, - { - "kind": "Exe", - "id": "PowerToys.PowerLauncher.exe", - "matching_strategy": "Equals" - }, - { - "kind": "Exe", - "id": "PowerToys.PowerAccent.exe", - "matching_strategy": "Equals" - }, - { - "kind": "Exe", - "id": "PowerToys.AdvancedPaste.exe", - "matching_strategy": "Equals" - }, - { - "kind": "Exe", - "id": "PowerToys.FileLocksmithUI.exe", - "matching_strategy": "Equals" - }, - { - "kind": "Exe", - "id": "Microsoft.CmdPal.UI.exe", - "matching_strategy": "Equals" - } - ] - }, - "Prime95": { - "floating": [ - { - "kind": "Exe", - "id": "prime95.exe", - "matching_strategy": "Equals" - } - ] - }, - "Prism Launcher": { - "floating": [ - [ - { - "kind": "Exe", - "id": "prismlauncher.exe", - "matching_strategy": "Equals" - }, - { - "kind": "Title", - "id": "- Prism Launcher", - "matching_strategy": "Contains" - } - ] - ] - }, - "Process Hacker": { - "ignore": [ - { - "kind": "Exe", - "id": "ProcessHacker.exe", - "matching_strategy": "Equals" - } - ], - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "ProcessHacker.exe", - "matching_strategy": "Equals" - } - ] - }, - "ProtonDrive": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "ProtonDrive.exe", - "matching_strategy": "Equals" - } - ] - }, - "ProtonVPN": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "ProtonVPN.exe", - "matching_strategy": "Equals" - } - ] - }, - "PyCharm": { - "ignore": [ - { - "kind": "Class", - "id": "SunAwtDialog", - "matching_strategy": "Equals" - } - ], - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "pycharm64.exe", - "matching_strategy": "Equals" - } - ], - "object_name_change": [ - { - "kind": "Exe", - "id": "pycharm64.exe", - "matching_strategy": "Equals" - } - ] - }, - "qBittorrent": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "qbittorrent.exe", - "matching_strategy": "Equals" - } - ], - "ignore": [ - [ - { - "kind": "Exe", - "id": "qbittorrent.exe", - "matching_strategy": "Equals" - }, - { - "kind": "Title", - "id": "Exiting qBittorrent", - "matching_strategy": "Equals" - } - ] - ] - }, - "QGIS": { - "floating": [ - [ - { - "kind": "Exe", - "id": "qgis-bin.exe", - "matching_strategy": "Equals" - }, - { - "kind": "Title", - "id": "QGIS", - "matching_strategy": "DoesNotContain" - } - ], - [ - { - "kind": "Exe", - "id": "qgis-ltr-bin.exe", - "matching_strategy": "Equals" - }, - { - "kind": "Title", - "id": "QGIS", - "matching_strategy": "DoesNotContain" - } - ] - ] - }, - "QQ": { - "ignore": [ - { - "kind": "Title", - "id": "图片查看器", - "matching_strategy": "Legacy" - }, - { - "kind": "Title", - "id": "群聊的聊天记录", - "matching_strategy": "Legacy" - }, - { - "kind": "Title", - "id": "语音通话", - "matching_strategy": "Legacy" - } - ], - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "QQ.exe", - "matching_strategy": "Equals" - } - ] - }, - "QtScrcpy": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "QtScrcpy.exe", - "matching_strategy": "Equals" - } - ] - }, - "QuickLook": { - "ignore": [ - { - "kind": "Exe", - "id": "QuickLook.exe", - "matching_strategy": "Equals" - } - ] - }, - "RepoZ": { - "ignore": [ - { - "kind": "Exe", - "id": "RepoZ.exe", - "matching_strategy": "Equals" - } - ] - }, - "Rider": { - "ignore": [ - { - "kind": "Class", - "id": "SunAwtDialog", - "matching_strategy": "Equals" - }, - { - "kind": "Title", - "id": "PopupMessageWindow", - "matching_strategy": "Legacy" - } - ], - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "rider64.exe", - "matching_strategy": "Equals" - } - ], - "object_name_change": [ - { - "kind": "Exe", - "id": "rider64.exe", - "matching_strategy": "Equals" - } - ] - }, - "Roblox FPS Unlocker": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "rbxfpsunlocker.exe", - "matching_strategy": "Equals" - } - ] - }, - "RoundedTB": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "RoundedTB.exe", - "matching_strategy": "Equals" - } - ] - }, - "RustRover": { - "ignore": [ - { - "kind": "Class", - "id": "SunAwtDialog", - "matching_strategy": "Equals" - } - ], - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "rustrover64.exe", - "matching_strategy": "Equals" - } - ], - "object_name_change": [ - { - "kind": "Exe", - "id": "rustrover64.exe", - "matching_strategy": "Equals" - } - ] - }, - "Sandboxie Plus": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "SandMan.exe", - "matching_strategy": "Equals" - } - ] - }, - "ShareX": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "ShareX.exe", - "matching_strategy": "Equals" - } - ] - }, - "Sideloadly": { - "ignore": [ - { - "kind": "Exe", - "id": "sideloadly.exe", - "matching_strategy": "Equals" - } - ] - }, - "Signal": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "Signal.exe", - "matching_strategy": "Equals" - } - ] - }, - "SiriKali": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "sirikali.exe", - "matching_strategy": "Equals" - } - ] - }, - "Slack": { - "ignore": [ - { - "kind": "Class", - "id": "Chrome_RenderWidgetHostHWND", - "matching_strategy": "Legacy" - } - ], - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "slack.exe", - "matching_strategy": "Equals" - } - ] - }, - "Smart Install Maker": { - "ignore": [ - { - "kind": "Class", - "id": "obj_App", - "matching_strategy": "Legacy" - }, - { - "kind": "Class", - "id": "obj_Form", - "matching_strategy": "Legacy" - } - ] - }, - "SnippingTool": { - "ignore": [ - { - "kind": "Exe", - "id": "SnippingTool.exe", - "matching_strategy": "Equals" - } - ] - }, - "SoulseekQt": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "SoulseekQt.exe", - "matching_strategy": "Equals" - } - ] - }, - "Spotify": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "Spotify.exe", - "matching_strategy": "Equals" - } - ] - }, - "Steam": { - "layered": [ - { - "kind": "Exe", - "id": "steam.exe", - "matching_strategy": "Equals" - } - ], - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "steam.exe", - "matching_strategy": "Equals" - } - ], - "ignore": [ - [ - { - "kind": "Exe", - "id": "steamwebhelper.exe", - "matching_strategy": "Equals" - }, - { - "kind": "Title", - "id": "Steam", - "matching_strategy": "DoesNotEqual" - } - ] - ], - "floating": [ - [ - { - "kind": "Exe", - "id": "steam.exe", - "matching_strategy": "Equals" - }, - { - "kind": "Class", - "id": "BootstrapUpdateUIClass", - "matching_strategy": "Equals" - } - ] - ] - }, - "Steam Beta": { - "ignore": [ - { - "kind": "Title", - "id": "notificationtoasts_", - "matching_strategy": "Legacy" - } - ], - "tray_and_multi_window": [ - { - "kind": "Class", - "id": "SDL_app", - "matching_strategy": "Legacy" - } - ] - }, - "Stremio": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "stremio.exe", - "matching_strategy": "Equals" - } - ] - }, - "Stremio Desktop Community": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "stremio-shell-ng.exe", - "matching_strategy": "Equals" - } - ] - }, - "System Informer": { - "ignore": [ - { - "kind": "Exe", - "id": "SystemInformer.exe", - "matching_strategy": "Equals" - } - ], - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "SystemInformer.exe", - "matching_strategy": "Equals" - } - ] - }, - "SystemSettings": { - "ignore": [ - { - "kind": "Class", - "id": "Shell_Dialog", - "matching_strategy": "Legacy" - } - ] - }, - "Tabby": { - "manage": [ - [ - { - "kind": "Class", - "id": "Chrome_WidgetWin_1", - "matching_strategy": "Equals" - }, - { - "kind": "Exe", - "id": "Tabby.exe", - "matching_strategy": "Equals" - } - ] - ] - }, - "TablePlus": { - "object_name_change": [ - { - "kind": "Exe", - "id": "TablePlus.exe", - "matching_strategy": "Equals" - } - ] - }, - "Task Manager": { - "ignore": [ - { - "kind": "Class", - "id": "TaskManagerWindow", - "matching_strategy": "Legacy" - } - ] - }, - "Telegram": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "Telegram.exe", - "matching_strategy": "Equals" - } - ] - }, - "TeraCopy": { - "ignore": [ - { - "kind": "Exe", - "id": "TeraCopy.exe", - "matching_strategy": "Equals" - } - ] - }, - "TickTick": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "TickTick.exe", - "matching_strategy": "Equals" - } - ] - }, - "Tobit.Team": { - "tray_and_multi_window": [ - { - "kind": "Class", - "id": "TobitTeamFrame", - "matching_strategy": "Equals" - } - ] - }, - "Total Commander": { - "ignore": [ - { - "kind": "Class", - "id": "TDLG2FILEACTIONMIN", - "matching_strategy": "Equals" - }, - { - "kind": "Class", - "id": "TFindFile", - "matching_strategy": "Equals" - }, - { - "kind": "Class", - "id": "TLister", - "matching_strategy": "Equals" - }, - { - "kind": "Class", - "id": "TCHANGETREEDLG", - "matching_strategy": "Equals" - }, - { - "kind": "Class", - "id": "TCONNECT", - "matching_strategy": "Equals" - }, - { - "kind": "Class", - "id": "TSEARCHTEXT", - "matching_strategy": "Equals" - } - ] - }, - "TouchCursor": { - "ignore": [ - { - "kind": "Exe", - "id": "tcconfig.exe", - "matching_strategy": "Equals" - } - ], - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "tcconfig.exe", - "matching_strategy": "Equals" - } - ] - }, - "TranslucentTB": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "TranslucentTB.exe", - "matching_strategy": "Equals" - } - ] - }, - "ueli": { - "ignore": [ - { - "kind": "Exe", - "id": "ueli.exe", - "matching_strategy": "Equals" - } - ], - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "ueli.exe", - "matching_strategy": "Equals" - } - ] - }, - "UniGetUI": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "UniGetUI.exe", - "matching_strategy": "Equals" - } - ] - }, - "Unity": { - "ignore": [ - { - "kind": "Class", - "id": "UnityWndClass", - "matching_strategy": "Equals" - } - ] - }, - "Unity Editor": { - "transparency_ignore": [ - { - "kind": "Exe", - "id": "Unity.exe", - "matching_strategy": "Equals" - } - ], - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "Unity.exe", - "matching_strategy": "Equals" - } - ] - }, - "Unity Hub": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "Unity Hub.exe", - "matching_strategy": "Equals" - } - ] - }, - "Unreal Editor": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "UnrealEditor.exe", - "matching_strategy": "Equals" - } - ], - "floating": [ - [ - { - "kind": "Exe", - "id": "UnrealEditor.exe", - "matching_strategy": "Equals" - }, - { - "kind": "Title", - "id": "- Unreal Editor", - "matching_strategy": "DoesNotEndWith" - } - ] - ] - }, - "Unreal Engine": { - "ignore": [ - { - "kind": "Class", - "id": "UnrealWindow", - "matching_strategy": "Equals" - }, - { - "kind": "Title", - "id": "SplashScreenGuard", - "matching_strategy": "Equals" - } - ] - }, - "visio": { - "ignore": [ - { - "kind": "Class", - "id": "VISIOS", - "matching_strategy": "Equals" - }, - { - "kind": "Class", - "id": "VISIOQ", - "matching_strategy": "Equals" - } - ], - "manage": [ - { - "kind": "Class", - "id": "VISIOA", - "matching_strategy": "Equals" - } - ] - }, - "Visual Studio": { - "object_name_change": [ - { - "kind": "Exe", - "id": "devenv.exe", - "matching_strategy": "Equals" - } - ], - "floating": [ - [ - { - "kind": "Exe", - "id": "devenv.exe", - "matching_strategy": "Equals" - }, - { - "kind": "Title", - "id": "QuickWatch", - "matching_strategy": "Equals" - } - ], - [ - { - "kind": "Exe", - "id": "devenv.exe", - "matching_strategy": "Equals" - }, - { - "kind": "Title", - "id": " - Microsoft Visual Studio", - "matching_strategy": "DoesNotContain" - } - ] - ], - "ignore": [ - { - "kind": "Exe", - "id": "VsDebugConsole.exe", - "matching_strategy": "Equals" - }, - [ - { - "kind": "Exe", - "id": "iisexpresstray.exe", - "matching_strategy": "Equals" - }, - { - "kind": "Class", - "id": "WindowsForms10.Window", - "matching_strategy": "StartsWith" - } - ], - { - "kind": "Title", - "id": "WindowsFormsParkingWindow", - "matching_strategy": "Equals" - }, - [ - { - "kind": "Exe", - "id": "devenv.exe", - "matching_strategy": "Equals" - }, - { - "kind": "Title", - "id": "Move files to a new location?", - "matching_strategy": "Equals" - } - ], - { - "kind": "Exe", - "id": "ServiceHub.ThreadedWaitDialog.exe", - "matching_strategy": "Equals" - } - ] - }, - "VLC": { - "object_name_change": [ - { - "kind": "Exe", - "id": "vlc.exe", - "matching_strategy": "Equals" - } - ], - "ignore": [ - [ - { - "kind": "Exe", - "id": "vlc.exe", - "matching_strategy": "Equals" - }, - { - "kind": "Title", - "id": "Open URL", - "matching_strategy": "Equals" - } - ], - [ - { - "kind": "Exe", - "id": "vlc.exe", - "matching_strategy": "Equals" - }, - { - "kind": "Title", - "id": "About", - "matching_strategy": "Equals" - } - ], - [ - { - "kind": "Exe", - "id": "vlc.exe", - "matching_strategy": "Equals" - }, - { - "kind": "Title", - "id": "Preferences", - "matching_strategy": "Contains" - } - ], - [ - { - "kind": "Exe", - "id": "vlc.exe", - "matching_strategy": "Equals" - }, - { - "kind": "Title", - "id": "Adjustments and Effects", - "matching_strategy": "Equals" - } - ], - [ - { - "kind": "Exe", - "id": "vlc.exe", - "matching_strategy": "Equals" - }, - { - "kind": "Title", - "id": "Open Media", - "matching_strategy": "Equals" - } - ], - [ - { - "kind": "Exe", - "id": "vlc.exe", - "matching_strategy": "Equals" - }, - { - "kind": "Title", - "id": "Current Media Information", - "matching_strategy": "Equals" - } - ], - [ - { - "kind": "Exe", - "id": "vlc.exe", - "matching_strategy": "Equals" - }, - { - "kind": "Title", - "id": "Messages", - "matching_strategy": "Equals" - } - ], - [ - { - "kind": "Exe", - "id": "vlc.exe", - "matching_strategy": "Equals" - }, - { - "kind": "Title", - "id": "VLC media player updates", - "matching_strategy": "Equals" - } - ], - [ - { - "kind": "Exe", - "id": "vlc.exe", - "matching_strategy": "Equals" - }, - { - "kind": "Title", - "id": "Help", - "matching_strategy": "Equals" - } - ], - [ - { - "kind": "Exe", - "id": "vlc.exe", - "matching_strategy": "Equals" - }, - { - "kind": "Title", - "id": "Plugins and extensions", - "matching_strategy": "Equals" - } - ], - [ - { - "kind": "Exe", - "id": "vlc.exe", - "matching_strategy": "Equals" - }, - { - "kind": "Title", - "id": "Building font cache", - "matching_strategy": "Equals" - } - ] - ] - }, - "VMware Horizon Client": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "vmware-view.exe", - "matching_strategy": "Equals" - } - ] - }, - "Voice.ai": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "VoiceAI.exe", - "matching_strategy": "Equals" - } - ] - }, - "VRCX": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "VRCX.exe", - "matching_strategy": "Equals" - } - ] - }, - "WebStorm": { - "ignore": [ - { - "kind": "Class", - "id": "SunAwtDialog", - "matching_strategy": "Equals" - } - ], - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "webstorm64.exe", - "matching_strategy": "Equals" - } - ], - "object_name_change": [ - { - "kind": "Exe", - "id": "webstorm64.exe", - "matching_strategy": "Equals" - } - ] - }, - "WebTorrent Desktop": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "WebTorrent.exe", - "matching_strategy": "Equals" - } - ] - }, - "WeChat": { - "ignore": [ - { - "kind": "Class", - "id": "WeChatLoginWndForPC", - "matching_strategy": "Equals" - }, - { - "kind": "Class", - "id": "FileListMgrWnd", - "matching_strategy": "Equals" - }, - { - "kind": "Class", - "id": "CWebviewControlHostWnd", - "matching_strategy": "Equals" - }, - { - "kind": "Class", - "id": "ChatWnd", - "matching_strategy": "Equals" - }, - { - "kind": "Class", - "id": "EmotionTipWnd", - "matching_strategy": "Equals" - }, - { - "kind": "Class", - "id": "ChatContactMenu", - "matching_strategy": "Equals" - }, - { - "kind": "Exe", - "id": "WeChatAppEx.exe", - "matching_strategy": "Equals" - } - ], - "manage": [ - { - "kind": "Class", - "id": "WeChatMainWndForPC", - "matching_strategy": "Equals" - } - ], - "tray_and_multi_window": [ - { - "kind": "Class", - "id": "WeChatMainWndForPC", - "matching_strategy": "Equals" - } - ] - }, - "WezTerm": { - "object_name_change": [ - { - "kind": "Exe", - "id": "wezterm-gui.exe", - "matching_strategy": "Equals" - } - ] - }, - "WinCompose": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "wincompose.exe", - "matching_strategy": "Equals" - } - ] - }, - "Windows Console (conhost.exe)": { - "manage": [ - { - "kind": "Class", - "id": "ConsoleWindowClass", - "matching_strategy": "Equals" - } - ] - }, - "Windows Explorer": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "explorer.exe", - "matching_strategy": "Equals" - } - ], - "ignore": [ - { - "kind": "Class", - "id": "NativeHWNDHost", - "matching_strategy": "Equals" - }, - { - "kind": "Class", - "id": "OperationStatusWindow", - "matching_strategy": "Legacy" - }, - { - "kind": "Title", - "id": "Control Panel", - "matching_strategy": "Legacy" - } - ] - }, - "Windows Installer": { - "ignore": [ - { - "kind": "Exe", - "id": "msiexec.exe", - "matching_strategy": "Equals" - } - ] - }, - "Windows Subsystem for Android": { - "ignore": [ - { - "kind": "Class", - "id": "android(splash)", - "matching_strategy": "Legacy" - } - ] - }, - "Windows Terminal": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "WindowsTerminal.exe", - "matching_strategy": "Equals" - } - ] - }, - "Windows Update Standalone Installer": { - "ignore": [ - { - "kind": "Exe", - "id": "wusa.exe", - "matching_strategy": "Equals" - } - ] - }, - "WingetUI": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "wingetui.exe", - "matching_strategy": "Equals" - } - ] - }, - "WinZip (32-bit)": { - "ignore": [ - { - "kind": "Exe", - "id": "winzip32.exe", - "matching_strategy": "Equals" - } - ] - }, - "WinZip (64-bit)": { - "ignore": [ - { - "kind": "Exe", - "id": "winzip64.exe", - "matching_strategy": "Equals" - } - ] - }, - "Wox": { - "ignore": [ - { - "kind": "Title", - "id": "Hotkey sink", - "matching_strategy": "Legacy" - } - ] - }, - "XAMPP Control Panel": { - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "xampp-control.exe", - "matching_strategy": "Equals" - } - ] - }, - "Zebar": { - "ignore": [ - { - "kind": "Exe", - "id": "zebar.exe", - "matching_strategy": "Equals" - } - ] - }, - "Zed": { - "layered": [ - { - "kind": "Exe", - "id": "zed.exe", - "matching_strategy": "Equals" - } - ] - }, - "Zen Browser": { - "ignore": [ - { - "kind": "Class", - "id": "MozillaDialogClass", - "matching_strategy": "Equals" - }, - { - "kind": "Class", - "id": "MozillaTaskbarPreviewClass", - "matching_strategy": "Legacy" - }, - [ - { - "kind": "Title", - "id": "Picture-in-Picture", - "matching_strategy": "Equals" - }, - { - "kind": "Exe", - "id": "zen.exe", - "matching_strategy": "Equals" - } - ] - ], - "tray_and_multi_window": [ - { - "kind": "Exe", - "id": "zen.exe", - "matching_strategy": "Equals" - } - ], - "object_name_change": [ - { - "kind": "Exe", - "id": "zen.exe", - "matching_strategy": "Equals" - } - ], - "slow_application": [ - { - "kind": "Exe", - "id": "zen.exe", - "matching_strategy": "Equals" - } - ] - }, - "Zoom": { - "ignore": [ - { - "kind": "Exe", - "id": "Zoom.exe", - "matching_strategy": "Equals" - } - ] - } -} diff --git a/.config/windows/komorebi/komorebi.bar.json b/.config/windows/komorebi/komorebi.bar.json deleted file mode 100644 index 9e26dfe..0000000 --- a/.config/windows/komorebi/komorebi.bar.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/.config/windows/komorebi/komorebi.json b/.config/windows/komorebi/komorebi.json deleted file mode 100644 index 738d9cb..0000000 --- a/.config/windows/komorebi/komorebi.json +++ /dev/null @@ -1,110 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/LGUG2Z/komorebi/v0.1.40/schema.json", - "app_specific_configuration_path": "$Env:USERPROFILE/applications.json", - "window_hiding_behaviour": "Cloak", - "cross_monitor_move_behaviour": "Insert", - "cross_boundary_behaviour": "Workspace", - "window_container_behaviour": "Create", - "window_handling_behaviour": "Sync", - "unmanaged_window_operation_behaviour": "NoOp", - "default_workspace_padding": 1, - "default_container_padding": 4, - "border": true, - "border_width": 3, - "border_offset": -1, - "border_style": "Rounded", - "mouse_follows_focus": true, - "stackbar": { - "height": 30, - "mode": "OnStack", - "tabs": { - "width": 200 - } - }, - "animation": { - "enabled": true, - "style": "EaseOutCubic", - "duration": 200, - "fps": 60 - }, - "transparency": true, - "transparency_alpha": 245, - "theme": { - "palette": "Base16", - "name": "TokyoNightDark", - "single_border": "Base0E", - "stack_border": "Base08", - "monocle_border": "Base0D", - "floating_border": "Base09", - "unfocused_border": "Base03", - "bar_accent": "Base0E" - }, - "display_index_preferences": { - "0": "CMN1556-4&243a609a&0&UID8388688", - "1": "DELF144-5&26d74eb9&0&UID4354" - }, - "ignore_rules": [ - { "kind": "Exe", "id": "Nani.exe", "matching_strategy": "Equals" }, - { "kind": "Exe", "id": "Docker Desktop.exe", "matching_strategy": "Equals" }, - { "kind": "Exe", "id": "WindowsTerminal.exe", "matching_strategy": "Equals" }, - { "kind": "Exe", "id": "explorer.exe", "matching_strategy": "Equals" } - ], - "object_name_change_applications": [ - { "kind": "Exe", "id": "Mattermost.exe", "matching_strategy": "Equals" } - ], - "monitors": [ - { - "workspaces": [ - { - "name": "I", - "layout": "BSP", - "initial_workspace_rules": [ - { "kind": "Exe", "id": "wezterm-gui.exe", "matching_strategy": "Equals" } - ] - }, - { - "name": "II", - "layout": "Grid", - "workspace_rules": [ - { "kind": "Exe", "id": "Discord.exe", "matching_strategy": "Equals" } - ] - }, - { - "name": "III", - "layout": "Columns", - "workspace_rules": [ - { "kind": "Exe", "id": "Slack.exe", "matching_strategy": "Equals" }, - { "kind": "Exe", "id": "Spotify.exe", "matching_strategy": "Equals" } - ] - } - ] - }, - { - "workspaces": [ - { - "name": "IV", - "layout": "BSP", - "workspace_rules": [ - { "kind": "Exe", "id": "Code.exe", "matching_strategy": "Equals" }, - { "kind": "Exe", "id": "Zed.exe", "matching_strategy": "Equals" } - ] - }, - { - "name": "V", - "layout": "BSP", - "workspace_rules": [ - { "kind": "Exe", "id": "chrome.exe", "matching_strategy": "Equals" }, - { "kind": "Exe", "id": "brave.exe", "matching_strategy": "Equals" } - ] - }, - { - "name": "VI", - "layout": "BSP", - "workspace_rules": [ - { "kind": "Exe", "id": "Mattermost.exe", "matching_strategy": "Equals" } - ] - } - ] - } - ] -} diff --git a/.config/windows/komorebi/komorebi_resolve_config.ps1 b/.config/windows/komorebi/komorebi_resolve_config.ps1 deleted file mode 100644 index 0e49579..0000000 --- a/.config/windows/komorebi/komorebi_resolve_config.ps1 +++ /dev/null @@ -1,91 +0,0 @@ -# 接続中の外部モニターを WMI で検出して、komorebi 設定の -# display_index_preferences[1] を実機に合わせた一時ファイルを生成する。 -# 標準出力に生成済みファイルのパスを 1 行で返す(komorebi_start.ps1 から -# `komorebic start --config ` 用に渡す)。 -# -# canonical な komorebi.json は dotfiles 側 (setup_windows.ps1 で -# $HOME\komorebi.json にリンク) を読み込み、リポジトリは書き換えない。 -# 検出に失敗した場合は canonical のパスをそのまま返す(フォールバック)。 - -$ErrorActionPreference = "Continue" - -# Canonical 設定ファイル(setup_windows.ps1 が $HOME\komorebi.json をシンボリックリンク化) -$canonicalPath = Join-Path $env:USERPROFILE "komorebi.json" -if (-not (Test-Path -LiteralPath $canonicalPath)) { - # リンクが無い場合はリポジトリ直接を見る - $canonicalPath = "$env:USERPROFILE\Project\github.com\t4ko0522\dotfiles\.config\komorebi\komorebi.json" -} - -# 認識済み外部モニター(後で増やす場合はここに追加) -$knownExternals = @{ - "IOD43EE" = "home (IO-DATA)" - "DELF144" = "work (Dell)" -} - -# 内蔵モニター(除外用) -$internalManufacturers = @("CMN", "AUO", "LGD", "BOE") - -function ConvertTo-KomorebiDeviceId { - param([string]$InstanceName) - # InstanceName: "DISPLAY\IOD43EE\5&26d74eb9&0&UID4354_0" - # komorebi: "IOD43EE-5&26d74eb9&0&UID4354" - $parts = $InstanceName -split '\\' - if ($parts.Count -lt 3) { return $null } - $deviceCode = $parts[1] - $hardwareId = $parts[2] -replace '_\d+$', '' - return "$deviceCode-$hardwareId" -} - -# 外部モニター検出 -$detectedExternalId = $null -try { - $wmiMonitors = Get-CimInstance -Namespace root\WMI -ClassName WmiMonitorID -ErrorAction Stop | - Where-Object { $_.Active } - foreach ($wm in $wmiMonitors) { - $mfg = ([System.Text.Encoding]::ASCII.GetString($wm.ManufacturerName)).TrimEnd([char]0) - if ($internalManufacturers -contains $mfg) { continue } - - $prod = ([System.Text.Encoding]::ASCII.GetString($wm.ProductCodeID)).TrimEnd([char]0) - $deviceCode = "$mfg$prod" - if (-not $knownExternals.ContainsKey($deviceCode)) { - Write-Host "[?] unknown external monitor: $deviceCode (komorebi_resolve_config.ps1 の knownExternals に追加してください)" -ForegroundColor Yellow - continue - } - - $detectedExternalId = ConvertTo-KomorebiDeviceId -InstanceName $wm.InstanceName - Write-Host ("[ext] detected: {0} ({1})" -f $detectedExternalId, $knownExternals[$deviceCode]) -ForegroundColor Cyan - break - } -} catch { - Write-Host "WMI monitor lookup failed: $_" -ForegroundColor Yellow -} - -# Canonical を読み込み、必要なら display_index_preferences[1] を patch -$json = Get-Content -LiteralPath $canonicalPath -Raw -$config = $json | ConvertFrom-Json - -if ($detectedExternalId -and $config.display_index_preferences) { - $current = $config.display_index_preferences.'1' - if ($current -ne $detectedExternalId) { - Write-Host ("[patch] display_index_preferences[1]: {0} -> {1}" -f $current, $detectedExternalId) -ForegroundColor DarkCyan - $config.display_index_preferences.'1' = $detectedExternalId - } -} - -# app_specific_configuration_path は dotfiles canonical では PowerShell 風の "$Env:..." 表記だが、 -# komorebi はこの形式を展開しないので、runtime 用には絶対パスへ解決しておく。 -if ($config.app_specific_configuration_path) { - $orig = $config.app_specific_configuration_path - $resolved = $orig.Replace('$Env:USERPROFILE', $env:USERPROFILE).Replace('${Env:USERPROFILE}', $env:USERPROFILE).Replace('%USERPROFILE%', $env:USERPROFILE) - if ($resolved -ne $orig) { - Write-Host ("[patch] app_specific_configuration_path: {0} -> {1}" -f $orig, $resolved) -ForegroundColor DarkCyan - $config.app_specific_configuration_path = $resolved - } -} - -# 一時設定ファイルへ書き出し -$runtimePath = Join-Path $env:LOCALAPPDATA "komorebi-runtime.json" -$config | ConvertTo-Json -Depth 100 | Set-Content -LiteralPath $runtimePath -Encoding UTF8 - -# stdout には生成済みファイルパスのみ -Write-Output $runtimePath diff --git a/.config/windows/komorebi/komorebi_start.ps1 b/.config/windows/komorebi/komorebi_start.ps1 deleted file mode 100644 index 5ed1957..0000000 --- a/.config/windows/komorebi/komorebi_start.ps1 +++ /dev/null @@ -1,61 +0,0 @@ -# komorebi + whkd + 常用アプリ一括起動を「実機モニターに合わせた -# display_index_preferences」で行う、朝の作業環境立ち上げの唯一の経路。 -# pwsh 起動時に startup.ps1 から komorebi 未起動時のみ呼ばれる。 -# -# 注意: `komorebic start --config ` は内部で `--config="path"` の形に連結して -# komorebi.exe に渡すため clap で reject される。これを避けるために komorebi.exe を -# 直接起動し、その後 whkd を別途立ち上げる。 - -$ErrorActionPreference = "Continue" - -$komorebiPath = (Get-Command komorebi -ErrorAction SilentlyContinue)?.Source -$whkdPath = (Get-Command whkd -ErrorAction SilentlyContinue)?.Source -if (-not $komorebiPath) { - Write-Host "komorebi not found in PATH" -ForegroundColor Yellow - exit 1 -} - -# 接続モニターに合わせて patch 済みの一時設定ファイルを生成 -$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path -$resolver = Join-Path $scriptDir "komorebi_resolve_config.ps1" -$runtimeConfig = $null -if (Test-Path -LiteralPath $resolver) { - $output = & $resolver - $last = $output | Where-Object { $_ } | Select-Object -Last 1 - if ($last) { $runtimeConfig = $last.ToString().Trim() } -} - -# komorebi.exe を直接起動 (komorebic start の --config 連結バグを回避) -$komorebiArgs = @() -if ($runtimeConfig -and (Test-Path -LiteralPath $runtimeConfig)) { - $komorebiArgs = @('--config', $runtimeConfig) - Write-Host ("[start] komorebi --config {0}" -f $runtimeConfig) -ForegroundColor Cyan -} else { - Write-Host "[start] komorebi (no runtime config)" -ForegroundColor Cyan -} -Start-Process -FilePath $komorebiPath -ArgumentList $komorebiArgs -WindowStyle Hidden - -# komorebi が socket を listen し始めるまで待機 (最大 15 秒) -$deadline = (Get-Date).AddSeconds(15) -while ((Get-Date) -lt $deadline) { - Start-Sleep -Milliseconds 300 - komorebic state 2>$null | Out-Null - if ($LASTEXITCODE -eq 0) { break } -} - -# whkd を別途立ち上げ -if ($whkdPath) { - if (-not (Get-Process -Name whkd -ErrorAction SilentlyContinue)) { - Start-Process -FilePath $whkdPath -WindowStyle Hidden - Write-Host "[start] whkd" -ForegroundColor Cyan - } -} - -# 常用アプリを一括起動して両モニターを WS1 に整列 -# komorebi 未起動 → 起動の流れでだけ走るので、作業中の pwsh タブ起動では -# 二度目の WS リセットは発生しない。 -$morningSetup = Join-Path $scriptDir "morning_setup.ps1" -if (Test-Path -LiteralPath $morningSetup) { - Write-Host "[start] morning_setup" -ForegroundColor Cyan - & $morningSetup -} diff --git a/.config/windows/komorebi/morning_setup.ps1 b/.config/windows/komorebi/morning_setup.ps1 deleted file mode 100644 index 378b0bf..0000000 --- a/.config/windows/komorebi/morning_setup.ps1 +++ /dev/null @@ -1,85 +0,0 @@ -# ワークスペース配置に沿ってよく使うアプリを一括起動する。 -# 振り分けは komorebi.json の workspace_rules 側で宣言的に管理しているため、 -# このスクリプトは起動だけを担当する(timing 依存を排除)。 -# -# 仕様: -# - 既に走っているプロセスは何もしない -# - インストール先が見つからない exe はスキップ -# - 全て実体フルパスで起動(PATH 依存を排除) - -$ErrorActionPreference = "Continue" - -# モニター index の動的補正は komorebi_start.ps1 が起動時に行うのでここでは不要。 - -function Start-IfNotRunning { - param( - [Parameter(Mandatory)][string] $ProcessName, - [Parameter(Mandatory)][string] $Path, - [string[]] $ArgumentList - ) - - if (Get-Process -Name $ProcessName -ErrorAction SilentlyContinue) { - Write-Host ("[skip] already running: {0}" -f $ProcessName) -ForegroundColor DarkGray - return - } - - if (-not (Test-Path -LiteralPath $Path)) { - Write-Host ("[miss] not installed: {0}" -f $Path) -ForegroundColor Yellow - return - } - - Write-Host ("[run ] launching: {0}" -f $Path) -ForegroundColor Cyan - if ($ArgumentList) { - Start-Process -FilePath $Path -ArgumentList $ArgumentList - } else { - Start-Process -FilePath $Path - } - Start-Sleep -Milliseconds 300 -} - -# WS I / M0 — WezTerm -Start-IfNotRunning ` - -ProcessName "wezterm-gui" ` - -Path "C:\Program Files\WezTerm\wezterm-gui.exe" - -# WS II / M0 — Discord (Update.exe --processStart Discord.exe でバージョン依存を回避) -Start-IfNotRunning ` - -ProcessName "Discord" ` - -Path "$env:LOCALAPPDATA\Discord\Update.exe" ` - -ArgumentList @("--processStart", "Discord.exe") - -# WS III / M0 — Slack (Microsoft Store 版。WindowsApps 以下の App Execution Alias を使う) -Start-IfNotRunning ` - -ProcessName "slack" ` - -Path "$env:LOCALAPPDATA\Microsoft\WindowsApps\slack.exe" - -# WS III / M0 — Spotify -Start-IfNotRunning ` - -ProcessName "Spotify" ` - -Path "$env:APPDATA\Spotify\Spotify.exe" - -# WS IV / M1 — Zed -Start-IfNotRunning ` - -ProcessName "Zed" ` - -Path "$env:LOCALAPPDATA\Programs\Zed\Zed.exe" - -# WS IV / M1 — Brave (プライベート用ブラウザ) -Start-IfNotRunning ` - -ProcessName "brave" ` - -Path "C:\Program Files\BraveSoftware\Brave-Browser\Application\brave.exe" - -# WS V / M1 — Chrome (ビジネス用ブラウザ) -Start-IfNotRunning ` - -ProcessName "chrome" ` - -Path "C:\Program Files\Google\Chrome\Application\chrome.exe" - -# WS VI / M1 — Mattermost -Start-IfNotRunning ` - -ProcessName "Mattermost" ` - -Path "C:\Program Files\Mattermost\Mattermost.exe" - -# 起動完了後に両モニターを WS 1 へ -Start-Sleep -Seconds 2 -if (Get-Command komorebic -ErrorAction SilentlyContinue) { - komorebic focus-workspaces 0 | Out-Null -} diff --git a/.config/windows/whkdrc b/.config/windows/whkdrc deleted file mode 100644 index f980c8b..0000000 --- a/.config/windows/whkdrc +++ /dev/null @@ -1,78 +0,0 @@ -.shell pwsh - -# Reload komorebi configuration -win + r : komorebic reload-configuration - -# App shortcuts - these require shell to be pwsh / powershell -# The apps will be focused if open, or launched if not open -# win + f : if ($wshell.AppActivate('Firefox') -eq $False) { start firefox } -# win + b : if ($wshell.AppActivate('Chrome') -eq $False) { start chrome } - -win + q : komorebic close -win + m : komorebic minimize - -# Focus windows within workspace -win + left : komorebic focus left -win + down : komorebic focus down -win + up : komorebic focus up -win + right : komorebic focus right -win + shift + oem_4 : komorebic cycle-focus previous # oem_4 is [ -win + shift + oem_6 : komorebic cycle-focus next # oem_6 is ] - -# Preselect split direction for next window (win + uiop) — 次に開くウィンドウの配置先を指定 -win + u : komorebic preselect-direction left -win + i : komorebic preselect-direction down -win + o : komorebic preselect-direction up -win + p : komorebic preselect-direction right -win + shift + return : komorebic promote - -# Swap/move focused window with neighbor (win + shift + uiop) -win + shift + u : komorebic move left -win + shift + i : komorebic move down -win + shift + o : komorebic move up -win + shift + p : komorebic move right - -# Stack windows -win + oem_1 : komorebic unstack # oem_1 is ; -win + oem_4 : komorebic cycle-stack previous # oem_4 is [ -win + oem_6 : komorebic cycle-stack next # oem_6 is ] - -# Resize -win + oem_plus : komorebic resize-axis horizontal increase -win + oem_minus : komorebic resize-axis horizontal decrease -win + shift + oem_plus : komorebic resize-axis vertical increase -win + shift + oem_minus : komorebic resize-axis vertical decrease - -# Manipulate windows -win + t : komorebic toggle-float -win + shift + f : komorebic toggle-monocle - -# Window manager options -win + z : komorebic toggle-pause - -# Layouts -win + x : komorebic flip-layout horizontal -win + y : komorebic flip-layout vertical - -# Workspaces — グローバル番号で固定 (フォーカス中モニターに依らず常に同じ WS へ飛ぶ) -win + 1 : komorebic focus-monitor-workspace 0 0 # WS 1 (M0:I): wezterm -win + 2 : komorebic focus-monitor-workspace 0 1 # WS 2 (M0:II): discord -win + 3 : komorebic focus-monitor-workspace 0 2 # WS 3 (M0:III): slack+spotify - -# M1 のワークスペースへ直接切替 (フォーカスも M1 へ移動) -win + f1 : komorebic focus-monitor-workspace 1 0 # WS 4 (M1:IV): vscode -win + f2 : komorebic focus-monitor-workspace 1 1 # WS 5 (M1:V): chrome+brave -win + f3 : komorebic focus-monitor-workspace 1 2 # WS 6 (M1:VI): mattermost - -# Move current window to a workspace on the focused monitor -win + alt + 1 : komorebic move-to-workspace 0 -win + alt + 2 : komorebic move-to-workspace 1 -win + alt + 3 : komorebic move-to-workspace 2 - -# Monitors (multi-monitor focus/move) -win + oem_comma : komorebic focus-monitor 0 # , — M0 main (wezterm / discord / slack+spotify) -win + oem_period : komorebic focus-monitor 1 # . — M1 sub (vscode+brave / chrome / mattermost) -win + shift + oem_comma : komorebic move-to-monitor 0 -win + shift + oem_period: komorebic move-to-monitor 1 -win + n : komorebic cycle-monitor next -win + shift + n : komorebic cycle-monitor previous \ No newline at end of file diff --git a/.config/windows/wsl/wsl.conf b/.config/windows/wsl/wsl.conf deleted file mode 100644 index c018f8a..0000000 --- a/.config/windows/wsl/wsl.conf +++ /dev/null @@ -1,13 +0,0 @@ -[boot] -systemd = true - -[user] -default = takow - -[automount] -enabled = true -options = "metadata,umask=22,fmask=11" - -[interop] -enabled = true -appendWindowsPath = true diff --git a/.git_template/hooks/post-merge b/.git_template/hooks/post-merge deleted file mode 100644 index 7c1c6f3..0000000 --- a/.git_template/hooks/post-merge +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env bash -# post-merge: branch 指定された submodule をリモート先端に追従させる -# (.gitmodules で `branch = ...` が設定されたものが対象) - -set -e - -repo_root="$(git rev-parse --show-toplevel 2>/dev/null)" || exit 0 -[ -f "$repo_root/.gitmodules" ] || exit 0 - -# branch 指定がある submodule のみ更新 (それ以外は通常の pin 動作のまま) -git -C "$repo_root" config -f .gitmodules --get-regexp '^submodule\..*\.branch$' 2>/dev/null \ - | awk '{print $1}' \ - | sed -E 's/^submodule\.(.*)\.branch$/\1/' \ - | while read -r name; do - path="$(git -C "$repo_root" config -f .gitmodules --get "submodule.$name.path")" - [ -n "$path" ] || continue - git -C "$repo_root" submodule update --init --remote --merge -- "$path" 2>/dev/null || true - done diff --git a/.github/workflows/benchmark-cache.yml b/.github/workflows/benchmark-cache.yml deleted file mode 100644 index 014d49e..0000000 --- a/.github/workflows/benchmark-cache.yml +++ /dev/null @@ -1,310 +0,0 @@ -# cf-edgeNix (nix.t4ko.pet) の有無で NixOS closure のビルド (nixos-rebuild の -# ビルド部分に相当) がどれだけ速くなるかを計測するベンチマーク。 -# -# シナリオ (すべて fresh runner・/nix/store キャッシュなし・同一 commit): -# 1. baseline — substituter は cache.nixos.org / numtide / vicinae のみ -# 2. edgenix-first — + https://nix.t4ko.pet (Workers Cache API はコールド想定) -# 3. edgenix-second — 同一構成を直後に再実行 (Cache API / KV / L0 ウォーム) -# -# コスト計測: 各フェーズの前後で /api/quota/metrics (5 分 cron が書く R2 使用量 -# snapshot) を取得し、R2 Class B operations の増分を比較する。 -# edgenix-second で増分が消えていれば、その差が Workers Cache API による -# R2 Class B 削減分。cron + GraphQL 集計遅延があるため取得前に 7 分待つ。 -# -# 注意: ビルド対象は checkout した working tree ではなく -# github:T4ko0522/dotfiles/ を直接参照する。flake が dotfilesDir = -# self.outPath を使っているため、working tree にベンチ用ファイルがあると -# store path が変わり publish 済み closure にヒットしなくなるため。 - -name: benchmark-cache - -on: - workflow_dispatch: - inputs: - rev: - description: "ビルド対象 commit SHA (空なら master HEAD)" - required: false - type: string - host: - description: "対象 host (laptop | desktop)" - required: false - default: laptop - type: string - -concurrency: - group: benchmark-cache - cancel-in-progress: false - -permissions: - contents: read - -env: - KEYS: >- - cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= - nix.t4ko.pet-1:0eRO18L1/5diWYWboKKPTejQGhGCHNITwELiUaX7Kps= - vicinae.cachix.org-1:1kDrfienkGHPYbkpNj1mWTr7Fm1+zcenzgTizIcI3oc= - niks3.numtide.com-1:DTx8wZduET09hRmMtKdQDxNNthLQETkc/yaX7M4qK0g= - SUBS_BASE: https://cache.nixos.org https://vicinae.cachix.org https://cache.numtide.com - SUBS_EDGE: https://nix.t4ko.pet https://cache.nixos.org https://vicinae.cachix.org https://cache.numtide.com - -jobs: - resolve: - runs-on: ubuntu-latest - outputs: - rev: ${{ steps.rev.outputs.rev }} - host: ${{ steps.rev.outputs.host }} - steps: - - name: Resolve target rev / host - id: rev - env: - GH_TOKEN: ${{ github.token }} - INPUT_REV: ${{ inputs.rev }} - INPUT_HOST: ${{ inputs.host }} - run: | - rev="$INPUT_REV" - if [ -z "$rev" ]; then - rev=$(gh api repos/${{ github.repository }}/commits/master --jq .sha) - fi - host="${INPUT_HOST:-laptop}" - case "$host" in - laptop|desktop) ;; - *) echo "unknown host: $host" >&2; exit 1 ;; - esac - echo "rev=$rev" >> "$GITHUB_OUTPUT" - echo "host=$host" >> "$GITHUB_OUTPUT" - echo "target: $rev / $host" - - quota-before: - runs-on: ubuntu-latest - environment: production - continue-on-error: true - outputs: - classB: ${{ steps.q.outputs.classB }} - classA: ${{ steps.q.outputs.classA }} - steps: - - name: Snapshot quota metrics - id: q - env: - ADMIN_TOKEN: ${{ secrets.ADMIN_TOKEN }} - run: | - json=$(curl -sSf -H "Authorization: Bearer $ADMIN_TOKEN" https://nix.t4ko.pet/api/quota/metrics) - echo "classB=$(jq -r '.metrics.classBOperations.value // 0' <<<"$json")" >> "$GITHUB_OUTPUT" - echo "classA=$(jq -r '.metrics.classAOperations.value // 0' <<<"$json")" >> "$GITHUB_OUTPUT" - jq . <<<"$json" - - baseline: - needs: [resolve, quota-before] - runs-on: ubuntu-latest - timeout-minutes: 120 - outputs: - duration: ${{ steps.bench.outputs.duration }} - closure_bytes: ${{ steps.bench.outputs.closure_bytes }} - copied_total: ${{ steps.bench.outputs.copied_total }} - from_edgenix: ${{ steps.bench.outputs.from_edgenix }} - from_nixos: ${{ steps.bench.outputs.from_nixos }} - built_locally: ${{ steps.bench.outputs.built_locally }} - steps: - - name: Free disk space - run: sudo rm -rf /usr/local/lib/android /usr/share/dotnet /opt/ghc /usr/local/.ghcup - - - name: Checkout (bench scripts) - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - - name: Install Nix (without nix.t4ko.pet) - uses: cachix/install-nix-action@08dcb3a5e62fa31e2da3d490afc4176ef55ecd72 # v30 - with: - extra_nix_config: | - experimental-features = nix-command flakes - substituters = ${{ env.SUBS_BASE }} - trusted-public-keys = ${{ env.KEYS }} - accept-flake-config = false - - - name: Build toplevel (baseline) - id: bench - env: - FLAKE_REF: github:${{ github.repository }}/${{ needs.resolve.outputs.rev }} - HOST: ${{ needs.resolve.outputs.host }} - run: bash scripts/bench-build.sh - - edgenix-first: - needs: [resolve, baseline] - runs-on: ubuntu-latest - timeout-minutes: 120 - outputs: - duration: ${{ steps.bench.outputs.duration }} - closure_bytes: ${{ steps.bench.outputs.closure_bytes }} - copied_total: ${{ steps.bench.outputs.copied_total }} - from_edgenix: ${{ steps.bench.outputs.from_edgenix }} - from_nixos: ${{ steps.bench.outputs.from_nixos }} - built_locally: ${{ steps.bench.outputs.built_locally }} - steps: - - name: Free disk space - run: sudo rm -rf /usr/local/lib/android /usr/share/dotnet /opt/ghc /usr/local/.ghcup - - - name: Checkout (bench scripts) - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - - name: Install Nix (with nix.t4ko.pet) - uses: cachix/install-nix-action@08dcb3a5e62fa31e2da3d490afc4176ef55ecd72 # v30 - with: - extra_nix_config: | - experimental-features = nix-command flakes - substituters = ${{ env.SUBS_EDGE }} - trusted-public-keys = ${{ env.KEYS }} - accept-flake-config = false - - - name: Build toplevel (edgenix cold) - id: bench - env: - FLAKE_REF: github:${{ github.repository }}/${{ needs.resolve.outputs.rev }} - HOST: ${{ needs.resolve.outputs.host }} - run: bash scripts/bench-build.sh - - quota-cold: - needs: [quota-before, edgenix-first] - runs-on: ubuntu-latest - environment: production - continue-on-error: true - outputs: - classB: ${{ steps.q.outputs.classB }} - classA: ${{ steps.q.outputs.classA }} - steps: - - name: Wait for quota cron + analytics lag - run: sleep 420 - - - name: Snapshot quota metrics - id: q - env: - ADMIN_TOKEN: ${{ secrets.ADMIN_TOKEN }} - run: | - json=$(curl -sSf -H "Authorization: Bearer $ADMIN_TOKEN" https://nix.t4ko.pet/api/quota/metrics) - echo "classB=$(jq -r '.metrics.classBOperations.value // 0' <<<"$json")" >> "$GITHUB_OUTPUT" - echo "classA=$(jq -r '.metrics.classAOperations.value // 0' <<<"$json")" >> "$GITHUB_OUTPUT" - jq . <<<"$json" - - edgenix-second: - needs: [resolve, quota-cold] - runs-on: ubuntu-latest - timeout-minutes: 120 - outputs: - duration: ${{ steps.bench.outputs.duration }} - closure_bytes: ${{ steps.bench.outputs.closure_bytes }} - copied_total: ${{ steps.bench.outputs.copied_total }} - from_edgenix: ${{ steps.bench.outputs.from_edgenix }} - from_nixos: ${{ steps.bench.outputs.from_nixos }} - built_locally: ${{ steps.bench.outputs.built_locally }} - steps: - - name: Free disk space - run: sudo rm -rf /usr/local/lib/android /usr/share/dotnet /opt/ghc /usr/local/.ghcup - - - name: Checkout (bench scripts) - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - - name: Install Nix (with nix.t4ko.pet) - uses: cachix/install-nix-action@08dcb3a5e62fa31e2da3d490afc4176ef55ecd72 # v30 - with: - extra_nix_config: | - experimental-features = nix-command flakes - substituters = ${{ env.SUBS_EDGE }} - trusted-public-keys = ${{ env.KEYS }} - accept-flake-config = false - - - name: Build toplevel (edgenix warm) - id: bench - env: - FLAKE_REF: github:${{ github.repository }}/${{ needs.resolve.outputs.rev }} - HOST: ${{ needs.resolve.outputs.host }} - run: bash scripts/bench-build.sh - - quota-warm: - needs: [quota-cold, edgenix-second] - runs-on: ubuntu-latest - environment: production - continue-on-error: true - outputs: - classB: ${{ steps.q.outputs.classB }} - classA: ${{ steps.q.outputs.classA }} - steps: - - name: Wait for quota cron + analytics lag - run: sleep 420 - - - name: Snapshot quota metrics - id: q - env: - ADMIN_TOKEN: ${{ secrets.ADMIN_TOKEN }} - run: | - json=$(curl -sSf -H "Authorization: Bearer $ADMIN_TOKEN" https://nix.t4ko.pet/api/quota/metrics) - echo "classB=$(jq -r '.metrics.classBOperations.value // 0' <<<"$json")" >> "$GITHUB_OUTPUT" - echo "classA=$(jq -r '.metrics.classAOperations.value // 0' <<<"$json")" >> "$GITHUB_OUTPUT" - jq . <<<"$json" - - report: - needs: [resolve, quota-before, baseline, edgenix-first, quota-cold, edgenix-second, quota-warm] - if: always() - runs-on: ubuntu-latest - steps: - - name: Write summary - env: - REV: ${{ needs.resolve.outputs.rev }} - HOST: ${{ needs.resolve.outputs.host }} - B_DUR: ${{ needs.baseline.outputs.duration }} - B_TOTAL: ${{ needs.baseline.outputs.copied_total }} - B_NIXOS: ${{ needs.baseline.outputs.from_nixos }} - B_BUILT: ${{ needs.baseline.outputs.built_locally }} - B_SIZE: ${{ needs.baseline.outputs.closure_bytes }} - C_DUR: ${{ needs.edgenix-first.outputs.duration }} - C_TOTAL: ${{ needs.edgenix-first.outputs.copied_total }} - C_EDGE: ${{ needs.edgenix-first.outputs.from_edgenix }} - C_NIXOS: ${{ needs.edgenix-first.outputs.from_nixos }} - C_BUILT: ${{ needs.edgenix-first.outputs.built_locally }} - W_DUR: ${{ needs.edgenix-second.outputs.duration }} - W_TOTAL: ${{ needs.edgenix-second.outputs.copied_total }} - W_EDGE: ${{ needs.edgenix-second.outputs.from_edgenix }} - W_NIXOS: ${{ needs.edgenix-second.outputs.from_nixos }} - W_BUILT: ${{ needs.edgenix-second.outputs.built_locally }} - Q0_B: ${{ needs.quota-before.outputs.classB }} - Q1_B: ${{ needs.quota-cold.outputs.classB }} - Q2_B: ${{ needs.quota-warm.outputs.classB }} - Q0_A: ${{ needs.quota-before.outputs.classA }} - Q1_A: ${{ needs.quota-cold.outputs.classA }} - Q2_A: ${{ needs.quota-warm.outputs.classA }} - run: | - fmt() { # 秒 → "12m34s (754s)" - local s="$1" - [ -z "$s" ] && { echo "n/a"; return; } - printf "%dm%02ds (%ss)" $((s / 60)) $((s % 60)) "$s" - } - gib() { - local b="$1" - [ -z "$b" ] && { echo "n/a"; return; } - awk -v b="$b" 'BEGIN { printf "%.2f GiB", b / 1024 / 1024 / 1024 }' - } - delta() { - local a="$1" b="$2" - { [ -z "$a" ] || [ -z "$b" ]; } && { echo "n/a"; return; } - echo $((b - a)) - } - { - echo "# cf-edgeNix cache benchmark" - echo - echo "- target: \`github:${{ github.repository }}/$REV\` / host: \`$HOST\`" - echo "- closure size: $(gib "$B_SIZE")" - echo - echo "## ビルド時間 (nixos-rebuild のビルド相当・fresh runner)" - echo - echo "| scenario | wall time | copied paths | from nix.t4ko.pet | from cache.nixos.org | built locally |" - echo "| --- | --- | --- | --- | --- | --- |" - echo "| baseline (cache なし) | $(fmt "$B_DUR") | ${B_TOTAL:-n/a} | 0 | ${B_NIXOS:-n/a} | ${B_BUILT:-n/a} |" - echo "| nix.t4ko.pet あり (edge cold) | $(fmt "$C_DUR") | ${C_TOTAL:-n/a} | ${C_EDGE:-n/a} | ${C_NIXOS:-n/a} | ${C_BUILT:-n/a} |" - echo "| nix.t4ko.pet あり (edge warm) | $(fmt "$W_DUR") | ${W_TOTAL:-n/a} | ${W_EDGE:-n/a} | ${W_NIXOS:-n/a} | ${W_BUILT:-n/a} |" - echo - echo "## R2 コスト (quota snapshot 差分・月間累計の増分)" - echo - echo "| phase | ΔClass B (read) | ΔClass A (write) |" - echo "| --- | --- | --- |" - echo "| edge cold run | $(delta "$Q0_B" "$Q1_B") | $(delta "$Q0_A" "$Q1_A") |" - echo "| edge warm run | $(delta "$Q1_B" "$Q2_B") | $(delta "$Q1_A" "$Q2_A") |" - echo - echo "> quota snapshot は 5 分 cron + GraphQL Analytics 経由のため増分は参考値。" - echo "> warm run の ΔClass B が cold run より小さい分が Workers Cache API による削減分。" - } >> "$GITHUB_STEP_SUMMARY" diff --git a/.github/workflows/chezmoi.yml b/.github/workflows/chezmoi.yml new file mode 100644 index 0000000..a20e254 --- /dev/null +++ b/.github/workflows/chezmoi.yml @@ -0,0 +1,159 @@ +name: Chezmoi + +on: + workflow_call: + +permissions: + contents: read + +jobs: + windows: + name: Windows availability + runs-on: windows-latest + timeout-minutes: 15 + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install chezmoi + shell: pwsh + run: choco install chezmoi --yes --no-progress + + - name: Apply Windows profile + shell: pwsh + run: | + $destination = Join-Path $env:RUNNER_TEMP 'chezmoi-home' + $env:CHEZMOI_WINDOWS_APPDATA = Join-Path $env:RUNNER_TEMP 'chezmoi-appdata' + $env:CHEZMOI_WINDOWS_DOCUMENTS = Join-Path $env:RUNNER_TEMP 'chezmoi-documents' + "CHEZMOI_WINDOWS_APPDATA=$env:CHEZMOI_WINDOWS_APPDATA" >> $env:GITHUB_ENV + "CHEZMOI_WINDOWS_DOCUMENTS=$env:CHEZMOI_WINDOWS_DOCUMENTS" >> $env:GITHUB_ENV + New-Item -ItemType Directory -Path $destination -Force | Out-Null + chezmoi --source $PWD --destination $destination init --apply ` + --no-tty ` + --promptChoice 'Environment profile=windows' + if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } + + $expected = @{ + (Join-Path $destination 'AppData\Local\nvim') = (Join-Path $PWD 'mutable\nvim') + (Join-Path $destination '.config\cava') = (Join-Path $PWD 'mutable\cava') + } + foreach ($target in $expected.Keys) { + $item = Get-Item -LiteralPath $target -Force + if ($item.LinkType -ne 'Junction') { + throw "Expected junction: $target" + } + if ([IO.Path]::GetFullPath([string]$item.Target) -ne [IO.Path]::GetFullPath($expected[$target])) { + throw "Unexpected junction target: $target -> $($item.Target)" + } + } + + - name: Verify managed configuration + shell: pwsh + run: | + $destination = Join-Path $env:RUNNER_TEMP 'chezmoi-home' + $required = @( + '.claude\CLAUDE.md', + '.claude\settings.json', + '.codex\AGENTS.md', + '.codex\config.toml', + '.config\ccwin-notify\config.toml', + '.config\fastfetch\config.jsonc', + '.config\lazygit\config.yml', + '.config\mise\config.toml', + '.config\starship.toml', + '.config\vim\vimrc', + '.config\wezterm\wezterm.lua', + '.config\yasb\config.yaml', + '.config\yazi\yazi.toml', + '.config\zed\settings.json', + '.git_template\hooks\prepare-commit-msg', + '.gitconfig', + 'Documents\PowerShell\Microsoft.PowerShell_profile.ps1' + ) + foreach ($relative in $required) { + $target = Join-Path $destination $relative + if (-not (Test-Path -LiteralPath $target)) { + throw "Missing managed target: $relative" + } + } + + $settings = Get-Content -LiteralPath (Join-Path $destination '.claude\settings.json') -Raw | ConvertFrom-Json + if (-not $settings.hooks.Notification) { + throw 'Windows Claude hooks were not merged' + } + + $yasb = Get-Content -LiteralPath (Join-Path $destination '.config\yasb\config.yaml') -Raw + if ($yasb -match 'C:\\Users\\(?:HP|takow)') { + throw 'YASB contains a hard-coded user profile' + } + + $links = @{ + (Join-Path $destination '.config\lazygit') = (Join-Path $PWD 'mutable\shared\lazygit') + (Join-Path $destination '.config\zed') = (Join-Path $PWD 'mutable\shared\zed') + (Join-Path $destination '.gitconfig') = (Join-Path $PWD 'mutable\shared\gitconfig') + } + foreach ($target in $links.Keys) { + $item = Get-Item -LiteralPath $target -Force + if (-not $item.LinkType) { + throw "Expected symbolic link: $target" + } + if ([IO.Path]::GetFullPath([string]$item.Target) -ne [IO.Path]::GetFullPath($links[$target])) { + throw "Unexpected symbolic link target: $target -> $($item.Target)" + } + } + + $nativeLinks = @{ + (Join-Path $env:CHEZMOI_WINDOWS_APPDATA 'yazi\config\yazi.toml') = (Join-Path $destination '.config\yazi\yazi.toml') + (Join-Path $env:CHEZMOI_WINDOWS_APPDATA 'Zed\settings.json') = (Join-Path $PWD 'mutable\shared\zed\settings.json') + (Join-Path $env:CHEZMOI_WINDOWS_DOCUMENTS 'PowerShell\Microsoft.PowerShell_profile.ps1') = (Join-Path $destination 'Documents\PowerShell\Microsoft.PowerShell_profile.ps1') + } + foreach ($target in $nativeLinks.Keys) { + $item = Get-Item -LiteralPath $target -Force + if (-not $item.LinkType) { + throw "Expected native symbolic link: $target" + } + if ([IO.Path]::GetFullPath([string]$item.Target) -ne [IO.Path]::GetFullPath($nativeLinks[$target])) { + throw "Unexpected native symbolic link target: $target -> $($item.Target)" + } + } + + $codexConfig = Join-Path $destination '.codex\config.toml' + Add-Content -LiteralPath $codexConfig -Value "`n# preserve-existing-config" + chezmoi --source $PWD --destination $destination --force --no-tty apply + if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } + if (-not (Select-String -LiteralPath $codexConfig -SimpleMatch '# preserve-existing-config' -Quiet)) { + throw 'chezmoi overwrote the existing Codex config' + } + + - name: Parse PowerShell sources + shell: pwsh + run: | + $parseErrors = @() + $files = Get-ChildItem -Path scripts, chezmoi -Filter '*.ps1' -Recurse -File + foreach ($file in $files) { + $tokens = $null + $errors = $null + [Management.Automation.Language.Parser]::ParseFile($file.FullName, [ref]$tokens, [ref]$errors) | Out-Null + foreach ($error in $errors) { + $parseErrors += "$($file.FullName): $($error.Message)" + } + } + if ($parseErrors.Count -gt 0) { + throw ($parseErrors -join "`n") + } + + contract: + name: Contract + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install Nix + uses: cachix/install-nix-action@v31 + with: + extra_nix_config: | + experimental-features = nix-command flakes + + - name: Check profiles and ownership + run: nix develop --command bash scripts/check_chezmoi.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 328d82d..be98b7e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,73 +2,61 @@ name: Checks on: push: + branches: + - master + pull_request: workflow_dispatch: -jobs: - syntax: - name: Nix syntax - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Install Nix - uses: cachix/install-nix-action@v31 - with: - extra_nix_config: | - experimental-features = nix-command flakes - - - name: Check Nix syntax - run: | - git ls-files '*.nix' \ - | xargs -r -n1 nix-instantiate --parse --quiet >/dev/null - - nix-formatting: - name: Nix formatting - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 +permissions: + contents: read - - name: Install Nix - uses: cachix/install-nix-action@v31 - with: - extra_nix_config: | - experimental-features = nix-command flakes - - - name: Check Nix formatting - run: nix run nixpkgs#alejandra -- --check . - - markdown-lint: - name: Markdown lint - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Install Nix - uses: cachix/install-nix-action@v31 - with: - extra_nix_config: | - experimental-features = nix-command flakes - - - name: Check Markdown lint - run: nix run nixpkgs#markdownlint-cli2 -- - - lua-formatting: - name: Lua formatting +jobs: + changes: + name: Detect changes runs-on: ubuntu-latest + permissions: + contents: read + outputs: + nix_configs: ${{ steps.filter.outputs.nix_configs }} steps: - name: Checkout uses: actions/checkout@v4 - - name: Install Nix - uses: cachix/install-nix-action@v31 + - name: Detect changed paths + id: filter + uses: dorny/paths-filter@v3 with: - extra_nix_config: | - experimental-features = nix-command flakes - - - name: Check Lua formatting - run: | - git ls-files '*.lua' \ - | xargs -r nix run nixpkgs#stylua -- --check + filters: | + nix_configs: + - 'nix-configs/**' + - 'flake.nix' + - 'flake.lock' + - 'scripts/check_profiles.sh' + + lint: + name: Lint + uses: ./.github/workflows/lint.yml + + chezmoi: + name: Chezmoi + uses: ./.github/workflows/chezmoi.yml + + nixos: + name: NixOS + needs: changes + if: >- + github.event_name == 'workflow_dispatch' || + needs.changes.outputs.nix_configs == 'true' + uses: ./.github/workflows/nixos.yml + with: + hosts: ${{ github.event_name == 'push' && '["wsl","nixos-ci"]' || '["laptop","desktop","wsl","nixos-ci"]' }} + + publish-cache: + name: Publish cache + needs: changes + if: >- + github.event_name == 'push' && + github.ref == 'refs/heads/master' && + needs.changes.outputs.nix_configs == 'true' + uses: ./.github/workflows/publish-cache.yml + secrets: inherit diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..e127362 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,60 @@ +name: Lint + +on: + workflow_call: + +permissions: + contents: read + +jobs: + syntax: + name: Nix syntax + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install Nix + uses: cachix/install-nix-action@v31 + with: + extra_nix_config: | + experimental-features = nix-command flakes + + - name: Check Nix syntax + run: | + git ls-files '*.nix' \ + | xargs -r -n1 nix-instantiate --parse --quiet >/dev/null + + nix-formatting: + name: Nix formatting + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install Nix + uses: cachix/install-nix-action@v31 + with: + extra_nix_config: | + experimental-features = nix-command flakes + + - name: Check Nix formatting + run: nix run nixpkgs#alejandra -- --check . + + lua-formatting: + name: Lua formatting + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install Nix + uses: cachix/install-nix-action@v31 + with: + extra_nix_config: | + experimental-features = nix-command flakes + + - name: Check Lua formatting + run: | + git ls-files '*.lua' \ + | xargs -r nix run nixpkgs#stylua -- --check diff --git a/.github/workflows/nixos.yml b/.github/workflows/nixos.yml new file mode 100644 index 0000000..b4be596 --- /dev/null +++ b/.github/workflows/nixos.yml @@ -0,0 +1,51 @@ +name: NixOS + +on: + workflow_call: + inputs: + hosts: + description: "Build対象hostのJSON配列" + required: false + type: string + default: '["laptop","desktop","wsl","nixos-ci"]' + +permissions: + contents: read + +jobs: + contracts: + name: Profile contracts + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install Nix + uses: cachix/install-nix-action@v31 + with: + extra_nix_config: | + experimental-features = nix-command flakes + + - name: Check profile contracts + run: bash scripts/check_profiles.sh + + build: + name: Build ${{ matrix.host }} + runs-on: ubuntu-latest + timeout-minutes: 120 + strategy: + fail-fast: false + matrix: + host: ${{ fromJSON(inputs.hosts) }} + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install Nix + uses: cachix/install-nix-action@v31 + with: + extra_nix_config: | + experimental-features = nix-command flakes + + - name: Build configuration + run: nix build .#nixosConfigurations.${{ matrix.host }}.config.system.build.toplevel diff --git a/.github/workflows/publish-cache.yml b/.github/workflows/publish-cache.yml index 762acfc..f4bdf51 100644 --- a/.github/workflows/publish-cache.yml +++ b/.github/workflows/publish-cache.yml @@ -1,39 +1,27 @@ # T4ko0522/cf-edgeNix の binary cache へ NixOS closure を publish する。 -# -# 本 workflow は cf-edgeNix の scripts/publish.sh を再利用するため、 -# このリポジトリ (flake source) と cf-edgeNix を別 path で checkout して走らせる。 -# 元テンプレート: T4ko0522/cf-edgeNix:docs/templates/publish-cache.yml -# -# ── 事前準備 (Settings → Environments → production に登録) ───────────────── -# Secrets: -# CACHE_PRIVATE_KEY NAR 署名用秘密鍵 -# ADMIN_TOKEN cf-edgeNix Worker の write API Bearer -# CLOUDFLARE_API_TOKEN KV bulk write の最小権限トークン -# R2_ACCESS_KEY_ID R2 S3 API のアクセスキー (R2 dashboard → Manage R2 API tokens) -# R2_SECRET_ACCESS_KEY R2 S3 API のシークレットキー -# Variables: -# CLOUDFLARE_ACCOUNT_ID -# API_BASE_URL deploy 済み cf-edgeNix Worker の URL -# R2_BUCKET_NAME 例: cf-edgenix-nar -# KV_NAMESPACE_ID name: publish-cache on: + workflow_call: + inputs: + host: + description: "対象 host を 1 つだけ指定したい場合 (空なら matrix の全 host)" + required: false + type: string workflow_dispatch: inputs: host: description: "対象 host を 1 つだけ指定したい場合 (空なら matrix の全 host)" required: false type: string - push: - branches: [master] concurrency: group: publish-cache-${{ github.ref }} cancel-in-progress: false -permissions: {} +permissions: + contents: read jobs: publish: @@ -46,9 +34,6 @@ jobs: uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 # 常に最新の publish.sh / publish.ts (bun で publish.ts を呼ぶ) を使うため main 先端を追従する。 - # 注意: これは secret を扱う job なので、cf-edgeNix 側の任意の上流 commit が - # CACHE_PRIVATE_KEY / ADMIN_TOKEN / CLOUDFLARE_API_TOKEN を持った状態で即座に実行される。 - # cf-edgeNix は自分のリポジトリである前提でこのリスクを許容している。 - name: Checkout cf-edgeNix (publish tooling) uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: diff --git a/.github/workflows/update-codex-desktop-linux.yml b/.github/workflows/update-codex-desktop-linux.yml deleted file mode 100644 index b632965..0000000 --- a/.github/workflows/update-codex-desktop-linux.yml +++ /dev/null @@ -1,38 +0,0 @@ -name: update-codex-desktop-linux - -on: - schedule: - - cron: "15 3 * * *" - workflow_dispatch: - -permissions: - contents: write - pull-requests: write - -jobs: - update: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - - - name: Install Nix - uses: cachix/install-nix-action@b4b293eae0b79aac8a161bb32925a5508c9cca93 # v31 - with: - extra_nix_config: | - experimental-features = nix-command flakes - - - name: Update codex-desktop-linux - run: nix flake update codex-desktop-linux - - - name: Create pull request - uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8 - with: - branch: automation/update-codex-desktop-linux - delete-branch: true - commit-message: "chore: update codex-desktop-linux" - title: "chore: update codex-desktop-linux" - body: | - Updates the `codex-desktop-linux` flake input. - - This picks up upstream DMG hash refreshes and prevents publish-cache failures. diff --git a/.gitignore b/.gitignore index 367742c..e45c328 100644 --- a/.gitignore +++ b/.gitignore @@ -9,79 +9,7 @@ result result-* # lazygit -.config/shared/lazygit/state.yml - -# claude -.config/shared/claude/.claude.json -.config/shared/claude/.claude.json.backup* -.config/shared/claude/cache/ -.config/shared/claude/ide/ -.config/shared/claude/debug/ -.config/shared/claude/plugins/ -.config/shared/claude/projects/ -.config/shared/claude/session-env/ -.config/shared/claude/statsig/ -.config/shared/claude/sessions/ -.config/shared/claude/skills/ -.config/shared/claude/tasks/ -.config/shared/claude/todos/ -.config/shared/claude/file-history/ -.config/shared/claude/history.jsonl -.config/shared/claude/mcp-needs-auth-cache.json -.config/shared/claude/shell-snapshots/ -.config/shared/claude/plans/ -.config/shared/claude/stats-cache.json -.config/shared/claude/paste-cache/ -.config/shared/claude/image-cache/ -.config/shared/claude/telemetry/ -.config/shared/claude/backups/ -.config/shared/claude/.credentials.json -.config/shared/claude/.last-cleanup - -# codex -.config/shared/codex/.tmp -.config/shared/codex/.sandbox -.config/shared/codex/.sandbox* -.config/shared/codex/.codex-global-state.json -.config/shared/codex/.personality_migration -.config/shared/codex/cache/ -.config/shared/codex/log/ -.config/shared/codex/memories/ -.config/shared/codex/plugins/ -.config/shared/codex/rules/default.rules -.config/shared/codex/sessions/ -.config/shared/codex/skills/ -.config/shared/codex/sqlite/ -.config/shared/codex/tmp/ -.config/shared/codex/vendor_imports/ -.config/shared/codex/auth.json -.config/shared/codex/cap_sid -.config/shared/codex/config.toml.bak-* -.config/shared/codex/history.jsonl -.config/shared/codex/logs_1.sqlite -.config/shared/codex/goals_* -.config/shared/codex/logs_1.sqlite* -.config/shared/codex/models_cache.json -.config/shared/codex/sandbox.log -.config/shared/codex/session_index.jsonl -.config/shared/codex/state_*.sqlite -.config/shared/codex/state_*.sqlite* -.config/shared/codex/version.json -.config/shared/codex/installation_id -.config/shared/codex/logs_2.sqlite -.config/shared/codex/logs_2.sqlite-shm -.config/shared/codex/logs_2.sqlite-wal -.config/shared/codex/.codex-global-state.json.bak - -# zsh -.config/nixos/zsh/**/*.zwc - -# PowerShell (Install-Module で入るモジュール) -.config/windows/powershell/Modules/ - -# yasb -.config/windows/yasb/yasb.log -.config/windows/yasb/.env +mutable/shared/lazygit/state.yml # Cloudflare Wrangler .wrangler/* diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 4a19b10..0000000 --- a/.gitmodules +++ /dev/null @@ -1,5 +0,0 @@ -[submodule "corne"] - path = corne - url = https://github.com/t4ko0522/corne_v4.git - branch = main - update = merge diff --git a/.markdownlint-cli2.jsonc b/.markdownlint-cli2.jsonc deleted file mode 100644 index a0dcbae..0000000 --- a/.markdownlint-cli2.jsonc +++ /dev/null @@ -1,37 +0,0 @@ -{ - // markdownlint ルール本体 - // ルール一覧: https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md - "config": { - "default": true, - // 日本語ドキュメント向けに無効化するルール - "MD013": false, // line-length: 日本語では行長制限は無意味 - "MD033": false, // no-inline-html:
/
等を README で使う - "MD034": false, // no-bare-urls: 日本語混じりで自動リンク化が崩れやすい - "MD036": false, // no-emphasis-as-heading: 強調を疑似見出しに使うことがある - "MD041": false, // first-line-h1: YAML frontmatter を持つ agent 定義のため - "MD026": false, // no-trailing-punctuation: 日本語見出しの「?」「!」等を許可 - // 兄弟見出しのみ重複検査(章をまたいで同名見出しが出るのを許容) - "MD024": { - "siblings_only": true - }, - // 既存 md との互換のため緩和 - "MD025": false, // single-title: H1 を 1 ファイル 1 つに強制しない - "MD040": false, // fenced-code-language: ``` の言語指定を強制しない - "MD060": false // table-column-style: テーブル列スタイルの統一を強制しない - }, - // 対象ファイル - "globs": [ - "**/*.md" - ], - // 除外パターン - "ignores": [ - "node_modules/**", - ".git/**", - ".config/claude/projects/**", - ".config/claude/cache/**", - ".config/claude/backups/**", - ".config/shared/lazygit/README.md" - ], - // .gitignore の除外を反映 - "gitignore": true -} diff --git a/AGENTS.md b/AGENTS.md index 0ea697c..80b4dce 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -25,12 +25,12 @@ GitHub Actions は `.github/workflows/checks.yml` で以下を実行します。 ## 構成 - `flake.nix`: flake inputs と `nixosConfigurations` を定義します。 -- `nix-configs/hosts/`: ホスト別の構成入口です。`laptop/`・`desktop/` があり、各 `default.nix` と `hardware-configuration.nix` を持ちます。自動生成由来の hardware 設定は目的なしに整理しないでください。 -- `nix-configs/configuration-ci.nix`: CI build 用の最小構成です。 -- `nix-configs/modules/`: NixOS 共通基盤モジュールです。 -- `nix-configs/profiles/`: desktop、gaming、nvidia など用途別の NixOS profile です。 +- `nix-configs/hosts/`: ホスト別の構成入口です。`laptop/`・`desktop/`・`wsl/`があります。物理ホストの自動生成由来のhardware設定は目的なしに整理しないでください。 +- `nix-configs/hosts/ci/`: CI build 用の最小構成です。 +- `nix-configs/feature/modules/`: NixOS の単一機能モジュールです。 +- `nix-configs/feature/profiles/`: base、workstation、gaming など用途別の NixOS profile です。 - `nix-configs/home/`: Home Manager 設定です。 -- `nix-configs/home/packages/`: Home Manager の package group です。 +- `nix-configs/home/modules/packages/`: Home Manager の package group です。 - `corne/`: Corne キーボード関連の設定、keymap、生成スクリプトです。 - `docs/`: keybindings などのドキュメントです。 @@ -40,26 +40,27 @@ GitHub Actions は `.github/workflows/checks.yml` で以下を実行します。 - `nixosConfigurations.laptop`: laptop ホスト構成 - `nixosConfigurations.desktop`: desktop ホスト構成 +- `nixosConfigurations.wsl`: NixOS-WSL 用の CLI 構成 - `nixosConfigurations.default`: `laptop` の alias - `nixosConfigurations.nixos-ci`: CI 用構成 - `devShells.x86_64-linux.default`: QMK/Vial 作業用 shell -`specialArgs` と Home Manager の `extraSpecialArgs` には `dotfilesDir` と `keyboardLayout` が渡されています。これらが必要な module では、ハードコードを増やさず既存の引数を使ってください。 +`specialArgs`とHome Managerの`extraSpecialArgs`には`dotfilesDir`、`keyboardLayout`、`username`、`homeDirectory`などが渡されています。これらが必要なmoduleでは、ハードコードを増やさず既存の引数を使ってください。 ## ファイル配置ルール -- `nix-configs/modules/` は複数構成で共有する NixOS 基盤設定を置きます。 -- `nix-configs/modules/default.nix` は modules の入口です。基本的に child module の import に留めます。 -- `nix-configs/modules/*.nix` は 1 ファイル 1 責務を保ちます。例: `kernel.nix` は kernel、`locale.nix` は locale、`qmk.nix` は udev/QMK。 -- `nix-configs/profiles/` は用途別の機能 bundle です。desktop/gaming/nvidia など、常に全構成へ入れるべきでない設定を置きます。 -- `nix-configs/home/packages/*.nix` は目的別の `home.packages` group です。CLI、development、gaming など既存分類に合わせてください。 +- `nix-configs/feature/modules/` は複数構成で共有する単一機能の NixOS 設定を置きます。module から profile を import しません。 +- `nix-configs/feature/profiles/` は用途別の機能 bundle です。module の実装を持たず、原則として imports で構成します。 +- `nix-configs/home/modules/` は単一の Home Manager 機能、`nix-configs/home/profiles/` はその bundle を置きます。 +- `nix-configs/home/modules/packages/*.nix` は目的別の `home.packages` group です。CLI、development、gaming など既存分類に合わせてください。 +- `nix-configs/pkgs/` は derivation のみを置き、feature/Home module 内で package を定義しません。 - 新しい Nix ファイルは、参照元の `imports` に必ず追加してください。flake 評価で使う新規ファイルは Git に track されている必要があります。 ## Claude Code の skill 管理 (apm) -- skill の source は `.config/shared/apm/packages//.apm/skills//` に置き、apm (Agent Package Manager) で管理します。カテゴリ (`agent-llm`・`docs`・`git-ops` など) は local apm package で、root の `apm.yml` が `dependencies.apm: [./packages/]` として参照します。 +- skill の source は `mutable/shared/apm/packages//.apm/skills//` に置き、apm (Agent Package Manager) で管理します。カテゴリ (`agent-llm`・`docs`・`git-ops` など) は local apm package で、root の `apm.yml` が `dependencies.apm: [./packages/]` として参照します。 - 新しいカテゴリを追加する場合は `packages//apm.yml` を作成し、root の `apm.yml` の `dependencies.apm` へ追記してください。apm と Claude Code はどちらも skill のネスト配置に非対応のため、deploy 先はフラット (`.claude/skills//`) になります。skill 名はカテゴリを跨いで一意にしてください。 -- `apm install` (home-manager activation で自動実行、手動は `just skills-sync`) が各 package と外部依存を `.config/shared/apm/.claude/skills/` へ deploy します。 +- `apm install` (home-manager activation で自動実行、手動は `just skills-sync`) が各 package と外部依存を `mutable/shared/apm/.claude/skills/` へ deploy します。 - 外部 skill も root の `apm.yml` の `dependencies.apm` に追加できます。現在は `mizchi/skills` の一部 (nix-setup・justfile・apm-usage・conventional-changelog・gh-fix-ci・cloudflare/deploy・workers-otel-utels) を取り込んでいます。HEAD が動くため必ず `#` でピンし、更新時は SHA を差し替えて `apm install` で lockfile を再生成してください。 - 生成物 (`.claude/skills/`・`apm_modules/`) は gitignore されています。`~/.claude/skills` は生成物への symlink なので、skill の追加・編集は必ず source 側で行ってください。 - `apm.lock.yaml` は外部依存のバージョン固定のため **追跡** しています (gitignore しない)。`dependencies.apm` を変更したら `apm install` を実行し、更新後の lockfile も併せてコミットしてください。 @@ -76,7 +77,7 @@ GitHub Actions は `.github/workflows/checks.yml` で以下を実行します。 - ユーザーの未 commit 変更を勝手に戻さないでください。 - `flake.lock` の `"version": 7` は lock file 形式のバージョンです。Linux kernel version ではありません。 -- Home Manager package を追加する場合は、system package と user package のどちらに置くべきか確認してください。個人用 GUI/CLI は通常 `nix-configs/home/packages/` 側です。 +- Home Manager package を追加する場合は、system package と user package のどちらに置くべきか確認してください。個人用 GUI/CLI は通常 `nix-configs/home/modules/packages/` 側です。 - `dogdns` のように nixpkgs で削除済みの package は、評価エラーの案内に従って代替 package を使ってください。 - secrets や token を tracked file に追加しないでください。 @@ -94,4 +95,5 @@ package 追加や NixOS module 変更では、必要に応じて以下も確認 ```sh nix eval .#nixosConfigurations.default.config.home-manager.users.t4ko.home.packages --apply 'xs: builtins.length xs' nix eval .#nixosConfigurations.default.config.boot.kernelPackages.kernel.version --raw +just wsl-check ``` diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 100644 index 93302cd..0000000 --- a/CLAUDE.md +++ /dev/null @@ -1 +0,0 @@ -./AGENTS.md diff --git a/README.md b/README.md index 9547bb8..ee1ba0e 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Dotfiles -NixOSとWindowsの環境を管理しているdotfiles. +NixOS、NixOS-WSL、Windowsの環境を管理しているdotfiles. ## Nix @@ -28,3 +28,23 @@ NixOSとWindowsの環境を管理しているdotfiles. ``` Inspired by [akazdayo/nix-configs](https://github.com/akazdayo/nix-configs), [moons-14/dotfiles](https://github.com/moons-14/dotfiles), [mozumasu/dotfiles](https://github.com/mozumasu/dotfiles). + +NixOSの再構築後にchezmoi profileを適用し、Home Managerの対象外へ移したdotfileも配置する。 + +```sh +just os-switch laptop +``` + +## NixOS-WSL + +NixOS-WSLの初期イメージ内でこのリポジトリをcloneし、NixOS構成とchezmoiの`wsl` profileを適用する。 + +```sh +just wsl-switch +``` + +WSL構成は`t4ko`ユーザー、Windows interop、CLI用Home Manager profileを有効にする。desktop packageとNeovim設定は含まない。 + +```sh +just wsl-check +``` diff --git a/image.png b/assets/windows.png similarity index 100% rename from image.png rename to assets/windows.png diff --git a/chezmoi/.chezmoi.toml.tmpl b/chezmoi/.chezmoi.toml.tmpl new file mode 100644 index 0000000..18eadd7 --- /dev/null +++ b/chezmoi/.chezmoi.toml.tmpl @@ -0,0 +1,5 @@ +{{- $profiles := list "windows" "nixos" "wsl" -}} +{{- $profile := promptChoiceOnce . "profile" "Environment profile" $profiles "nixos" -}} +[data] +profile = {{ $profile | quote }} +username = "t4ko" diff --git a/chezmoi/.chezmoiignore b/chezmoi/.chezmoiignore new file mode 100644 index 0000000..13a444a --- /dev/null +++ b/chezmoi/.chezmoiignore @@ -0,0 +1,28 @@ +{{- if ne .profile "windows" }} +AppData/** +Documents/PowerShell/** +.config/ccwin-notify/** +.config/mise/** +.config/yasb/** +.claude/ccwin-hook.ps1 +.codex/config.toml +{{- end }} + +{{- if ne .profile "nixos" }} +.claude/claude-notify-hook.sh +{{- end }} + +{{- if eq .profile "windows" }} +.config/niri/** +.config/swaync/** +.config/waybar/** +{{- end }} + +{{- if eq .profile "wsl" }} +.config/wezterm/** +.config/zed +{{- end }} + +# Neovim is never a shared chezmoi target. Windows uses a junction to +# mutable/nvim; NixOS uses nixvim; WSL leaves it unmanaged. +.config/nvim/** diff --git a/.config/shared/claude/settings.json b/chezmoi/.chezmoitemplates/claude-settings-base.json similarity index 100% rename from .config/shared/claude/settings.json rename to chezmoi/.chezmoitemplates/claude-settings-base.json diff --git a/.config/nixos/claude/settings.hooks.json b/chezmoi/.chezmoitemplates/claude-settings-nixos-hooks.json similarity index 100% rename from .config/nixos/claude/settings.hooks.json rename to chezmoi/.chezmoitemplates/claude-settings-nixos-hooks.json diff --git a/.config/windows/claude/settings.hooks.json b/chezmoi/.chezmoitemplates/claude-settings-windows-hooks.json similarity index 100% rename from .config/windows/claude/settings.hooks.json rename to chezmoi/.chezmoitemplates/claude-settings-windows-hooks.json diff --git a/.config/shared/codex/config.toml b/chezmoi/.chezmoitemplates/codex-config.toml similarity index 100% rename from .config/shared/codex/config.toml rename to chezmoi/.chezmoitemplates/codex-config.toml diff --git a/chezmoi/.chezmoiversion b/chezmoi/.chezmoiversion new file mode 100644 index 0000000..38a7743 --- /dev/null +++ b/chezmoi/.chezmoiversion @@ -0,0 +1 @@ +2.70.0 diff --git a/.config/windows/powershell/Microsoft.PowerShell_profile.ps1 b/chezmoi/Documents/PowerShell/Microsoft.PowerShell_profile.ps1 similarity index 100% rename from .config/windows/powershell/Microsoft.PowerShell_profile.ps1 rename to chezmoi/Documents/PowerShell/Microsoft.PowerShell_profile.ps1 diff --git a/.config/windows/powershell/conf.d/aliases.ps1 b/chezmoi/Documents/PowerShell/conf.d/aliases.ps1 similarity index 100% rename from .config/windows/powershell/conf.d/aliases.ps1 rename to chezmoi/Documents/PowerShell/conf.d/aliases.ps1 diff --git a/.config/windows/powershell/conf.d/keybindings.ps1 b/chezmoi/Documents/PowerShell/conf.d/keybindings.ps1 similarity index 100% rename from .config/windows/powershell/conf.d/keybindings.ps1 rename to chezmoi/Documents/PowerShell/conf.d/keybindings.ps1 diff --git a/.config/windows/powershell/conf.d/mise.ps1 b/chezmoi/Documents/PowerShell/conf.d/mise.ps1 similarity index 100% rename from .config/windows/powershell/conf.d/mise.ps1 rename to chezmoi/Documents/PowerShell/conf.d/mise.ps1 diff --git a/.config/windows/powershell/conf.d/navigation.ps1 b/chezmoi/Documents/PowerShell/conf.d/navigation.ps1 similarity index 100% rename from .config/windows/powershell/conf.d/navigation.ps1 rename to chezmoi/Documents/PowerShell/conf.d/navigation.ps1 diff --git a/.config/windows/powershell/conf.d/startup.ps1 b/chezmoi/Documents/PowerShell/conf.d/startup.ps1 similarity index 55% rename from .config/windows/powershell/conf.d/startup.ps1 rename to chezmoi/Documents/PowerShell/conf.d/startup.ps1 index 9710a78..14fed56 100644 --- a/.config/windows/powershell/conf.d/startup.ps1 +++ b/chezmoi/Documents/PowerShell/conf.d/startup.ps1 @@ -16,40 +16,6 @@ Register-EngineEvent -SourceIdentifier PowerShell.OnIdle -MaxTriggerCount 1 -Act # https://github.com/antfu-collective/ni とNew-Itemの競合を無効化 Remove-Item Alias:ni -Force -ErrorAction Ignore -# モニター構成変更後の手動再セットアップ。 -# pwsh 起動後にモニターを抜き差ししたとき、display_index_preferences を実機に -# 合わせて patch し直すには komorebi 自体を起こし直す必要があるためのショートカット。 -function Restart-Komorebi { - $startScript = "$env:USERPROFILE\Project\github.com\t4ko0522\dotfiles\.config\komorebi\komorebi_start.ps1" - if (-not (Test-Path -LiteralPath $startScript)) { - Write-Error "komorebi_start.ps1 が見つかりません: $startScript" - return - } - Get-Process -Name komorebi, whkd -ErrorAction SilentlyContinue | Stop-Process -Force -ErrorAction SilentlyContinue - & $startScript -} - -# komorebi + whkd 自動起動 (接続モニターに合わせた一時設定で起動) -# プロセス存在だけで判定するとゾンビ時に skip してしまうため、socket 応答で生死判定する。 -# 起動本体は別プロセス(pwsh -NoProfile)に投げて profile 読み込みをブロックしない。 -if (Get-Command komorebic -ErrorAction SilentlyContinue) { - $komorebiAlive = $false - if (Get-Process -Name komorebi -ErrorAction SilentlyContinue) { - komorebic state 2>$null | Out-Null - $komorebiAlive = ($LASTEXITCODE -eq 0) - } - if (-not $komorebiAlive) { - # ゾンビ komorebi/whkd を掃除してから起動 - Get-Process -Name komorebi, whkd -ErrorAction SilentlyContinue | Stop-Process -Force -ErrorAction SilentlyContinue - $startScript = "$env:USERPROFILE\Project\github.com\t4ko0522\dotfiles\.config\komorebi\komorebi_start.ps1" - if (Test-Path -LiteralPath $startScript) { - Start-Process -FilePath 'pwsh' -ArgumentList '-NoLogo', '-NoProfile', '-NonInteractive', '-WindowStyle', 'Hidden', '-File', $startScript -WindowStyle Hidden - } else { - Start-Process komorebic -ArgumentList 'start', '--whkd' -WindowStyle Hidden - } - } -} - # yasb 自動起動 if (-not (Get-Process -Name yasb -ErrorAction SilentlyContinue)) { Start-Process yasb -WindowStyle Hidden @@ -84,4 +50,4 @@ if (Get-Command starship -ErrorAction SilentlyContinue) { $initScript | Set-Content -LiteralPath $starshipCache -Encoding UTF8 Invoke-Expression $initScript } -} \ No newline at end of file +} diff --git a/.config/windows/ccwin-notify/config.toml b/chezmoi/dot_config/ccwin-notify/config.toml similarity index 100% rename from .config/windows/ccwin-notify/config.toml rename to chezmoi/dot_config/ccwin-notify/config.toml diff --git a/.config/shared/fastfetch/anime.txt b/chezmoi/dot_config/fastfetch/anime.txt similarity index 100% rename from .config/shared/fastfetch/anime.txt rename to chezmoi/dot_config/fastfetch/anime.txt diff --git a/.config/shared/fastfetch/config.jsonc b/chezmoi/dot_config/fastfetch/config.jsonc similarity index 100% rename from .config/shared/fastfetch/config.jsonc rename to chezmoi/dot_config/fastfetch/config.jsonc diff --git a/.config/shared/fastfetch/mclaren.txt b/chezmoi/dot_config/fastfetch/mclaren.txt similarity index 95% rename from .config/shared/fastfetch/mclaren.txt rename to chezmoi/dot_config/fastfetch/mclaren.txt index bd33b7e..d872dd9 100644 --- a/.config/shared/fastfetch/mclaren.txt +++ b/chezmoi/dot_config/fastfetch/mclaren.txt @@ -13,4 +13,4 @@ $1 =@@@@@@%+. $1 :%@@@%*- $1 -%@@#=. $1 +@%+: -$1 :: \ No newline at end of file +$1 :: diff --git a/.config/shared/fastfetch/show_music.py b/chezmoi/dot_config/fastfetch/show_music.py similarity index 100% rename from .config/shared/fastfetch/show_music.py rename to chezmoi/dot_config/fastfetch/show_music.py diff --git a/.config/shared/fastfetch/windows.txt b/chezmoi/dot_config/fastfetch/windows.txt similarity index 94% rename from .config/shared/fastfetch/windows.txt rename to chezmoi/dot_config/fastfetch/windows.txt index ca92a29..0e6953f 100644 --- a/.config/shared/fastfetch/windows.txt +++ b/chezmoi/dot_config/fastfetch/windows.txt @@ -13,4 +13,4 @@ E::::::::zt33L @EEEtttt::::z3F {3=*^```"*4E3) ;EEEtttt:::::tZ` ` :EEEEtttt::::z7 - "VEzjt:;;z>*` \ No newline at end of file + "VEzjt:;;z>*` diff --git a/.config/windows/mise/config.toml b/chezmoi/dot_config/mise/config.toml similarity index 95% rename from .config/windows/mise/config.toml rename to chezmoi/dot_config/mise/config.toml index 658f63f..fd9b1de 100644 --- a/.config/windows/mise/config.toml +++ b/chezmoi/dot_config/mise/config.toml @@ -57,8 +57,6 @@ kubectl = "latest" "npm:oxfmt" = "latest" "npm:sdd-mcp" = "latest" "npm:vde-layout" = "0.0.9" -"npm:markdownlint-cli" = "latest" -"npm:markdownlint-cli2" = "latest" "npm:@openai/codex" = "latest" [settings] diff --git a/.config/shared/starship.toml b/chezmoi/dot_config/starship.toml similarity index 100% rename from .config/shared/starship.toml rename to chezmoi/dot_config/starship.toml diff --git a/chezmoi/dot_config/symlink_lazygit.tmpl b/chezmoi/dot_config/symlink_lazygit.tmpl new file mode 100644 index 0000000..93bae2c --- /dev/null +++ b/chezmoi/dot_config/symlink_lazygit.tmpl @@ -0,0 +1 @@ +{{ .chezmoi.sourceDir }}/../mutable/shared/lazygit diff --git a/chezmoi/dot_config/symlink_zed.tmpl b/chezmoi/dot_config/symlink_zed.tmpl new file mode 100644 index 0000000..1acf5b6 --- /dev/null +++ b/chezmoi/dot_config/symlink_zed.tmpl @@ -0,0 +1 @@ +{{ .chezmoi.sourceDir }}/../mutable/shared/zed diff --git a/.config/shared/vim/vimrc b/chezmoi/dot_config/vim/vimrc similarity index 100% rename from .config/shared/vim/vimrc rename to chezmoi/dot_config/vim/vimrc diff --git a/.config/shared/wezterm/appearance.lua b/chezmoi/dot_config/wezterm/appearance.lua similarity index 100% rename from .config/shared/wezterm/appearance.lua rename to chezmoi/dot_config/wezterm/appearance.lua diff --git a/.config/shared/wezterm/keymaps.lua b/chezmoi/dot_config/wezterm/keymaps.lua similarity index 98% rename from .config/shared/wezterm/keymaps.lua rename to chezmoi/dot_config/wezterm/keymaps.lua index cc582a3..1f9d0cc 100644 --- a/.config/shared/wezterm/keymaps.lua +++ b/chezmoi/dot_config/wezterm/keymaps.lua @@ -58,8 +58,7 @@ return { { key = "c", mods = "CTRL", action = act.CopyTo("Clipboard") }, -- 貼り付け { key = "v", mods = "CTRL", action = act.PasteFrom("Clipboard") }, - -- Ctrl+Shift+V を F24 として Neovim に送る(Markdown プレビュー トグル用、衝突回避) - { key = "v", mods = "CTRL|SHIFT", action = act.SendKey({ key = "F24" }) }, + { key = "v", mods = "CTRL|SHIFT", action = act.PasteFrom("Clipboard") }, -- Pane操作: Alt+q を押してモードに入り、hjkl 等を連続で押せる(Esc またはタイムアウトで抜ける) { diff --git a/.config/shared/wezterm/modules/claude_status.lua b/chezmoi/dot_config/wezterm/modules/claude_status.lua similarity index 100% rename from .config/shared/wezterm/modules/claude_status.lua rename to chezmoi/dot_config/wezterm/modules/claude_status.lua diff --git a/.config/shared/wezterm/modules/opacity.lua b/chezmoi/dot_config/wezterm/modules/opacity.lua similarity index 100% rename from .config/shared/wezterm/modules/opacity.lua rename to chezmoi/dot_config/wezterm/modules/opacity.lua diff --git a/.config/shared/wezterm/modules/wsl.lua b/chezmoi/dot_config/wezterm/modules/wsl.lua similarity index 100% rename from .config/shared/wezterm/modules/wsl.lua rename to chezmoi/dot_config/wezterm/modules/wsl.lua diff --git a/.config/shared/wezterm/statusbar.lua b/chezmoi/dot_config/wezterm/statusbar.lua similarity index 100% rename from .config/shared/wezterm/statusbar.lua rename to chezmoi/dot_config/wezterm/statusbar.lua diff --git a/.config/shared/wezterm/tab.lua b/chezmoi/dot_config/wezterm/tab.lua similarity index 100% rename from .config/shared/wezterm/tab.lua rename to chezmoi/dot_config/wezterm/tab.lua diff --git a/.config/shared/wezterm/wezterm.lua b/chezmoi/dot_config/wezterm/wezterm.lua similarity index 100% rename from .config/shared/wezterm/wezterm.lua rename to chezmoi/dot_config/wezterm/wezterm.lua diff --git a/.config/shared/wezterm/workspace.lua b/chezmoi/dot_config/wezterm/workspace.lua similarity index 100% rename from .config/shared/wezterm/workspace.lua rename to chezmoi/dot_config/wezterm/workspace.lua diff --git a/.config/windows/yasb/config.yaml b/chezmoi/dot_config/yasb/config.yaml.tmpl similarity index 91% rename from .config/windows/yasb/config.yaml rename to chezmoi/dot_config/yasb/config.yaml.tmpl index 395006c..599835f 100644 --- a/.config/windows/yasb/config.yaml +++ b/chezmoi/dot_config/yasb/config.yaml.tmpl @@ -1,10 +1,6 @@ watch_stylesheet: true watch_config: true debug: false -komorebi: - start_command: "komorebic start" - stop_command: "komorebic stop" - reload_command: "komorebic stop && komorebic start" bars: status-bar: enabled: true @@ -53,7 +49,6 @@ bars: right: [ "weather", - "komorebi_workspaces", "clock", "cava", "media", @@ -63,19 +58,6 @@ bars: "power_menu" ] widgets: - komorebi_workspaces: - type: "komorebi.workspaces.WorkspaceWidget" - options: - label_offline: "komorebi offline" - label_workspace_btn: "{index}" - label_workspace_active_btn: "{index}" - label_workspace_populated_btn: "{index}" - label_default_name: "{index}" - label_zero_index: false - hide_empty_workspaces: false - hide_if_offline: true - animation: true - enable_scroll_switching: true glazewm_workspaces: type: "glazewm.workspaces.GlazewmWorkspacesWidget" options: @@ -90,7 +72,7 @@ widgets: label_placeholder: "👋 Hi there!" class_name: "greeting-widget" exec_options: - run_cmd: "powershell.exe -NoProfile -ExecutionPolicy Bypass -File C:\\Users\\takow\\.config\\yasb\\greeting.ps1" + run_cmd: "powershell.exe -NoProfile -ExecutionPolicy Bypass -File {{ .chezmoi.destDir | toString | replace "\\" "\\\\" }}\\.config\\yasb\\greeting.ps1" run_interval: 60000 return_format: "string" hide_empty: false @@ -99,7 +81,7 @@ widgets: type: "yasb.wallpapers.WallpapersWidget" options: label: "\uf03e" - image_path: "C:\\Users\\HP\\Pictures\\Wallpapers" + image_path: "{{ .chezmoi.destDir | toString | replace "\\" "\\\\" }}\\Pictures\\Wallpapers" change_automatically: false # Automatically change wallpaper update_interval: 60 gallery: @@ -141,10 +123,10 @@ widgets: label: "\udb80\udf5c" menu_list: - { title: "Home", path: "~" } - - { title: "Downloads", path: "C:\\Users\\HP\\Downloads"} - - { title: "Documents", path: "C:\\Users\\HP\\Documents"} - - { title: "Pictures", path: "C:\\Users\\HP\\Pictures"} - - { title: "Videos", path: "C:\\Users\\HP\\Videos"} + - { title: "Downloads", path: "{{ .chezmoi.destDir | toString | replace "\\" "\\\\" }}\\Downloads"} + - { title: "Documents", path: "{{ .chezmoi.destDir | toString | replace "\\" "\\\\" }}\\Documents"} + - { title: "Pictures", path: "{{ .chezmoi.destDir | toString | replace "\\" "\\\\" }}\\Pictures"} + - { title: "Videos", path: "{{ .chezmoi.destDir | toString | replace "\\" "\\\\" }}\\Videos"} system_menu: true power_menu: false blur: true @@ -249,10 +231,10 @@ widgets: label: "{icon} {level}" label_alt: "{volume}" volume_icons: - - "\ueee8" + - "\ueee8" - "\uf026" - - "\uf027" - - "\uf027" + - "\uf027" + - "\uf027" - "\uf028" audio_menu: blur: True @@ -325,7 +307,7 @@ widgets: label_alt: "\uf473" group_label: volume_labels: ["C", "D", "E", "F"] - show_label_name: true + show_label_name: true blur: True round_corners: True round_corners_type: "normal" diff --git a/.config/windows/yasb/greeting.ps1 b/chezmoi/dot_config/yasb/greeting.ps1 similarity index 100% rename from .config/windows/yasb/greeting.ps1 rename to chezmoi/dot_config/yasb/greeting.ps1 diff --git a/.config/windows/yasb/styles.css b/chezmoi/dot_config/yasb/styles.css similarity index 94% rename from .config/windows/yasb/styles.css rename to chezmoi/dot_config/yasb/styles.css index cabcff7..ed6faa4 100644 --- a/.config/windows/yasb/styles.css +++ b/chezmoi/dot_config/yasb/styles.css @@ -125,42 +125,6 @@ border-radius: 5px; } -/***--------------------------------- • Komorebi Workspaces • ---------------------------***/ - -.komorebi-workspaces { - margin: 0; -} -.komorebi-workspaces .widget-container { - background-color: var(--mantle); - margin: 3px 0px 3px 0px; - border-radius: 8px; - padding: 0 4px; -} -.komorebi-workspaces .offline-status { - color: var(--text); - font-size: 12px; - padding: 0 8px; - font-weight: 600; -} -.komorebi-workspaces .ws-btn { - border: none; - background-color: transparent; - color: var(--overlay0); - margin: 0 2px; - padding: 0 6px; - border-radius: 4px; - font-size: 12px; - min-width: 16px; -} -.komorebi-workspaces .ws-btn.populated { - color: var(--subtext0); -} -.komorebi-workspaces .ws-btn.active { - color: var(--base); - background-color: var(--mauve); - font-weight: 700; -} - /***--------------------------------- • Audio Widget • ----------------------------------***/ .audio-menu { @@ -611,9 +575,9 @@ color: rgb(203, 166, 247); color: rgb(203, 166, 247); font-size: 24px; font-weight: 600; - padding: 10px 0 20px 0; + padding: 10px 0 20px 0; } -.notes-menu .add-button, +.notes-menu .add-button, .notes-menu .cancel-button { padding: 8px; background-color: rgba(255, 255, 255, 0.1); @@ -630,8 +594,8 @@ color: rgb(203, 166, 247); background-color: rgba(255, 255, 255, 0.2); } .notes-menu .scroll-area { - background: transparent; - border: none; + background: transparent; + border: none; border-radius:0; } .notes-menu .note-input { diff --git a/.config/shared/yazi/keymap.toml b/chezmoi/dot_config/yazi/keymap.toml similarity index 100% rename from .config/shared/yazi/keymap.toml rename to chezmoi/dot_config/yazi/keymap.toml diff --git a/.config/shared/yazi/theme.toml b/chezmoi/dot_config/yazi/theme.toml similarity index 100% rename from .config/shared/yazi/theme.toml rename to chezmoi/dot_config/yazi/theme.toml diff --git a/.config/shared/yazi/yazi.toml b/chezmoi/dot_config/yazi/yazi.toml similarity index 100% rename from .config/shared/yazi/yazi.toml rename to chezmoi/dot_config/yazi/yazi.toml diff --git a/.config/shared/claude/CLAUDE.md b/chezmoi/private_dot_claude/CLAUDE.md similarity index 100% rename from .config/shared/claude/CLAUDE.md rename to chezmoi/private_dot_claude/CLAUDE.md diff --git a/.config/shared/claude/agents/README.md b/chezmoi/private_dot_claude/agents/README.md similarity index 100% rename from .config/shared/claude/agents/README.md rename to chezmoi/private_dot_claude/agents/README.md diff --git a/.config/shared/claude/agents/at-analyzer.md b/chezmoi/private_dot_claude/agents/at-analyzer.md similarity index 100% rename from .config/shared/claude/agents/at-analyzer.md rename to chezmoi/private_dot_claude/agents/at-analyzer.md diff --git a/.config/shared/claude/agents/at-doc-auditor.md b/chezmoi/private_dot_claude/agents/at-doc-auditor.md similarity index 100% rename from .config/shared/claude/agents/at-doc-auditor.md rename to chezmoi/private_dot_claude/agents/at-doc-auditor.md diff --git a/.config/shared/claude/agents/at-doc-reviewer-codex.md b/chezmoi/private_dot_claude/agents/at-doc-reviewer-codex.md similarity index 100% rename from .config/shared/claude/agents/at-doc-reviewer-codex.md rename to chezmoi/private_dot_claude/agents/at-doc-reviewer-codex.md diff --git a/.config/shared/claude/agents/at-doc-reviewer-opus.md b/chezmoi/private_dot_claude/agents/at-doc-reviewer-opus.md similarity index 100% rename from .config/shared/claude/agents/at-doc-reviewer-opus.md rename to chezmoi/private_dot_claude/agents/at-doc-reviewer-opus.md diff --git a/.config/shared/claude/agents/at-doc-writer.md b/chezmoi/private_dot_claude/agents/at-doc-writer.md similarity index 100% rename from .config/shared/claude/agents/at-doc-writer.md rename to chezmoi/private_dot_claude/agents/at-doc-writer.md diff --git a/.config/shared/claude/agents/at-explorer.md b/chezmoi/private_dot_claude/agents/at-explorer.md similarity index 100% rename from .config/shared/claude/agents/at-explorer.md rename to chezmoi/private_dot_claude/agents/at-explorer.md diff --git a/.config/shared/claude/agents/at-impl-reviewer-codex.md b/chezmoi/private_dot_claude/agents/at-impl-reviewer-codex.md similarity index 100% rename from .config/shared/claude/agents/at-impl-reviewer-codex.md rename to chezmoi/private_dot_claude/agents/at-impl-reviewer-codex.md diff --git a/.config/shared/claude/agents/at-impl-reviewer-opus.md b/chezmoi/private_dot_claude/agents/at-impl-reviewer-opus.md similarity index 100% rename from .config/shared/claude/agents/at-impl-reviewer-opus.md rename to chezmoi/private_dot_claude/agents/at-impl-reviewer-opus.md diff --git a/.config/shared/claude/agents/at-implementer.md b/chezmoi/private_dot_claude/agents/at-implementer.md similarity index 100% rename from .config/shared/claude/agents/at-implementer.md rename to chezmoi/private_dot_claude/agents/at-implementer.md diff --git a/.config/shared/claude/agents/at-performance.md b/chezmoi/private_dot_claude/agents/at-performance.md similarity index 100% rename from .config/shared/claude/agents/at-performance.md rename to chezmoi/private_dot_claude/agents/at-performance.md diff --git a/.config/shared/claude/agents/at-plan-reviewer.md b/chezmoi/private_dot_claude/agents/at-plan-reviewer.md similarity index 100% rename from .config/shared/claude/agents/at-plan-reviewer.md rename to chezmoi/private_dot_claude/agents/at-plan-reviewer.md diff --git a/.config/shared/claude/agents/at-planner.md b/chezmoi/private_dot_claude/agents/at-planner.md similarity index 100% rename from .config/shared/claude/agents/at-planner.md rename to chezmoi/private_dot_claude/agents/at-planner.md diff --git a/.config/shared/claude/agents/at-security-codex.md b/chezmoi/private_dot_claude/agents/at-security-codex.md similarity index 100% rename from .config/shared/claude/agents/at-security-codex.md rename to chezmoi/private_dot_claude/agents/at-security-codex.md diff --git a/.config/shared/claude/agents/at-security-opus.md b/chezmoi/private_dot_claude/agents/at-security-opus.md similarity index 100% rename from .config/shared/claude/agents/at-security-opus.md rename to chezmoi/private_dot_claude/agents/at-security-opus.md diff --git a/.config/shared/claude/agents/at-test-reviewer-codex.md b/chezmoi/private_dot_claude/agents/at-test-reviewer-codex.md similarity index 100% rename from .config/shared/claude/agents/at-test-reviewer-codex.md rename to chezmoi/private_dot_claude/agents/at-test-reviewer-codex.md diff --git a/.config/shared/claude/agents/at-test-reviewer-opus.md b/chezmoi/private_dot_claude/agents/at-test-reviewer-opus.md similarity index 100% rename from .config/shared/claude/agents/at-test-reviewer-opus.md rename to chezmoi/private_dot_claude/agents/at-test-reviewer-opus.md diff --git a/.config/shared/claude/agents/at-tester.md b/chezmoi/private_dot_claude/agents/at-tester.md similarity index 100% rename from .config/shared/claude/agents/at-tester.md rename to chezmoi/private_dot_claude/agents/at-tester.md diff --git a/.config/shared/claude/agents/tp-qa-architect.md b/chezmoi/private_dot_claude/agents/tp-qa-architect.md similarity index 100% rename from .config/shared/claude/agents/tp-qa-architect.md rename to chezmoi/private_dot_claude/agents/tp-qa-architect.md diff --git a/.config/shared/claude/agents/tp-requirements-analyst.md b/chezmoi/private_dot_claude/agents/tp-requirements-analyst.md similarity index 100% rename from .config/shared/claude/agents/tp-requirements-analyst.md rename to chezmoi/private_dot_claude/agents/tp-requirements-analyst.md diff --git a/.config/shared/claude/agents/tp-system-designer.md b/chezmoi/private_dot_claude/agents/tp-system-designer.md similarity index 100% rename from .config/shared/claude/agents/tp-system-designer.md rename to chezmoi/private_dot_claude/agents/tp-system-designer.md diff --git a/.config/shared/claude/agents/tp-task-decomposer.md b/chezmoi/private_dot_claude/agents/tp-task-decomposer.md similarity index 100% rename from .config/shared/claude/agents/tp-task-decomposer.md rename to chezmoi/private_dot_claude/agents/tp-task-decomposer.md diff --git a/.config/windows/claude/ccwin-hook.ps1 b/chezmoi/private_dot_claude/ccwin-hook.ps1 similarity index 83% rename from .config/windows/claude/ccwin-hook.ps1 rename to chezmoi/private_dot_claude/ccwin-hook.ps1 index 9334c3f..e691202 100644 --- a/.config/windows/claude/ccwin-hook.ps1 +++ b/chezmoi/private_dot_claude/ccwin-hook.ps1 @@ -19,10 +19,11 @@ $Kind = switch ($Kind.ToLower()) { } # dev ビルド (リポジトリ内 bin/) を優先しつつ、なければ scoop インストール版に fallback +$projectDir = Join-Path $env:USERPROFILE "Project\github.com\t4ko0522\ccwin-notify" $devCandidates = @( - "C:\Users\takow\Project\github.com\t4ko0522\ccwin-notify\bin\ccwin.exe", - "C:\Users\takow\Project\github.com\t4ko0522\ccwin-notify\ccwin.exe", - "C:\Users\takow\Project\github.com\t4ko0522\ccwin-notify\ccwin-dev.exe" + (Join-Path $projectDir "bin\ccwin.exe"), + (Join-Path $projectDir "ccwin.exe"), + (Join-Path $projectDir "ccwin-dev.exe") ) $ccwin = $null foreach ($c in $devCandidates) { diff --git a/.config/shared/claude/claude-icon.svg b/chezmoi/private_dot_claude/claude-icon.svg similarity index 100% rename from .config/shared/claude/claude-icon.svg rename to chezmoi/private_dot_claude/claude-icon.svg diff --git a/.config/nixos/claude/claude-notify-hook.sh b/chezmoi/private_dot_claude/executable_claude-notify-hook.sh similarity index 100% rename from .config/nixos/claude/claude-notify-hook.sh rename to chezmoi/private_dot_claude/executable_claude-notify-hook.sh diff --git a/.config/shared/claude/statusline.sh b/chezmoi/private_dot_claude/executable_statusline.sh similarity index 100% rename from .config/shared/claude/statusline.sh rename to chezmoi/private_dot_claude/executable_statusline.sh diff --git a/chezmoi/private_dot_claude/settings.json.tmpl b/chezmoi/private_dot_claude/settings.json.tmpl new file mode 100644 index 0000000..1729ade --- /dev/null +++ b/chezmoi/private_dot_claude/settings.json.tmpl @@ -0,0 +1,10 @@ +{{- $base := include ".chezmoitemplates/claude-settings-base.json" | fromJson -}} +{{- if eq .profile "windows" -}} +{{- $hooks := include ".chezmoitemplates/claude-settings-windows-hooks.json" | fromJson -}} +{{ mergeOverwrite $base $hooks | toPrettyJson }} +{{- else if eq .profile "nixos" -}} +{{- $hooks := include ".chezmoitemplates/claude-settings-nixos-hooks.json" | fromJson -}} +{{ mergeOverwrite $base $hooks | toPrettyJson }} +{{- else -}} +{{ $base | toPrettyJson }} +{{- end }} diff --git a/.config/shared/codex/AGENTS.md b/chezmoi/private_dot_codex/AGENTS.md similarity index 100% rename from .config/shared/codex/AGENTS.md rename to chezmoi/private_dot_codex/AGENTS.md diff --git a/.config/shared/codex/agents/worker.toml b/chezmoi/private_dot_codex/agents/worker.toml similarity index 100% rename from .config/shared/codex/agents/worker.toml rename to chezmoi/private_dot_codex/agents/worker.toml diff --git a/chezmoi/private_dot_codex/create_config.toml.tmpl b/chezmoi/private_dot_codex/create_config.toml.tmpl new file mode 100644 index 0000000..223f340 --- /dev/null +++ b/chezmoi/private_dot_codex/create_config.toml.tmpl @@ -0,0 +1 @@ +{{ include ".chezmoitemplates/codex-config.toml" }} diff --git a/.config/shared/codex/rules/npm.rules b/chezmoi/private_dot_codex/rules/npm.rules similarity index 100% rename from .config/shared/codex/rules/npm.rules rename to chezmoi/private_dot_codex/rules/npm.rules diff --git a/.config/shared/codex/rules/safety.rules b/chezmoi/private_dot_codex/rules/safety.rules similarity index 100% rename from .config/shared/codex/rules/safety.rules rename to chezmoi/private_dot_codex/rules/safety.rules diff --git a/.git_template/hooks/prepare-commit-msg b/chezmoi/private_dot_git_template/hooks/executable_prepare-commit-msg old mode 100755 new mode 100644 similarity index 100% rename from .git_template/hooks/prepare-commit-msg rename to chezmoi/private_dot_git_template/hooks/executable_prepare-commit-msg diff --git a/chezmoi/run_after_create-windows-junctions.ps1.tmpl b/chezmoi/run_after_create-windows-junctions.ps1.tmpl new file mode 100644 index 0000000..e475266 --- /dev/null +++ b/chezmoi/run_after_create-windows-junctions.ps1.tmpl @@ -0,0 +1,115 @@ +{{- if eq .profile "windows" }} +#!/usr/bin/env pwsh + +$ErrorActionPreference = 'Stop' + +$repo = {{ .chezmoi.workingTree | quote }} +$homeDir = {{ .chezmoi.destDir | quote }} +$appData = if ($env:CHEZMOI_WINDOWS_APPDATA) { + $env:CHEZMOI_WINDOWS_APPDATA +} else { + $env:APPDATA +} +$documentsDir = if ($env:CHEZMOI_WINDOWS_DOCUMENTS) { + $env:CHEZMOI_WINDOWS_DOCUMENTS +} else { + [Environment]::GetFolderPath('MyDocuments') +} +$junctions = @( + @{ + Source = Join-Path $repo 'mutable\nvim' + Target = Join-Path $homeDir 'AppData\Local\nvim' + }, + @{ + Source = Join-Path $repo 'mutable\cava' + Target = Join-Path $homeDir '.config\cava' + } +) + +foreach ($junction in $junctions) { + $source = [IO.Path]::GetFullPath($junction.Source) + $target = [IO.Path]::GetFullPath($junction.Target) + + if (-not (Test-Path -LiteralPath $source -PathType Container)) { + throw "Junction source does not exist: $source" + } + + $targetItem = Get-Item -LiteralPath $target -Force -ErrorAction SilentlyContinue + if ($targetItem) { + if ($targetItem.LinkType -ne 'Junction') { + throw "Refusing to replace non-junction path: $target" + } + + $currentSource = [IO.Path]::GetFullPath([string]$targetItem.Target) + if ($currentSource -eq $source) { + continue + } + + Remove-Item -LiteralPath $target -Force + } + + $targetParent = Split-Path -Parent $target + New-Item -ItemType Directory -Path $targetParent -Force | Out-Null + New-Item -ItemType Junction -Path $target -Target $source | Out-Null +} + +function Set-NativeFileLink { + param( + [Parameter(Mandatory)][string]$Source, + [Parameter(Mandatory)][string]$Target + ) + + $sourcePath = [IO.Path]::GetFullPath($Source) + $targetPath = [IO.Path]::GetFullPath($Target) + if ($sourcePath -eq $targetPath) { + return + } + + $targetItem = Get-Item -LiteralPath $targetPath -Force -ErrorAction SilentlyContinue + if ($targetItem) { + if ($targetItem.LinkType) { + $currentSource = [IO.Path]::GetFullPath([string]$targetItem.Target) + if ($currentSource -eq $sourcePath) { + return + } + } + Remove-Item -LiteralPath $targetPath -Force + } + + New-Item -ItemType Directory -Path (Split-Path -Parent $targetPath) -Force | Out-Null + New-Item -ItemType SymbolicLink -Path $targetPath -Target $sourcePath | Out-Null +} + +$nativeRoots = @( + @{ + Source = Join-Path $homeDir '.config\yazi' + Target = Join-Path $appData 'yazi\config' + }, + @{ + Source = Join-Path $repo 'mutable\shared\zed' + Target = Join-Path $appData 'Zed' + }, + @{ + Source = Join-Path $homeDir 'Documents\PowerShell' + Target = Join-Path $documentsDir 'PowerShell' + } +) + +foreach ($mapping in $nativeRoots) { + $sourceRoot = [IO.Path]::GetFullPath($mapping.Source) + $targetRoot = [IO.Path]::GetFullPath($mapping.Target) + if (-not (Test-Path -LiteralPath $sourceRoot -PathType Container)) { + throw "Native configuration source does not exist: $sourceRoot" + } + if ($sourceRoot -eq $targetRoot) { + continue + } + + foreach ($file in Get-ChildItem -LiteralPath $sourceRoot -Recurse -File -FollowSymlink) { + $relativePath = [IO.Path]::GetRelativePath($sourceRoot, $file.FullName) + Set-NativeFileLink ` + -Source $file.FullName ` + -Target (Join-Path $targetRoot $relativePath) + } +} +{{- end }} diff --git a/chezmoi/symlink_dot_gitconfig.tmpl b/chezmoi/symlink_dot_gitconfig.tmpl new file mode 100644 index 0000000..c426927 --- /dev/null +++ b/chezmoi/symlink_dot_gitconfig.tmpl @@ -0,0 +1 @@ +{{ .chezmoi.sourceDir }}/../mutable/shared/gitconfig diff --git a/corne b/corne deleted file mode 160000 index 291af9f..0000000 --- a/corne +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 291af9ff9d43312c6bb0331c5d78e9a2781b0753 diff --git a/docs/keybindings/komorebi.md b/docs/keybindings/komorebi.md deleted file mode 100644 index dfb8a2a..0000000 --- a/docs/keybindings/komorebi.md +++ /dev/null @@ -1,115 +0,0 @@ -# komorebi + whkd キーバインド - -設定ファイル: [`.config/windows/whkdrc`](../../.config/windows/whkdrc) / [`.config/windows/komorebi/komorebi.json`](../../.config/windows/komorebi/komorebi.json) - -前提: - -- シェルは `powershell` -- `Win` = Windows キー - -## ワークスペース構成 - -`Win+1/2/3` は **フォーカス中モニターのみ** を切り替える (`focus-workspace` 単数形)。 -`Win+F1/F2/F3` は **M1 へフォーカスを移しつつ** IV/V/VI に切り替える (`focus-monitor-workspace 1 N`)。 - -| Index | M0 `CMN1556` (メイン) | M1 `DELF144` (拡張) | -|---|---|---| -| 0 (`Win+1` / `Win+F1`) | **I** / BSP — WezTerm | **IV** / BSP — VSCode, Zed, Brave (プライベート) | -| 1 (`Win+2` / `Win+F2`) | **II** / Grid — Discord | **V** / BSP — Chrome (ビジネス) | -| 2 (`Win+3` / `Win+F3`) | **III** / Columns — Slack, Spotify | **VI** / BSP — Mattermost | - -> `Win+F1/F2/F3` はモニターをまたいで M1 側の作業に直接ジャンプしたい時に使う。M0 を見たまま M1 側だけ切り替えたい場合は使えない (フォーカスが M1 に移る)。 - -### 配置ポリシー - -- **M0 = コミュニケーション・開発端末** - - I: ターミナル作業 (WezTerm) - - II: 通話・チャット (Discord) - - III: ワークチャット系 + BGM (Slack, Spotify) -- **M1 = 広い作業領域** - - IV: コーディング + プライベートブラウジング (VSCode, Zed, Brave) - - V: ビジネス用ブラウジング (Chrome) - - VI: ビジネスチャット専用 (Mattermost) -- **ブラウザの役割分担** - - **Brave = プライベート**: 私用閲覧・SNS・動画・課金記事の送り込み防止 - - **Chrome = ビジネス**: Google Workspace, 業務ツール, 顧客サービス - -ワークスペース名は `I, II, III` (M0) と `IV, V, VI` (M1) で連番。`Win+3` を押した時に表示される名前 (III or VI) で、どちらのモニターを操作中か即時に判別できる。 - -### 起動スクリプト - -pwsh 起動時 ([`.config/windows/powershell/conf.d/startup.ps1`](../../.config/windows/powershell/conf.d/startup.ps1)) に komorebi が未起動なら [`.config/windows/komorebi/komorebi_start.ps1`](../../.config/windows/komorebi/komorebi_start.ps1) が走り、モニター適応 → komorebi/whkd 起動 → [`morning_setup.ps1`](../../.config/windows/komorebi/morning_setup.ps1) による常用アプリ一括起動まで一気通貫で行う (`workspace_rules` が配置を担当)。2 回目以降の pwsh タブ起動では komorebi の生存を socket 応答で確認し、何もしない。 - -## 基本 - -| キー | 動作 | -| --- | --- | -| `Win+r` | 設定の再読込 | -| `Win+/` | whkd のショートカット一覧を表示 | -| `Win+q` | ウィンドウを閉じる | -| `Win+m` | ウィンドウを最小化 | -| `Win+t` | フローティング切替 | -| `Win+Shift+f` | モノクル (最大化) 切替 | -| `Win+z` | komorebi の一時停止トグル | - -## レイアウト - -| キー | 動作 | -| --- | --- | -| `Win+x` | 水平方向にフリップ | -| `Win+y` | 垂直方向にフリップ | - -## フォーカス移動 - -ワークスペース内に閉じた方向フォーカス。 - -| キー | 動作 | -| --- | --- | -| `Win+←` / `Win+↓` / `Win+↑` / `Win+→` | 左 / 下 / 上 / 右のウィンドウにフォーカス | -| `Win+Shift+[` | 前のウィンドウへ (`cycle-focus previous`) | -| `Win+Shift+]` | 次のウィンドウへ (`cycle-focus next`) | - -> `cross_boundary_behaviour: "Workspace"` によりフォーカス移動は同一ワークスペース内に閉じる。モニター切替は `Win+,` / `Win+.` を使う。 -> -> 注: `Win+u/i/o/p` は方向フォーカスではなく `preselect-direction` (次に開くウィンドウの配置先指定)。 - -## ウィンドウ移動 - -| キー | 動作 | -| --- | --- | -| `Win+Shift+u` / `i` / `o` / `p` | 左 / 下 / 上 / 右へ移動 | -| `Win+Shift+Enter` | プロモート (マスター位置へ) | - -## スタック - -| キー | 動作 | -| --- | --- | -| `Win+;` | スタックを解除 | -| `Win+[` / `Win+]` | スタック内の前 / 次 | - -> 方向キーによるスタック作成 (`komorebic stack `) は廃止し、`Win+←/↓/↑/→` はフォーカス移動に再割り当て。スタックを組みたい場合は CLI から `komorebic stack ` を直接実行する (現状 `window_container_behaviour: "Create"` のため `move` ではスタックにならない点に注意)。 - -## リサイズ - -| キー | 動作 | -| --- | --- | -| `Win++` / `Win+-` | 水平方向に拡大 / 縮小 | -| `Win+Shift++` / `Win+Shift+-` | 垂直方向に拡大 / 縮小 | - -## ワークスペース - -| キー | 動作 | -| --- | --- | -| `Win+1`〜`Win+3` | フォーカス中モニターのワークスペース 0〜2 にフォーカス | -| `Win+F1`〜`Win+F3` | M1 へフォーカスを移しつつ M1 のワークスペース 0〜2 (IV/V/VI) に切替 | -| `Win+Alt+1`〜`Win+Alt+3` | アクティブウィンドウをフォーカス中モニターのワークスペース 0〜2 へ移動 | - -## マルチモニター - -| キー | 動作 | -| --- | --- | -| `Win+,` | モニター 0 (メイン: WezTerm / Discord / Slack+Spotify) | -| `Win+.` | モニター 1 (拡張: VSCode+Zed+Brave / Chrome / Mattermost) | -| `Win+Shift+,` / `Win+Shift+.` | ウィンドウをモニター 0 / 1 へ移動 | -| `Win+n` | 次のモニターへ | -| `Win+Shift+n` | 前のモニターへ | diff --git a/docs/keybindings/niri.md b/docs/keybindings/niri.md deleted file mode 100644 index 584cb4a..0000000 --- a/docs/keybindings/niri.md +++ /dev/null @@ -1,159 +0,0 @@ -# niri キーバインド - -設定ファイル: [`nix-configs/home/niri-keybind.nix`](../../nix-configs/home/niri-keybind.nix) - -`Win` は niri 設定上の `Mod` キーです。 - -## niri の見方 - -niri はスクロール型タイルの Wayland compositor です。画面を固定分割するのではなく、ウィンドウを横方向の列として並べ、必要に応じて左右へスクロールしながら使います。 - -| 概念 | 説明 | この設定での主な操作 | -| --- | --- | --- | -| 列 | ウィンドウを置く横方向の単位。列は左右へ並ぶ | `Win+H/L`, `Win+←/→`, `Win+Ctrl+←/→` | -| 列内のウィンドウ | 1 つの列に複数ウィンドウを上下へ積める | `Win+Ctrl+↑/↓` | -| ワークスペース | 作業単位。niri では上下方向に並ぶ | `Win+J/K`, `Win+1` - `Win+9` | -| モニター | 各モニターが独立したワークスペース群を持つ | `Win+Shift+H/L`, `Win+Ctrl+H/L` | -| レイアウト | 列幅、中央寄せ、最大化、フルスクリーンを調整する | `Win+R/F/C`, `Win+-/=`, `Win+Shift+F` | - -## niri の WM 機能 - -- **スクロール型タイル**: ウィンドウは横方向へ伸びる列として管理されます。新しいウィンドウを開いても、既存のウィンドウ全体を毎回小さく分割する使い方ではありません。 -- **列ベースの操作**: 左右は「列」の移動、上下矢印は「今のウィンドウを上下のワークスペースへ送る」操作として考えると整理しやすいです。ワークスペースの表示先は `J/K` または数字キーで選びます。 -- **動的ワークスペース**: ワークスペースは必要に応じて増減します。作業内容ごとに上下へ分けるイメージです。 -- **モニターごとの独立性**: 複数モニターでは、それぞれのモニターが独立したワークスペースを持ちます。ウィンドウを別モニターへ送る操作は明示的に行います。 -- **列幅の調整**: プリセット幅の切り替え、最大化、中央寄せ、幅の増減で、作業中の列を見やすい幅にできます。 -- **フルスクリーンとスクリーンショット**: WM 側の操作としてフルスクリーン切り替えとスクリーンショットが使えます。 -- **Overview**: ワークスペースとウィンドウを縮小表示して、全体を見渡しながら移動や整理ができます。 -- **設定の live reload**: `config.kdl` の設定変更を反映しながら調整できます。このリポジトリでは Home Manager から `config.kdl` を生成しています。 -- **タブ、floating**: niri 自体にはタブ化、floating window などの機能があります。この設定では Quick Shell 用の Ghostty だけを floating で開きます。 - -## 操作の覚え方 - -- `H/J/K/L`: フォーカスだけを移動 -- `←/↓/↑/→`: 今のウィンドウまたは列を伴って移動 -- 横方向: `H/L` は列フォーカス、`←/→` は列そのものを左右へ移動 -- 縦方向: `J/K` はワークスペースフォーカス、`↑/↓` は今のウィンドウを上下のワークスペースへ移動 -- `Ctrl` 付き: ウィンドウや列そのものを移動する操作 -- 数字: ワークスペースへ直接移動 - -## Overview - -`Win+D` で Overview を開くと、ワークスペースとウィンドウを縮小表示して全体を見渡せます。Overview 中も通常の niri キーバインドは有効です。この設定では `Win+H/J/K/L` を「ウィンドウを動かさない移動」、`Win+←/↓/↑/→` を「ウィンドウまたは列を伴う移動」として使います。 - -| キー | 操作 | -| --- | --- | -| `Win+D` | Overview を開く/閉じる | -| `Win+H` | 左の列へフォーカス | -| `Win+L` | 右の列へフォーカス | -| `Win+J` | 下のワークスペースへフォーカス | -| `Win+K` | 上のワークスペースへフォーカス | -| `Win+←` | 列を左へ移動 | -| `Win+→` | 列を右へ移動 | -| `Win+↓` | 今のウィンドウを下のワークスペースへ移動 | -| `Win+↑` | 今のウィンドウを上のワークスペースへ移動 | - -素の `H/J/K/L` を Overview 専用に割り当てる設定は niri にはありません。素の `H/J/K/L` を bind すると通常の文字入力にも影響するため、この設定では使いません。 - -## 起動・終了 - -| キー | 操作 | -| --- | --- | -| `Win+Enter` | WezTerm を起動 | -| `Win+Shift+Enter` | Quick Shell をトグル | -| `Win+T` | WezTerm を起動 | -| `Alt+Space` | Vicinae を開く | -| `Win+V` | クリップボード履歴を開く | -| `Win+E` | ウィンドウを閉じる | -| `Win+D` | Overview を開く/閉じる | -| `Win+Shift+E` | niri を終了 | -| `Win+Shift+P` | モニターの電源を切る | - -## Quick Shell - -`Win+Shift+Enter` は一時作業用の Ghostty をモーダル風に開きます。専用 app-id (`dev.t4ko.quickshell`) を付けて起動し、niri の通常タイル配置ではなく floating window として画面上部中央に表示します。 - -同じキーをもう一度押すと、Quick Shell が非フォーカスなら呼び戻し、フォーカス中なら閉じます。シェルは `quick-shell` という tmux セッションで動くため、ウィンドウを閉じても作業状態は残ります。シェル側で `exit` するとセッションも終了します。 - -Quick Shell 内で `quick-shell-wezterm` を実行すると、同じセッションを最後に操作した WezTerm ウィンドウの新しいタブへ引き継ぎ、モーダル側を閉じます。WezTerm が起動していない場合は、新しいウィンドウを開きます。プロンプトには通常のシェルとは別の、Quick Shell 専用 Starship 設定を使います。 - -Quick Shell がフォーカス中なら、`Win+F` でも同じ引き継ぎを実行します。それ以外のウィンドウでは、従来どおり現在の列を最大化します。 - -## フォーカス移動 - -| キー | 操作 | -| --- | --- | -| `Win+H` | 左の列へフォーカス | -| `Win+L` | 右の列へフォーカス | -| `Win+J` | 下のワークスペースへフォーカス | -| `Win+K` | 上のワークスペースへフォーカス | - -## ウィンドウ・列の移動 - -| キー | 操作 | -| --- | --- | -| `Win+←` | 列を左へ移動 | -| `Win+→` | 列を右へ移動 | -| `Win+Ctrl+←` | 列を左へ移動 | -| `Win+Ctrl+↓` | ウィンドウを下へ移動 | -| `Win+Ctrl+↑` | ウィンドウを上へ移動 | -| `Win+Ctrl+→` | 列を右へ移動 | -| `Win+Ctrl+J` | ウィンドウを下へ移動 | -| `Win+Ctrl+K` | ウィンドウを上へ移動 | - -## モニター間移動 - -| キー | 操作 | -| --- | --- | -| `Win+Shift+H` | 左のモニターへフォーカス | -| `Win+Shift+L` | 右のモニターへフォーカス | -| `Win+Ctrl+H` | ウィンドウを左のモニターへ移動 | -| `Win+Ctrl+L` | ウィンドウを右のモニターへ移動 | -| `Win+Ctrl+Shift+H` | 列ごと左のモニターへ移動 | -| `Win+Ctrl+Shift+L` | 列ごと右のモニターへ移動 | - -## ワークスペース - -| キー | 操作 | -| --- | --- | -| `Win+J` | 下のワークスペースへフォーカス | -| `Win+K` | 上のワークスペースへフォーカス | -| `Win+↓` | 今のウィンドウを下のワークスペースへ移動 | -| `Win+↑` | 今のウィンドウを上のワークスペースへ移動 | -| `Win+Ctrl+PageDown` | 列を下のワークスペースへ移動 | -| `Win+Ctrl+PageUp` | 列を上のワークスペースへ移動 | -| `Win+1` - `Win+9` | 指定したワークスペースへフォーカス | - -## レイアウト - -| キー | 操作 | -| --- | --- | -| `Win+R` | プリセット列幅を切り替え | -| `Win+F` | 列を最大化 | -| `Win+Shift+F` | フルスクリーン切り替え | -| `Win+C` | 列を中央へ配置 | -| `Win+-` | 列幅を 10% 縮小 | -| `Win+=` | 列幅を 10% 拡大 | - -## スクリーンショット - -| キー | 操作 | -| --- | --- | -| `Print` | スクリーンショット | -| `Ctrl+Print` | 画面のスクリーンショット | -| `Alt+Print` | ウィンドウのスクリーンショット | - -## 音量 - -| キー | 操作 | -| --- | --- | -| `XF86AudioRaiseVolume` | 音量を上げる | -| `XF86AudioLowerVolume` | 音量を下げる | -| `XF86AudioMute` | ミュート切り替え | -| `XF86AudioMicMute` | マイクミュート切り替え | - -## ヘルプ - -| キー | 操作 | -| --- | --- | -| `Win+Shift+/` | ホットキー一覧を表示 | diff --git a/docs/keybindings/nvim/README.md b/docs/keybindings/nvim/README.md index 26bb1bd..05141a7 100644 --- a/docs/keybindings/nvim/README.md +++ b/docs/keybindings/nvim/README.md @@ -4,10 +4,10 @@ Vim 初心者向けに、本リポジトリの Neovim 設定 ([LazyVim](https:// 設定ファイル: -- [`.config/shared/nvim/lua/config/options.lua`](../../../.config/shared/nvim/lua/config/options.lua) — オプションとリーダーキー -- [`.config/shared/nvim/lua/config/keymaps.lua`](../../../.config/shared/nvim/lua/config/keymaps.lua) — カスタムキーマップ -- [`.config/shared/nvim/lua/config/autocmds.lua`](../../../.config/shared/nvim/lua/config/autocmds.lua) — autocmd とユーザーコマンド -- [`.config/shared/nvim/lua/plugins/`](../../../.config/shared/nvim/lua/plugins/) — 各プラグインの設定 +- [`mutable/nvim/lua/config/options.lua`](../../../mutable/nvim/lua/config/options.lua) — Windows LazyVimのオプションとリーダーキー +- [`mutable/nvim/lua/config/keymaps.lua`](../../../mutable/nvim/lua/config/keymaps.lua) — Windows LazyVimのカスタムキーマップ +- [`mutable/nvim/lua/config/autocmds.lua`](../../../mutable/nvim/lua/config/autocmds.lua) — Windows LazyVimのautocmdとユーザーコマンド +- [`mutable/nvim/lua/plugins/`](../../../mutable/nvim/lua/plugins/) — Windows LazyVimの各プラグイン設定 ## 大事な前提 diff --git a/docs/keybindings/wezterm/README.md b/docs/keybindings/wezterm/README.md index be85a42..4f652b3 100644 --- a/docs/keybindings/wezterm/README.md +++ b/docs/keybindings/wezterm/README.md @@ -2,10 +2,10 @@ 設定ファイル: -- [`.config/shared/wezterm/wezterm.lua`](../../../.config/shared/wezterm/wezterm.lua) — エントリポイント -- [`.config/shared/wezterm/keymaps.lua`](../../../.config/shared/wezterm/keymaps.lua) — グローバル / `tab_ops` / `pane_ops` / `resize_pane` / `activate_pane` / `copy_mode` -- [`.config/shared/wezterm/workspace.lua`](../../../.config/shared/wezterm/workspace.lua) — ワークスペース / `workspace_mode` -- [`.config/shared/wezterm/modules/opacity.lua`](../../../.config/shared/wezterm/modules/opacity.lua) — `setting_mode` +- [`chezmoi/dot_config/wezterm/wezterm.lua`](../../../chezmoi/dot_config/wezterm/wezterm.lua) — エントリポイント +- [`chezmoi/dot_config/wezterm/keymaps.lua`](../../../chezmoi/dot_config/wezterm/keymaps.lua) — グローバル / `tab_ops` / `pane_ops` / `resize_pane` / `activate_pane` / `copy_mode` +- [`chezmoi/dot_config/wezterm/workspace.lua`](../../../chezmoi/dot_config/wezterm/workspace.lua) — ワークスペース / `workspace_mode` +- [`chezmoi/dot_config/wezterm/modules/opacity.lua`](../../../chezmoi/dot_config/wezterm/modules/opacity.lua) — `setting_mode` ## 前提 diff --git a/docs/keybindings/wezterm/copy-mode.md b/docs/keybindings/wezterm/copy-mode.md index b9b984f..e346179 100644 --- a/docs/keybindings/wezterm/copy-mode.md +++ b/docs/keybindings/wezterm/copy-mode.md @@ -1,6 +1,6 @@ # コピーモード — `copy_mode` key table -定義箇所: [`.config/shared/wezterm/keymaps.lua`](../../../.config/shared/wezterm/keymaps.lua) の `key_tables.copy_mode` +定義箇所: [`chezmoi/dot_config/wezterm/keymaps.lua`](../../../chezmoi/dot_config/wezterm/keymaps.lua) の `key_tables.copy_mode` `Leader → c` で起動。vim 風のキーバインドで移動・選択・コピー・検索を行う。 diff --git a/docs/keybindings/wezterm/global.md b/docs/keybindings/wezterm/global.md index 1697345..20d7267 100644 --- a/docs/keybindings/wezterm/global.md +++ b/docs/keybindings/wezterm/global.md @@ -2,7 +2,7 @@ key table に入っていない通常状態で常時有効なキーバインド。 -定義箇所: [`.config/shared/wezterm/keymaps.lua`](../../../.config/shared/wezterm/keymaps.lua) の `keys` テーブル +定義箇所: [`chezmoi/dot_config/wezterm/keymaps.lua`](../../../chezmoi/dot_config/wezterm/keymaps.lua) の `keys` テーブル ## コマンドパレット / 設定 @@ -20,7 +20,7 @@ key table に入っていない通常状態で常時有効なキーバインド | `Ctrl+v` | クリップボードから貼り付け | | `Ctrl+Shift+Space` | QuickSelect 起動(URL / git hash / IP / path 等を 1 文字キーで選択) | -QuickSelect の追加パターンは [`wezterm.lua`](../../../.config/shared/wezterm/wezterm.lua) の `config.quick_select_patterns` で定義可能(現在は未設定で WezTerm 既定パターンのみ)。 +QuickSelect の追加パターンは [`wezterm.lua`](../../../chezmoi/dot_config/wezterm/wezterm.lua) の `config.quick_select_patterns` で定義可能(現在は未設定で WezTerm 既定パターンのみ)。 ## フォントサイズ diff --git a/docs/keybindings/wezterm/panes.md b/docs/keybindings/wezterm/panes.md index 1d49bc9..ea6fcf9 100644 --- a/docs/keybindings/wezterm/panes.md +++ b/docs/keybindings/wezterm/panes.md @@ -1,6 +1,6 @@ # ペイン -定義箇所: [`.config/shared/wezterm/keymaps.lua`](../../../.config/shared/wezterm/keymaps.lua) の `key_tables` 配下 `pane_ops` / `resize_pane` / `activate_pane` +定義箇所: [`chezmoi/dot_config/wezterm/keymaps.lua`](../../../chezmoi/dot_config/wezterm/keymaps.lua) の `key_tables` 配下 `pane_ops` / `resize_pane` / `activate_pane` ## `pane_ops` — `Alt+q` で起動 diff --git a/docs/keybindings/wezterm/setting-mode.md b/docs/keybindings/wezterm/setting-mode.md index 8012578..800744c 100644 --- a/docs/keybindings/wezterm/setting-mode.md +++ b/docs/keybindings/wezterm/setting-mode.md @@ -1,12 +1,12 @@ # 透明度 — `setting_mode` key table -定義箇所: [`.config/shared/wezterm/modules/opacity.lua`](../../../.config/shared/wezterm/modules/opacity.lua) +定義箇所: [`chezmoi/dot_config/wezterm/modules/opacity.lua`](../../../chezmoi/dot_config/wezterm/modules/opacity.lua) 背景の不透明度をリアルタイム調整するモード。キーを押すたびに `setting_mode` が再アクティブ化されるため、連続操作が可能。 ## 起動 -`setting_mode` を起動するキーは現在割り当てなし。コマンドパレット (`Ctrl+j`) から `ActivateKeyTable` を選んで起動するか、必要に応じて [`keymaps.lua`](../../../.config/shared/wezterm/keymaps.lua) にエントリを追加する。 +`setting_mode` を起動するキーは現在割り当てなし。コマンドパレット (`Ctrl+j`) から `ActivateKeyTable` を選んで起動するか、必要に応じて [`keymaps.lua`](../../../chezmoi/dot_config/wezterm/keymaps.lua) にエントリを追加する。 ## キー一覧 @@ -14,7 +14,7 @@ | --- | --- | | `;` | 不透明度を `+0.1`(上限 `1.0`) | | `-` | 不透明度を `-0.1`(下限 `0.1`) | -| `0` | [`wezterm.lua`](../../../.config/shared/wezterm/wezterm.lua) の `window_background_opacity` 初期値(現在 `0.7`)へリセット | +| `0` | [`wezterm.lua`](../../../chezmoi/dot_config/wezterm/wezterm.lua) の `window_background_opacity` 初期値(現在 `0.7`)へリセット | ## 補足 diff --git a/docs/keybindings/wezterm/tabs.md b/docs/keybindings/wezterm/tabs.md index 74a2d7d..0e054fd 100644 --- a/docs/keybindings/wezterm/tabs.md +++ b/docs/keybindings/wezterm/tabs.md @@ -1,6 +1,6 @@ # タブ — `tab_ops` key table -定義箇所: [`.config/shared/wezterm/keymaps.lua`](../../../.config/shared/wezterm/keymaps.lua) の `key_tables.tab_ops` +定義箇所: [`chezmoi/dot_config/wezterm/keymaps.lua`](../../../chezmoi/dot_config/wezterm/keymaps.lua) の `key_tables.tab_ops` `Alt+a` でトグル起動。`one_shot = false` のため操作後も継続。再度 `Alt+a` か `Esc` で終了。 diff --git a/docs/keybindings/wezterm/workspace.md b/docs/keybindings/wezterm/workspace.md index f0e3022..f3e84b0 100644 --- a/docs/keybindings/wezterm/workspace.md +++ b/docs/keybindings/wezterm/workspace.md @@ -1,6 +1,6 @@ # ワークスペース -定義箇所: [`.config/shared/wezterm/workspace.lua`](../../../.config/shared/wezterm/workspace.lua) +定義箇所: [`chezmoi/dot_config/wezterm/workspace.lua`](../../../chezmoi/dot_config/wezterm/workspace.lua) `scratch` ワークスペースは一時的な作業領域として扱われ、`Ctrl+Cmd+n` / `Ctrl+Cmd+p` の巡回からは除外される。`Ctrl+Cmd+s` のトグルで `scratch` へ移動した際は、移動前のワークスペースを記憶しており、再度同キーで元に戻る。 diff --git a/docs/memo/dotfiles-ownership.tsv b/docs/memo/dotfiles-ownership.tsv new file mode 100644 index 0000000..6e8399c --- /dev/null +++ b/docs/memo/dotfiles-ownership.tsv @@ -0,0 +1,54 @@ +profile target owner mode source +windows AppData/Local/nvim chezmoi junction mutable/nvim +windows .config/cava chezmoi junction mutable/cava +windows AppData/Roaming/yazi/config chezmoi native-link chezmoi/dot_config/yazi +windows AppData/Roaming/Zed chezmoi native-link mutable/shared/zed +windows MyDocuments/PowerShell chezmoi native-link chezmoi/Documents/PowerShell +nixos .config/nvim nix nixvim nix-configs/home/modules/editors/nixvim +wsl .config/nvim unmanaged none - +wsl /etc/wsl.conf nix generated nix-configs/hosts/wsl/default.nix +windows .config/starship.toml chezmoi copy chezmoi/dot_config/starship.toml +nixos .config/starship.toml chezmoi copy chezmoi/dot_config/starship.toml +wsl .config/starship.toml chezmoi copy chezmoi/dot_config/starship.toml +windows .config/fastfetch chezmoi copy chezmoi/dot_config/fastfetch +nixos .config/fastfetch chezmoi copy chezmoi/dot_config/fastfetch +wsl .config/fastfetch chezmoi copy chezmoi/dot_config/fastfetch +windows .config/lazygit chezmoi link mutable/shared/lazygit +nixos .config/lazygit chezmoi link mutable/shared/lazygit +wsl .config/lazygit chezmoi link mutable/shared/lazygit +windows .config/yazi chezmoi copy chezmoi/dot_config/yazi +nixos .config/yazi chezmoi copy chezmoi/dot_config/yazi +wsl .config/yazi chezmoi copy chezmoi/dot_config/yazi +windows .config/wezterm chezmoi copy chezmoi/dot_config/wezterm +nixos .config/wezterm chezmoi copy chezmoi/dot_config/wezterm +wsl .config/wezterm unmanaged none - +nixos .config/niri nix generated nix-configs/home/modules/desktop/niri.nix +nixos .config/swaync nix generated nix-configs/home/modules/desktop/swaync.nix +nixos .config/waybar nix generated nix-configs/home/modules/desktop/waybar.nix +windows Documents/PowerShell chezmoi copy chezmoi/Documents/PowerShell +windows .config/zed chezmoi link mutable/shared/zed +nixos .config/zed chezmoi link mutable/shared/zed +nixos .config/fcitx5/config nix link mutable/nixos/fcitx5/config +nixos .config/zsh/rc nix store nix-configs/home/modules/shell/zsh/files/rc +windows .config/vim chezmoi copy chezmoi/dot_config/vim +nixos .config/vim chezmoi copy chezmoi/dot_config/vim +wsl .config/vim chezmoi copy chezmoi/dot_config/vim +windows .claude/CLAUDE.md chezmoi copy chezmoi/private_dot_claude/CLAUDE.md +nixos .claude/CLAUDE.md chezmoi copy chezmoi/private_dot_claude/CLAUDE.md +wsl .claude/CLAUDE.md chezmoi copy chezmoi/private_dot_claude/CLAUDE.md +windows .claude/settings.json chezmoi template chezmoi/private_dot_claude/settings.json.tmpl +nixos .claude/settings.json chezmoi template chezmoi/private_dot_claude/settings.json.tmpl +wsl .claude/settings.json chezmoi template chezmoi/private_dot_claude/settings.json.tmpl +windows .claude/ccwin-hook.ps1 chezmoi copy chezmoi/private_dot_claude/ccwin-hook.ps1 +nixos .claude/claude-notify-hook.sh chezmoi copy chezmoi/private_dot_claude/executable_claude-notify-hook.sh +windows .codex/AGENTS.md chezmoi copy chezmoi/private_dot_codex/AGENTS.md +nixos .codex/AGENTS.md chezmoi copy chezmoi/private_dot_codex/AGENTS.md +wsl .codex/AGENTS.md chezmoi copy chezmoi/private_dot_codex/AGENTS.md +windows .codex/config.toml chezmoi create chezmoi/private_dot_codex/create_config.toml.tmpl +nixos .codex/config.toml nix seed chezmoi/.chezmoitemplates/codex-config.toml +windows .config/mise chezmoi copy chezmoi/dot_config/mise +windows .config/ccwin-notify chezmoi copy chezmoi/dot_config/ccwin-notify +windows .config/yasb chezmoi template chezmoi/dot_config/yasb +windows .gitconfig chezmoi link mutable/shared/gitconfig +nixos .gitconfig chezmoi link mutable/shared/gitconfig +wsl .gitconfig chezmoi link mutable/shared/gitconfig diff --git a/docs/memo/vr-setup-2026-06-15.md b/docs/memo/vr-setup-2026-06-15.md index 84fc601..e65efa3 100644 --- a/docs/memo/vr-setup-2026-06-15.md +++ b/docs/memo/vr-setup-2026-06-15.md @@ -30,7 +30,7 @@ NixOS + Meta Quest 3 で VRChat を中心とした VR 環境を構築した際 ### やったこと - `services.wivrn` を導入(`autoStart` / `openFirewall` / `highPriority` / `steam.importOXRRuntimes`)。 -- OpenComposite (`home/vr.nix`) で OpenVR→OpenXR 変換し SteamVR を回避。 +- OpenComposite (`home/modules/apps/vr.nix`) で OpenVR→OpenXR 変換し SteamVR を回避。 - Quest 3 に Meta Store 版 WiVRn アプリをインストール。 ### 試して却下したもの @@ -95,7 +95,7 @@ NixOS + Meta Quest 3 で VRChat を中心とした VR 環境を構築した際 - 機能: デスクトップ画面の VR 内表示 / 仮想キーボード / 手首ウォッチUI (時計・バッテリー)。 - 起動: `wayvr --openxr` - **motoc** (nixpkgs に 0.3.6): プレイスペース調整・フルボディトラッキング校正。OVR Advanced Settings の代替。 -- 導入: `home/vr.nix` の `home.packages` に追加。 +- 導入: `home/modules/apps/vr.nix` の `home.packages` に追加。 - wayvr に無い機能: デスクトップ通知転送・リッチなメディアウィジェット・凝ったテーマ (Linux ネイティブには現状なし)。 ### その他の選択肢 (パラダイム違い) @@ -166,11 +166,11 @@ NixOS + Meta Quest 3 で VRChat を中心とした VR 環境を構築した際 | ファイル | 変更 | |---|---| | `nix-configs/pkgs/wivrn/package.nix` | WiVRn 26.6 を PR #531078 からローカル取り込み (新規) | -| `nix-configs/profiles/vr.nix` | `services.wivrn` (NVENC AV1 10bit / RUNPATH 対応 / importOXRRuntimes) | -| `nix-configs/home/vr.nix` | OpenComposite + openvrpaths.vrpath + wayvr + motoc | +| `nix-configs/feature/profiles/vr.nix` | `services.wivrn` (NVENC AV1 10bit / RUNPATH 対応 / importOXRRuntimes) | +| `nix-configs/home/modules/apps/vr.nix` | OpenComposite + openvrpaths.vrpath + wayvr + motoc | | `nix-configs/configuration.nix` | `./profiles/vr.nix` を import | -| `nix-configs/home.nix` | `./home/vr.nix` を import | -| `nix-configs/home/packages/gaming.nix` | `vrcx` (既存) | +| `nix-configs/home/profiles/workstation.nix` | `../modules/apps/vr.nix` を import | +| `nix-configs/home/modules/packages/gaming.nix` | `vrcx` (既存) | ### 起動フロー diff --git a/docs/memo/windows-nixos-dotfiles-design-options.md b/docs/memo/windows-nixos-dotfiles-design-options.md index c925c25..e6880c2 100644 --- a/docs/memo/windows-nixos-dotfiles-design-options.md +++ b/docs/memo/windows-nixos-dotfiles-design-options.md @@ -1,19 +1,19 @@ # Windows / NixOS dotfiles 設計の深掘り(選択肢) -`windows-nixos-dotfiles-design.md` の chezmoi 方針を、現リポジトリの実態に合わせて深掘りした設計選択肢メモ。ここは「決定済みの計画」ではなく「取りうる設計とトレードオフ」を並べる。 +`windows-nixos-dotfiles-design.md`の検討過程を残した資料。現在の決定事項は同文書を正とし、この文書内の`home/` source root、旧`dot_config/`、`setup_windows.ps1`、Maximal構成、両OS共通nvimなどのパスと案は移行前の記録であり、現行実装を表さない。 ## 現状から見えた制約・論点 調査で判明した、設計を縛る既存事実。 -- NixOS は `nix-configs/home/xdg.nix` で **二層戦略**を取っている。 +- NixOS は `nix-configs/home/modules/xdg/files.nix` で **二層戦略**を取っている。 - out-of-store symlink(`mkOutOfStoreSymlink`, xdg.nix:11): 実行時に書き戻る/頻繁に変わるもの。lazygit `state.yml`、nvim `lazy-lock.json`、codex `config.toml`、zsh `rc`、fcitx5 `config`、`.gitconfig`、claude `skills`。**rebuild 不要・repo を直接 live-edit** が狙い。 - in-store readonly: 静的なもの。starship、fastfetch、vim、wezterm、yazi。変更に `just os-switch` が要る。 - Claude `settings.json` は **shared base + OS 固有 hooks のマージ生成**。NixOS は `home.activation`(xdg.nix:100-108)、Windows は `setup_windows.ps1`(144-162)で**同じことを二重実装**している。 - niri / waybar / swaync は **Nix がテンプレート生成**している。per-host monitor(laptop/desktop で出力構成が違う)、Catppuccin palette、keyboard layout(`jp`/`jp106`) を Nix 値で KDL/JSON/CSS に埋め込む(niri.nix:67-186 ほか)。これらは Linux 専用かつ Nix ネイティブ。 - Windows は `setup_windows.ps1` が 41 エントリのリンク表 + symlink→hardlink→copy フォールバック(75-104)を手書きしている。 - flake は `laptop` / `desktop` / `nixos-ci` の 3 ホスト。hostname 判定あり。 -- CI は alejandra / nix-instantiate / statix / nixos-ci build。taplo・markdownlint は未統合。 +- CI は alejandra / nix-instantiate / statix / nixos-ci build。taplo は未統合。 **含意**: chezmoi が素直に置き換えられるのは「Claude settings のマージ二重実装」と「Windows のリンク表」。逆に **niri 系の Nix テンプレートは chezmoi に移せない**(移すと per-host/palette/keyboard のデータ源を失う)。そして既存が大事にしている **live-edit(out-of-store)の性質を chezmoi の既定モデルが壊しうる**——ここが最大の論点。 @@ -68,13 +68,13 @@ chezmoi source には `symlink_` エントリ(中身 = link 先 path、`.tmpl` | fcitx5 config | linux | chezmoi | B symlink | | **niri / waybar / swaync** | linux | **Nix** | Nix template(据え置き) | | package / service / systemd / system | linux | **Nix** | 据え置き | -| komorebi / yasb / whkd / powershell / cava | windows | chezmoi | A/B | +| powershell / cava / YASB | windows | chezmoi | A/B | niri 系を Nix に残すのは、per-host monitor・palette・keyboard というデータを Nix が握っているため。これらを chezmoi に移すと、そのデータを `.chezmoidata` 等へ再実装する羽目になる(次節)。Linux 専用なので Windows との共有不要= chezmoi に出す動機も薄い。 ## 共有データの扱い(palette / keyboard / per-host) -Nix 側には `specialArgs`(keyboardLayout, dotfilesDir)、per-host monitors、Catppuccin palette がある。chezmoi 側には `.chezmoidata` + `.chezmoi.hostname`。**同じ値を両 OS で使いたくなったとき**(例: Catppuccin を Windows の wezterm/yasb でも統一)にデータ源が二つになる。 +Nix 側には `specialArgs`(keyboardLayout, dotfilesDir)、per-host monitors、Catppuccin palette がある。chezmoi 側には `.chezmoidata` + `.chezmoi.hostname`。**同じ値を両 OS で使いたくなったとき**(例: Catppuccin を Windows の wezterm でも統一)にデータ源が二つになる。 - 案 1: **分離(疎結合)**。Nix の desktop データは Nix 内に閉じ、chezmoi 側 cross-platform 設定は `.chezmoidata` に独自定義。重複は許容。実装が単純で初手向き。 - 案 2: **単一ソース**。`palette.toml` / `theme.toml` を 1 つ置き、Nix は `builtins.fromTOML`、chezmoi は `.chezmoidata.toml`(または `include | fromToml`)で**両方が同じファイルを読む**。色やキーボードを一元化できる。やや構築コスト。 @@ -87,7 +87,7 @@ Nix 側には `specialArgs`(keyboardLayout, dotfilesDir)、per-host monitors ```gotmpl {{/* home/dot_claude/settings.json.tmpl */}} -{{- $base := include ".config/shared/claude/settings.json" | fromJson -}} +{{- $base := include "dot_config/shared/claude/settings.json" | fromJson -}} {{- $os := eq .chezmoi.os "windows" | ternary "windows" "nixos" -}} {{- $hooks := include (printf ".config/%s/claude/settings.hooks.json" $os) | fromJson -}} {{ mergeOverwrite $base $hooks | toPrettyJson }} @@ -97,7 +97,7 @@ Nix 側には `specialArgs`(keyboardLayout, dotfilesDir)、per-host monitors ただし注意(Codex 指摘): -- `include` は **source directory 相対**。`.chezmoiroot=home/` にするなら、上記 `.config/shared/...` は `home/` 配下に置かれている必要がある。レイアウト確定前に最小 PoC で解決を確認すること。 +- `include` は **source directory 相対**。`.chezmoiroot=home/` にするなら、上記 `dot_config/shared/...` は `home/` 配下に置かれている必要がある。レイアウト確定前に最小 PoC で解決を確認すること。 - `mergeOverwrite` は **deep merge だが deep copy ではなく右側優先、配列は連結しない**。現 PS は `hooks` を丸ごと差し替え、Nix は `recursiveUpdate`。テンプレート化前に **JSON fixture テスト**で挙動を固定し、両 OS で一致させること。 ## 書き戻し系の symlink 設計(Windows junction も統一) @@ -112,7 +112,7 @@ Nix 側には `specialArgs`(keyboardLayout, dotfilesDir)、per-host monitors - Linux: `mkOutOfStoreSymlink`(xdg.nix の out-of-store 群)を chezmoi symlink へ移譲。 - Windows: junction(setup_windows.ps1)を chezmoi symlink へ移譲。chezmoi は Windows で symlink 権限が無ければ挙動が変わるため、**ディレクトリは junction 相当が要るか**を要検証(未解決点)。 -- 実体は `live/`(仮)= chezmoi 変換外の plain ツリーに置く。現状の `.config/shared` の役割をここが引き継ぐ。 +- 実体は `live/`(仮)= chezmoi 変換外の plain ツリーに置く。現状の `dot_config/shared` の役割をここが引き継ぐ。 ## Home Manager と chezmoi の衝突回避(correctness) @@ -182,9 +182,9 @@ chezmoi は主に Windows、NixOS は現状の HM 維持。 2. **`symlink_` で Windows junction まで置換する前提は危険**。chezmoi の `symlink_` は symbolic link を作る機能で junction 互換を保証しない。現 PS の「dir=junction / file=symlink→hardlink→copy」フォールバックは Windows 権限問題を踏んだ知見。**Windows ディレクトリは `symlink_` 前提にせず `run_onchange_` で junction を明示作成**すべき。開発者モード/権限の現実も要検証。 3. **HM↔chezmoi の排他所有は「不変条件の明記」だけでは不足**。HM 生成 path と chezmoi 管理 path の**交差を CI で検出する仕組みが必須**。activation 順序では根本解決しない(同一 path を両者が持った時点で負け)。 4. **`mergeOverwrite` は deep merge だが deep copy ではない・右側優先・配列は連結されない**。現 PS は `hooks` を丸ごと差し替え、Nix は `recursiveUpdate`。**テンプレート化前に JSON fixture テストで挙動を固定**し、両 OS で一致させること。 -5. **`.chezmoiroot=home/` と `include` パスが矛盾している**(実バグ)。chezmoi の `include` は **source directory 相対**。source root を `home/` にすると、本メモの Claude 例が使う `.config/shared/...` という include パスはズレる。**最小 PoC で確認してから**実装すること。 +5. **`.chezmoiroot=home/` と `include` パスが矛盾している**(実バグ)。chezmoi の `include` は **source directory 相対**。source root を `home/` にすると、本メモの Claude 例が使う `dot_config/shared/...` という include パスはズレる。**最小 PoC で確認してから**実装すること。 6. **見落とし代替**: 「Windows だけ chezmoi、NixOS は現状 HM 維持」が技術的に最小リスク。ユーザー方針(nixos 最低限)とはズレるが、選択肢として明記すべき。次点は「Claude settings と Windows 共有対象だけ chezmoi、live-edit 系(nvim/lazygit/zsh/fcitx5)は当面 HM out-of-store のまま」。 -7. **後戻り不能点**: `.config/shared` を `live/` へ大移動 → HM リンク削除、の局面。ここで Windows junction 代替が不完全だと両 OS の足場が同時に崩れる。**先に「Windows symlink_/run_ の PoC」「Claude settings の fixture テスト」「HM/chezmoi path 交差チェック」を用意してから移行**。 +7. **後戻り不能点**: `dot_config/shared` を `live/` へ大移動 → HM リンク削除、の局面。ここで Windows junction 代替が不完全だと両 OS の足場が同時に崩れる。**先に「Windows symlink_/run_ の PoC」「Claude settings の fixture テスト」「HM/chezmoi path 交差チェック」を用意してから移行**。 Codex の自己推奨: **Hybrid**。chezmoi は Windows bootstrap / Windows 配置 / Claude settings 生成 / 真に cross-platform な静的 dotfiles から始め、NixOS の二層戦略と niri/waybar/swaync は維持。Windows dir は junction を `run_onchange_` で明示。 @@ -209,7 +209,7 @@ Codex の自己推奨: **Hybrid**。chezmoi は Windows bootstrap / Windows 配 1. **最終形(案 1 Maximal)と移行本線(案 2 Hybrid)の二段構えで進めるか**、いきなり Maximal か。 2. Codex 推奨どおり **Hybrid 起点**(Windows + Claude settings + cross-platform 静的から)にするか、ユーザー方針優先で Maximal を急ぐか。 -3. **symlink stub の実体ツリー名**(`live/`?)と `.config/shared` からの移設手順。 +3. **symlink stub の実体ツリー名**(`live/`?)と `dot_config/shared` からの移設手順。 4. **共有データを案 1(分離)で始めるか案 2(単一 toml)にするか**。 5. niri/waybar/swaync を **完全に Nix 据え置き**でよいか(Windows と見た目を揃える要求が無いか)。 6. codex config を `private_` で足りるか `encrypted_` まで要るか。 diff --git a/docs/memo/windows-nixos-dotfiles-design.md b/docs/memo/windows-nixos-dotfiles-design.md index 58d372b..4cdff82 100644 --- a/docs/memo/windows-nixos-dotfiles-design.md +++ b/docs/memo/windows-nixos-dotfiles-design.md @@ -1,239 +1,144 @@ -# Windows / NixOS dotfiles 設計 +# Windows / NixOS / WSL dotfiles設計 ## 目的 -Windows と NixOS の両方で同じ dotfiles を運用する。OS 差分は chezmoi の template と ignore で吸収し、「どちらか片方だけ設定が増える」「リンク先がズレる」「存在しない設定を参照する」といった不整合を `chezmoi diff` / `chezmoi verify` で機械的に検出できる状態にする。 +chezmoiとNixの責務を分離し、Windows、NixOS、Windows上のNixOS-WSLを同じリポジトリから管理する。1つのtarget pathを複数の仕組みで所有しないことを最優先の不変条件とする。 -最終形では、dotfiles の配置を chezmoi が単一の applier として担い、NixOS の Home Manager は package / service / desktop profile など Nix でしか表現できない領域に専念する。 +## 決定事項 -## 採用方針 +- chezmoiはHybrid方式で採用する。 +- chezmoi source rootはリポジトリ直下の`chezmoi/`とする。 +- 静的なcopy・templateは`chezmoi/`に置く。 +- アプリが書き戻す設定や直接参照する実体は`mutable/`に置く。 +- NixOSのsystem、package、service、desktop生成設定、nixvimはNixが所有する。 +- WindowsはLazyVim、NixOSはnixvimを使用する。 +- NixOS-WSLではnixvimおよびchezmoi管理のNeovim設定を使用しない。 +- Linuxのユーザー名はNixOS、NixOS-WSLともに`t4ko`へ統一する。 +- chezmoiはHome Manager activationから実行せず、明示的に`chezmoi apply`する。 -- dotfiles の適用は chezmoi に一本化する(Windows / NixOS 共通) -- 独自の契約 TOML + PowerShell executor は採用しない(chezmoi が肩代わりする) -- OS 差分は物理ディレクトリ分割ではなく chezmoi の template (`.tmpl`) と `.chezmoiignore` で表現する -- machine 固有値は `.chezmoidata` / `.chezmoi.toml.tmpl` に集約する -- Python は採用しない -- NixOS では Home Manager の dotfiles リンクを撤退し、最低限(package / service / profile)に絞る -- repository をそのまま chezmoi の source directory として使う -- **最終形は Maximal(NixOS 撤退)だが、移行は Hybrid 起点で漸進する**(Windows + Claude settings + cross-platform 静的 → live-edit 系 → Maximal) - -## 責務分担 - -### chezmoi(配置) - -repo を chezmoi の source とし、`chezmoi apply` で home 配下へ配置する。OS 差分は template と ignore で解決する。Windows / NixOS の両方でこの applier を共有する。 - -### NixOS(最低限) - -Home Manager は以下だけを管理する。 - -- package -- service / systemd user unit -- desktop profile(niri など Nix 生成が必要なもの) -- system 設定 - -dotfiles のシンボリックリンク定義は Home Manager から削除し、chezmoi に委譲する。niri のように Nix で生成する必要がある設定は引き続き Nix が持ち、chezmoi の管理対象外にする。 - -### Windows - -`scripts/setup_windows.ps1` は chezmoi の bootstrap(install + `chezmoi init --apply`)だけを担う。リンク対象の個別列挙は廃止する。 - -## ソース構成(chezmoi source) - -`.chezmoiroot` で `home/` を source root に指定し、chezmoi の naming convention で配置する。 +## ディレクトリ構成 ```text dotfiles/ - .chezmoiroot # "home" を指す - home/ - .chezmoi.toml.tmpl # chezmoi config 生成(data / OS 判定) - .chezmoidata.toml # 静的データ(editor 名など) - .chezmoiignore # OS ごとの除外 + .chezmoiroot # chezmoiを指す + chezmoi/ # chezmoi source root + .chezmoi.toml.tmpl + .chezmoiignore dot_config/ - nvim/... - starship.toml - ... - ... - nix-configs/ # NixOS: package / service / profile のみ - scripts/ - setup_windows.ps1 # chezmoi bootstrap のみ + mutable/ # chezmoi変換対象外の書き込み可能な実体 + shared/ + nvim/ # Windows LazyVim + cava/ # Windows Cava runtime files + nixos/ + nix-configs/ # NixOS、Home Manager、nixvim + scripts/ # bootstrapとCI契約検査のみ docs/ ``` -naming convention: - -- `dot_foo` → `~/.foo` -- `private_foo` → permission 0600 -- `executable_foo` → 実行ビット付与 -- `foo.tmpl` → Go template として評価 -- `symlink_foo` → symlink(ファイル内容が link 先 path) -- `run_onchange_foo` → 内容変化時に実行する script - -## OS 差分の扱い +`mutable/`はchezmoi source rootの外に置く。これにより`mutable/`自体が誤ってホームディレクトリへ配置されることを防ぐ。 -旧設計の `shared` / `windows` / `nixos` 物理分割は廃止し、chezmoi の仕組みへ置き換える。 +## 所有権 -- 共有設定: そのまま source に置く(両 OS に適用される) -- 内容が OS で異なる: `foo.tmpl` 内で `{{ if eq .chezmoi.os "windows" }}` 分岐 -- 片方だけに置く: `.chezmoiignore` で対象外の OS を除外 +機械可読な目標状態は`docs/memo/dotfiles-ownership.tsv`で管理する。 ```text -# .chezmoiignore -{{ if ne .chezmoi.os "windows" }} -AppData/** -{{ end }} -{{ if ne .chezmoi.os "linux" }} -dot_config/niri/** -{{ end }} -``` - -## 配置先が OS で違う場合 - -nvim のように、Linux では `~/.config/nvim`、Windows では `%LOCALAPPDATA%\nvim` と配置先が異なるものは次のように扱う。 - -- 正準の内容は `dot_config/nvim` に一度だけ置く -- Windows 向けは `AppData/Local/nvim` を `symlink_`、もしくは `run_onchange_` の junction 作成で `dot_config/nvim` の実体へ向ける -- `.chezmoiignore` で OS ごとに不要な側を除外する - -これで内容の二重管理を避けつつ、OS ごとの配置先差分を吸収する。 - -## 実行時に書き戻される設定 - -Claude / Codex のように tool が runtime で書き戻す設定は、chezmoi の managed copy にすると drift する。これらは次のいずれかで扱う。 - -- `symlink_` で repo 作業ツリーの実体へ link する(旧 `outOfStoreSymlink` 相当) -- `modify_` script で既存内容を尊重してマージする - -推奨は symlink。tool の書き込みが直接 repo に届き、`chezmoi apply` と競合しない。 - -## machine データ - -`.chezmoi.toml.tmpl` で OS と machine を判定し、`.chezmoidata.toml` の静的値と合わせて template に渡す。 - -```toml -# .chezmoidata.toml -editor = "nvim" -``` - -```toml -# .chezmoi.toml.tmpl -[data] -hostname = {{ .chezmoi.hostname | quote }} -os = {{ .chezmoi.os | quote }} -``` - -template 側ではこれらを `{{ .editor }}` / `{{ .hostname }}` として参照する。 - -## 整合性チェック - -独自の PowerShell checker は廃止し、chezmoi 標準を使う。 - -- `chezmoi doctor`: 環境の健全性 -- `chezmoi verify`: 適用済み状態と source の一致 -- `chezmoi diff`: 差分(CI で空であることを確認) -- `chezmoi execute-template`: template が両 OS で評価できるか - -## CI - -`just ci` の例: - -```sh -chezmoi doctor -chezmoi diff --source home # diff が無いこと -just check-ownership # HM target と chezmoi target が素であること -just check-claude-settings # 生成 settings.json が fixture と一致すること -alejandra --check . -nix build .#nixosConfigurations.nixos-ci.config.system.build.toplevel +(profile, target path) -> exactly one owner ``` -- `check-ownership`: Home Manager が生成する target path 集合と chezmoi が管理する target path 集合の**交差が空**であることを検査する(二重所有の事故防止)。不変条件の明記だけでは不足なので CI で機械検出する。 -- `check-claude-settings`: `mergeOverwrite` で生成した `settings.json` が、固定した JSON fixture(=旧 Nix `recursiveUpdate` / 旧 PowerShell マージと一致する期待値)と一致することを検査する。配列・深いキーの扱いの差異を回帰検出する。 +ownerは次のいずれかとする。 -Windows 側の差分は GitHub Actions の windows runner で `chezmoi apply --dry-run` を回して検証する。 +- `chezmoi`: copy、template、symlink、Windows junction +- `nix`: NixOSまたはHome Managerによる生成・配置 +- `unmanaged`: 意図的に配置しない -## bootstrap +移行時は必ず既存ownerからtargetを削除してから新ownerへ追加する。同じコミット内でも、この順序でactivationとapplyを確認する。 -両 OS 共通: +## 環境別の責務 -```sh -chezmoi init --apply -``` +| 対象 | Windows | NixOS | NixOS-WSL | +|---|---|---|---| +| system / service | Windows | NixOS | NixOS-WSL | +| package | winget / Scoop / mise | Nix / Home Manager | Nix / Home Manager | +| Neovim | chezmoi + LazyVim | Nix + nixvim | 管理しない | +| shell | chezmoi + PowerShell | Home Manager + zsh | Home Manager + zsh | +| Git / Starship / Yazi / Lazygit | chezmoi | chezmoi | chezmoi | +| WezTerm | chezmoi | chezmoi | 管理しない | +| YASB | chezmoi | 対象外 | 対象外 | +| niri / waybar / swaync | 対象外 | Nix | 対象外 | +| `/etc/wsl.conf` | 対象外 | 対象外 | NixOS-WSL | -- Windows: `setup_windows.ps1` が chezmoi を winget で導入し、`chezmoi init --apply` を呼ぶ -- NixOS: chezmoi を package に追加し、初回のみ `chezmoi init --apply`。以降は `chezmoi apply` +## Neovim -## NixOS 連携の方針 - -Home Manager から dotfiles リンクを撤去する。`chezmoi apply` を Nix の activation に組み込むことも可能だが、Nix eval と chezmoi を密結合させないため、`chezmoi apply` は明示実行(手動 or systemd user oneshot)にとどめる。 - -niri など Nix 生成が必須の設定は Nix 側に残し、chezmoi の管理対象外(`.chezmoiignore`)にする。 +### Windows -## tools.toml(package 整合) +LazyVimの実体を`mutable/nvim`へ置き、`%LOCALAPPDATA%\nvim`からjunctionで参照する。Windowsのdirectory symlink権限に依存しないよう、chezmoiの`run_after_` PowerShell scriptでjunctionを収束させる。 -dotfiles とは別に package の整合を取りたい場合、chezmoi の `.chezmoidata` や `run_onchange_` script で扱える。Windows は winget、NixOS は Nix が package を持つため、capability 単位の管理は将来拡張とする。最初は dotfiles の chezmoi 化を優先する。 +### NixOS -## 段階移行(Hybrid 起点 → Maximal 最終形) +`feat/nixvim`でnixvimへの移行を完了した。Home Managerの`programs.neovim`と`~/.config/nvim` linkは撤去済みで、Nixvim設定は`nix-configs/home/modules/editors/nixvim`が所有する。 -最終形は案 1 Maximal(NixOS は dotfiles 配置から撤退)。ただし一気に寄せず、リスクの低い領域から段階的に chezmoi へ移す。各 Phase は exit 条件を満たしてから次へ進む。設計の選択肢・トレードオフは `windows-nixos-dotfiles-design-options.md` を参照。 +### NixOS-WSL -### Phase 0: 先行 PoC(移行前に必須) +nixvimをimportせず、chezmoiでも`~/.config/nvim`を生成しない。将来editorが必要になった場合は、この所有権を明示的に再決定する。 -実体は動かさず、危険な前提を実機で潰す。 +## chezmoi profile -- P1. Windows link PoC: `symlink_` のディレクトリ挙動を検証し、junction は `run_onchange_` で明示作成する方式を確立(権限/開発者モード込み)。 -- P2. Claude settings fixture: `mergeOverwrite` 出力が旧 Nix `recursiveUpdate` / 旧 PowerShell マージと一致するか JSON fixture で固定。 -- P3. HM↔chezmoi path 交差 CI: 両者の target path 集合が素であることを検査する `check-ownership` を用意。 -- P4. `.chezmoiroot` × `include` PoC: source root を `home/` にした時の `include` 解決を最小再現で確認。 +初期化時に次のprofileを選択し、chezmoi configの`data.profile`へ保存する。 -exit: P1〜P4 がすべて green。Windows ディレクトリ配置と Claude settings 生成の方式が確定。 +- `windows` +- `nixos` +- `wsl` -### Phase 1: Hybrid 起点 +`.chezmoi.os`だけではNixOSとNixOS-WSLを区別できないため、OS判定の代わりにprofileをtarget選択へ使用する。ユーザー名は全Linux環境で`t4ko`とする。 -chezmoi が明確に勝つ領域だけ先に移す。NixOS の live-edit 二層はまだ触らない。 +## 移行フェーズ -- Windows: `setup_windows.ps1` を chezmoi bootstrap のみへ簡略化。Windows 専用配置(komorebi / yasb / whkd / cava / powershell / mise / ccwin)を chezmoi へ。 -- Claude `settings.json`: 両 OS とも chezmoi template(モード C)へ集約。`xdg.nix` の activation と PS マージを撤去。 -- cross-platform 静的(starship / fastfetch / vim / wezterm / yazi): chezmoi managed copy(モード A)へ。NixOS の in-store エントリは HM から削除(churn しないので低リスク)。 +### Phase 0: 契約とPoC -exit: 上記 path が HM から消え chezmoi 所有へ移行。`check-ownership` green。両 OS で `chezmoi diff` が空。 +- source root、profile、所有権表を追加する。 +- 3 profileのtemplateを非対話で評価する。 +- Windows junctionを一時ディレクトリで検証する。 +- Claude settingsのmerge結果をfixture化する。 +- Nix/Home Managerとchezmoiのtarget交差検査を追加する。 -### Phase 2: live-edit 系の移譲 +### Phase 1: NixOS-WSL -書き戻し・churn 系を chezmoi の symlink stub(モード B)へ。P1 の junction 方式が前提。 +実装済み。`nixosConfigurations.wsl`と`nix-configs/hosts/wsl/home.nix`を入口とする。 -- nvim / lazygit / zsh / fcitx5 / codex / gitconfig / claude skills を `symlink_`(実体は plain ツリー)へ。 -- NixOS の out-of-store symlink(`mkOutOfStoreSymlink`)を chezmoi 由来へ置換。live-edit・rebuild 不要の性質は維持。 -- codex config は `private_`(必要なら `encrypted_`)で権限/秘匿を再現。 +- `nixos-wsl` inputと`nixosConfigurations.wsl`を追加する。 +- usernameとhome directoryをホスト引数化する。 +- desktopを含まないHome Manager profileを作る。 +- `/etc/wsl.conf`とWindows interopをNixで管理する。 -exit: out-of-store 群が chezmoi 所有へ移行。両 OS で live-edit が rebuild なしに効くことを確認。 +### Phase 2: Windows -### Phase 3: Maximal 化(NixOS 最低限) +- Windows LazyVimとcavaを`mutable`へ移し、chezmoiのjunction所有へ切り替えた。 +- PowerShell、YASB、mise、ccwin-notifyをchezmoi sourceへ移した。 +- 独自の`setup_windows.ps1`を廃止し、`bootstrap.ps1`からchezmoiを直接適用する。 -- `xdg.nix` の dotfile-link 定義を削除し、HM は package / service / systemd / system のみへ縮小。 -- niri / waybar / swaync は **Nix 据え置き**(per-host monitor / palette / keyboard を Nix が握るため)。`.chezmoiignore` で chezmoi 対象外に。 -- 旧 contract / 暫定 checker 案を破棄。 +### Phase 3: NixOS nixvim -exit: NixOS の dotfiles 配置が chezmoi 一本化(Nix 生成必須の Linux desktop を除く)。 +- `feat/nixvim`でNixOSのnixvim移行を完了した。 +- LazyVimとの機能差分を必要に応じて追跡する。 -## ファイル別 所有 / モード対応 +### Phase 4: 共有設定 -| 対象 | OS | 現状 | 移行先所有 | モード | Phase | -|------|----|------|-----------|--------|-------| -| claude settings.json | both | activation/PS マージ | chezmoi | C template | 1 | -| starship / fastfetch / vim / wezterm / yazi | both | HM in-store | chezmoi | A copy | 1 | -| komorebi / yasb / whkd / cava / powershell / mise / ccwin | windows | PS リンク表 | chezmoi | A/B | 1 | -| nvim / lazygit / gitconfig / claude skills | both | HM out-of-store | chezmoi | B symlink | 2 | -| zsh rc / fcitx5 config | linux | HM out-of-store | chezmoi | B symlink | 2 | -| codex config.toml | both | HM out-of-store | chezmoi | B symlink + private_ | 2 | -| niri / waybar / swaync | linux | Nix template | **Nix 据え置き** | — | — | -| package / service / system | linux | Nix | **Nix 据え置き** | — | — | +- Starship、Fastfetch、Git、Vim、Yazi、Lazygit、WezTerm、Zedをchezmoiへ移した。 +- 書き戻し対象だけを`mutable/shared`へ置いた。 +- Home Managerの所有をNix固有targetだけへ縮小した。 -## 判断 +### Phase 5: 整理 -chezmoi を採用することで、Windows / NixOS の dotfiles 配置を単一の applier に統一できる。独自契約 + PowerShell executor を実装・保守する必要がなくなり、OS 差分は chezmoi の template と ignore に集約される。NixOS は最終的に Nix にしかできない領域(package / service / profile + Nix 生成必須の Linux desktop)に専念し、dotfiles 配置からは撤退する。 +- Claude settings生成のNix/PowerShell二重実装をchezmoi templateへ統合した。 +- 存在しないsourceを参照する旧Windows設定と補助scriptを削除した。 +- GitHub ActionsでNixOS 4構成とWindows profileの可用性を検証する。 -ただし独立レビュー(Codex)の指摘どおり、既存 NixOS の out-of-store/in-store 二層戦略は成熟しており、一気に捨てるのはリスクが高い。よって **Maximal を最終形に据えつつ、Hybrid 起点で段階移行**する。先行 PoC(Windows link / Claude fixture / path 交差 CI / chezmoiroot×include)で危険な前提を潰してから着手する。 +## 検証 -## 設計の深掘り +```sh +just chezmoi-check +just syntax +just ci +``` -取りうる設計とトレードオフ(適用モデルの 3 分岐、Nix との責務境界、HM との衝突回避、共有データの扱いなど)は `windows-nixos-dotfiles-design-options.md` に分離して整理する。 +移行中も既存環境へ直接applyするテストは行わず、一時HOMEまたはdry-runで確認してから実機へ適用する。 diff --git a/flake.lock b/flake.lock index 81ff225..76f0721 100644 --- a/flake.lock +++ b/flake.lock @@ -33,34 +33,17 @@ "type": "github" } }, - "claudex": { - "flake": false, - "locked": { - "lastModified": 1772183396, - "narHash": "sha256-YRsSUzrElmsBVTfUrP5iVtbCH6UA/oE+tP60juAf4zg=", - "owner": "StringKe", - "repo": "claudex", - "rev": "a1eb95957e71ab85d91aae8cdc3b7bb78bd4e9ea", - "type": "github" - }, - "original": { - "owner": "StringKe", - "ref": "v0.2.4", - "repo": "claudex", - "type": "github" - } - }, "codex-desktop-linux": { "inputs": { "flake-utils": "flake-utils", "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1784548123, - "narHash": "sha256-1wlOwTJ1BF5QXrvj4jB54pTHlrM1FcXxxGzbuzp0srY=", + "lastModified": 1784875470, + "narHash": "sha256-qW04dQkQjvrpTgztSMItCbEu/h91U9CyeLhOPHUdrB0=", "owner": "ilysenko", "repo": "codex-desktop-linux", - "rev": "a29387ebc1c76cc51c942d97c5f5c609a81cdccf", + "rev": "15f3bd4fabc44bc0afba85b16d0121f0b4abd052", "type": "github" }, "original": { @@ -100,6 +83,22 @@ "type": "github" } }, + "flake-compat_2": { + "flake": false, + "locked": { + "lastModified": 1767039857, + "narHash": "sha256-vNpUSpF5Nuw8xvDLj2KCwwksIbjua2LZCqhV1LNRDns=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "5edf11c44bc78a0d334f6334cdaf7d60d732daab", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, "flake-parts": { "inputs": { "nixpkgs-lib": [ @@ -121,6 +120,27 @@ "type": "github" } }, + "flake-parts_2": { + "inputs": { + "nixpkgs-lib": [ + "nixvim", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1778716662, + "narHash": "sha256-m1Yf0wZ8j1OHjTc2UwHwyQRSnNeSgLJOd7q5Y45hzi4=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "f7c1a2d347e4c52d5fb8d10cb4d94b5884e546fb", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, "flake-utils": { "inputs": { "systems": "systems" @@ -248,6 +268,28 @@ "type": "github" } }, + "nixos-wsl": { + "inputs": { + "flake-compat": "flake-compat_2", + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1784642409, + "narHash": "sha256-hcbDqFuySAJawljt5r0sKBCJKYnbtGD0T/ZIozH1Dq0=", + "owner": "nix-community", + "repo": "NixOS-WSL", + "rev": "eaeb18da90024448a60eb1ec7132eafa4003404e", + "type": "github" + }, + "original": { + "owner": "nix-community", + "ref": "main", + "repo": "NixOS-WSL", + "type": "github" + } + }, "nixpkgs": { "locked": { "lastModified": 1772773019, @@ -313,6 +355,22 @@ } }, "nixpkgs_4": { + "locked": { + "lastModified": 1781216227, + "narHash": "sha256-9mUW6gNwoN2SWc/l0fW4svPNOulXLl8ijqKyeSOGgJE=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "a0374025a863d007d98e3297f6aa46cc3141c2f0", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-26.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_5": { "locked": { "lastModified": 1772542754, "narHash": "sha256-WGV2hy+VIeQsYXpsLjdr4GvHv5eECMISX1zKLTedhdg=", @@ -328,7 +386,7 @@ "type": "github" } }, - "nixpkgs_5": { + "nixpkgs_6": { "locked": { "lastModified": 1778869304, "narHash": "sha256-30sZNZoA1cqF5JNO9fVX+wgiQYjB7HJqqJ4ztCDeBZE=", @@ -344,6 +402,27 @@ "type": "github" } }, + "nixvim": { + "inputs": { + "flake-parts": "flake-parts_2", + "nixpkgs": "nixpkgs_4", + "systems": "systems_3" + }, + "locked": { + "lastModified": 1782919967, + "narHash": "sha256-pRwjfB5HQJ3m8J8bOR43pPHtHI7VUJSqwLA3P06cOY0=", + "owner": "nix-community", + "repo": "nixvim", + "rev": "667c8471f4a0fb24d702d1a61af8609f1a5f1ba6", + "type": "github" + }, + "original": { + "owner": "nix-community", + "ref": "nixos-26.05", + "repo": "nixvim", + "type": "github" + } + }, "pre-commit": { "inputs": { "flake-compat": "flake-compat", @@ -369,13 +448,14 @@ }, "root": { "inputs": { - "claudex": "claudex", "codex-desktop-linux": "codex-desktop-linux", "home-manager": "home-manager", "lanzaboote": "lanzaboote", "llm-agents": "llm-agents", "nixos-loading-plymouth": "nixos-loading-plymouth", + "nixos-wsl": "nixos-wsl", "nixpkgs": "nixpkgs_3", + "nixvim": "nixvim", "spotify-cli": "spotify-cli", "vial-qmk": "vial-qmk", "vicinae": "vicinae" @@ -404,7 +484,7 @@ }, "soulver-cpp": { "inputs": { - "nixpkgs": "nixpkgs_5", + "nixpkgs": "nixpkgs_6", "nixpkgs-libxml2": "nixpkgs-libxml2" }, "locked": { @@ -486,6 +566,21 @@ "type": "github" } }, + "systems_4": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, "treefmt-nix": { "inputs": { "nixpkgs": [ @@ -527,9 +622,9 @@ }, "vicinae": { "inputs": { - "nixpkgs": "nixpkgs_4", + "nixpkgs": "nixpkgs_5", "soulver-cpp": "soulver-cpp", - "systems": "systems_3" + "systems": "systems_4" }, "locked": { "lastModified": 1784464594, diff --git a/flake.nix b/flake.nix index 6858ae3..3f28d69 100644 --- a/flake.nix +++ b/flake.nix @@ -14,6 +14,13 @@ inputs.nixpkgs.follows = "nixpkgs"; }; + nixvim.url = "github:nix-community/nixvim/nixos-26.05"; + + nixos-wsl = { + url = "github:nix-community/NixOS-WSL/main"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + vial-qmk = { url = "git+https://github.com/vial-kb/vial-qmk?submodules=1"; flake = false; @@ -23,11 +30,6 @@ llm-agents.url = "github:numtide/llm-agents.nix"; - claudex = { - url = "github:StringKe/claudex/v0.2.4"; - flake = false; - }; - codex-desktop-linux.url = "github:ilysenko/codex-desktop-linux"; spotify-cli = { @@ -52,11 +54,12 @@ self, nixpkgs, home-manager, + nixvim, + nixos-wsl, vial-qmk, vicinae, lanzaboote, llm-agents, - claudex, nixos-loading-plymouth, spotify-cli, codex-desktop-linux, @@ -74,77 +77,48 @@ fcitxLayout = "jp"; }; - mkNixos = { - configuration, - homeConfiguration, - extraModules ? [], - }: - nixpkgs.lib.nixosSystem { - inherit system; - specialArgs = { - inherit dotfilesDir keyboardLayout; - nixosLoadingPlymouth = nixos-loading-plymouth; - }; - modules = - [ - home-manager.nixosModules.home-manager - vicinae.nixosModules.default - nixos-loading-plymouth.nixosModules.default - configuration - ] - ++ extraModules - ++ [ - { - nixpkgs.overlays = [ - spotify-cli.overlays.default - # actrun.inputs.moonbit-overlay.overlays.default - # actrun.overlays.default - # (final: prev: { - # actrun = prev.actrun.overrideAttrs (old: { - # nativeBuildInputs = (old.nativeBuildInputs or []) ++ [final.makeWrapper]; - # postFixup = - # (old.postFixup or "") - # + '' - # for bin in "$out"/bin/*; do - # wrapProgram "$bin" --prefix LD_LIBRARY_PATH : "${final.openssl.out}/lib" - # done - # ''; - # }); - # }) - ]; - home-manager = { - useGlobalPkgs = true; - useUserPackages = true; - backupFileExtension = "hm-backup"; - extraSpecialArgs = { - inherit claudex dotfilesDir keyboardLayout llm-agents; - }; - sharedModules = [ - vicinae.homeManagerModules.default - codex-desktop-linux.homeManagerModules.default - ]; - users.t4ko = import homeConfiguration; - }; - } - ]; - }; + mkNixos = import ./nix-configs/lib/mk-nixos.nix { + inherit + codex-desktop-linux + home-manager + llm-agents + nixos-loading-plymouth + nixpkgs + nixvim + spotify-cli + system + vicinae + ; + }; laptop = mkNixos { configuration = ./nix-configs/hosts/laptop; - homeConfiguration = ./nix-configs/home.nix; + homeConfiguration = ./nix-configs/hosts/laptop/home.nix; + inherit dotfilesDir keyboardLayout; }; desktop = mkNixos { configuration = ./nix-configs/hosts/desktop; - homeConfiguration = ./nix-configs/home.nix; + homeConfiguration = ./nix-configs/hosts/desktop/home.nix; + inherit dotfilesDir keyboardLayout; extraModules = [lanzaboote.nixosModules.lanzaboote]; }; nixosCi = mkNixos { - configuration = ./nix-configs/configuration-ci.nix; - homeConfiguration = ./nix-configs/home-ci.nix; + configuration = ./nix-configs/hosts/ci; + homeConfiguration = ./nix-configs/home/profiles/ci.nix; + inherit dotfilesDir keyboardLayout; + }; + wsl = mkNixos { + configuration = ./nix-configs/hosts/wsl; + homeConfiguration = ./nix-configs/hosts/wsl/home.nix; + inherit dotfilesDir keyboardLayout; + platformModules = [nixos-wsl.nixosModules.default]; + sharedHomeModules = []; + userExtraGroups = ["wheel"]; + editor = "vim"; }; in { nixosConfigurations = { - inherit laptop desktop; + inherit laptop desktop wsl; default = laptop; nixos-ci = nixosCi; }; @@ -153,6 +127,7 @@ default = pkgs.mkShell { packages = with pkgs; [ avrdude + chezmoi dfu-util gcc-arm-embedded git diff --git a/justfile b/justfile index 1986b7d..921a552 100644 --- a/justfile +++ b/justfile @@ -1,30 +1,45 @@ default: - @just --list + @just --list os-switch host="laptop": - nh os switch . -H {{host}} + nh os switch . -H {{ host }} + just dotfiles-apply nixos + +wsl-switch: + sudo nixos-rebuild switch --flake .#wsl + just dotfiles-apply wsl + +dotfiles-apply profile: + chezmoi --source "{{ justfile_directory() }}" init --apply --promptChoice "Environment profile={{ profile }}" skills-sync: - cd .config/shared/apm && apm install + cd mutable/shared/apm && apm install fmt: - alejandra . - nix run nixpkgs#markdownlint-cli2 -- --fix - git ls-files '*.lua' | xargs -r nix run nixpkgs#stylua -- + git ls-files --cached --others --exclude-standard '*.nix' | while read -r file; do [ ! -f "$file" ] || printf '%s\0' "$file"; done | xargs -0 -r alejandra + git ls-files --cached --others --exclude-standard '*.lua' | while read -r file; do [ ! -f "$file" ] || printf '%s\0' "$file"; done | xargs -0 -r nix run nixpkgs#stylua -- syntax: - git ls-files '*.nix' | xargs -r -n1 nix-instantiate --parse --quiet >/dev/null + git ls-files --cached --others --exclude-standard '*.nix' | while read -r file; do [ ! -f "$file" ] || printf '%s\0' "$file"; done | xargs -0 -r -n1 nix-instantiate --parse --quiet >/dev/null fmt-check: - alejandra --check . - nix run nixpkgs#markdownlint-cli2 -- - git ls-files '*.lua' | xargs -r nix run nixpkgs#stylua -- --check + git ls-files --cached --others --exclude-standard '*.nix' | while read -r file; do [ ! -f "$file" ] || printf '%s\0' "$file"; done | xargs -0 -r alejandra --check + git ls-files --cached --others --exclude-standard '*.lua' | while read -r file; do [ ! -f "$file" ] || printf '%s\0' "$file"; done | xargs -0 -r nix run nixpkgs#stylua -- --check lint: - statix check . + statix check . + +chezmoi-check: + nix develop --command bash scripts/check_chezmoi.sh + +wsl-check: + bash scripts/check_wsl.sh + +profile-check: + bash scripts/check_profiles.sh build host="laptop": - nix build .#nixosConfigurations.{{host}}.config.system.build.toplevel + nix build .#nixosConfigurations.{{ host }}.config.system.build.toplevel -ci: syntax fmt-check - nix build .#nixosConfigurations.nixos-ci.config.system.build.toplevel +ci: syntax fmt-check chezmoi-check wsl-check profile-check + nix build .#nixosConfigurations.nixos-ci.config.system.build.toplevel diff --git a/.config/windows/cava/shaders/bar_spectrum.frag b/mutable/cava/shaders/bar_spectrum.frag similarity index 100% rename from .config/windows/cava/shaders/bar_spectrum.frag rename to mutable/cava/shaders/bar_spectrum.frag diff --git a/.config/windows/cava/shaders/eye_of_phi.frag b/mutable/cava/shaders/eye_of_phi.frag similarity index 100% rename from .config/windows/cava/shaders/eye_of_phi.frag rename to mutable/cava/shaders/eye_of_phi.frag diff --git a/.config/windows/cava/shaders/northern_lights.frag b/mutable/cava/shaders/northern_lights.frag similarity index 100% rename from .config/windows/cava/shaders/northern_lights.frag rename to mutable/cava/shaders/northern_lights.frag diff --git a/.config/windows/cava/shaders/orion_circle.frag b/mutable/cava/shaders/orion_circle.frag similarity index 100% rename from .config/windows/cava/shaders/orion_circle.frag rename to mutable/cava/shaders/orion_circle.frag diff --git a/.config/windows/cava/shaders/orion_circle_rotate.frag b/mutable/cava/shaders/orion_circle_rotate.frag similarity index 100% rename from .config/windows/cava/shaders/orion_circle_rotate.frag rename to mutable/cava/shaders/orion_circle_rotate.frag diff --git a/.config/windows/cava/shaders/orion_saturn_core.frag b/mutable/cava/shaders/orion_saturn_core.frag similarity index 100% rename from .config/windows/cava/shaders/orion_saturn_core.frag rename to mutable/cava/shaders/orion_saturn_core.frag diff --git a/.config/windows/cava/shaders/orion_saturn_subring.frag b/mutable/cava/shaders/orion_saturn_subring.frag similarity index 100% rename from .config/windows/cava/shaders/orion_saturn_subring.frag rename to mutable/cava/shaders/orion_saturn_subring.frag diff --git a/.config/windows/cava/shaders/pass_through.vert b/mutable/cava/shaders/pass_through.vert similarity index 100% rename from .config/windows/cava/shaders/pass_through.vert rename to mutable/cava/shaders/pass_through.vert diff --git a/.config/windows/cava/shaders/spectrogram.frag b/mutable/cava/shaders/spectrogram.frag similarity index 100% rename from .config/windows/cava/shaders/spectrogram.frag rename to mutable/cava/shaders/spectrogram.frag diff --git a/.config/windows/cava/shaders/winamp_line_style_spectrum.frag b/mutable/cava/shaders/winamp_line_style_spectrum.frag similarity index 100% rename from .config/windows/cava/shaders/winamp_line_style_spectrum.frag rename to mutable/cava/shaders/winamp_line_style_spectrum.frag diff --git a/.config/windows/cava/themes/solarized_dark b/mutable/cava/themes/solarized_dark similarity index 92% rename from .config/windows/cava/themes/solarized_dark rename to mutable/cava/themes/solarized_dark index 200057c..e8ea78e 100644 --- a/.config/windows/cava/themes/solarized_dark +++ b/mutable/cava/themes/solarized_dark @@ -12,4 +12,4 @@ horizontal_gradient_color_1 = '#586e75' horizontal_gradient_color_2 = '#b58900' horizontal_gradient_color_3 = '#839496' -blend_direction = 'up' \ No newline at end of file +blend_direction = 'up' diff --git a/.config/windows/cava/themes/tricolor b/mutable/cava/themes/tricolor similarity index 88% rename from .config/windows/cava/themes/tricolor rename to mutable/cava/themes/tricolor index b908137..0fc5c05 100644 --- a/.config/windows/cava/themes/tricolor +++ b/mutable/cava/themes/tricolor @@ -7,4 +7,4 @@ horizontal_gradient_color_4 = '#f2dde1' horizontal_gradient_color_5 = '#cbc7d8' horizontal_gradient_color_6 = '#8db7d2' horizontal_gradient_color_7 = '#5e62a9' -horizontal_gradient_color_8 = '#434279' \ No newline at end of file +horizontal_gradient_color_8 = '#434279' diff --git a/.config/nixos/fcitx5/config b/mutable/nixos/fcitx5/config similarity index 100% rename from .config/nixos/fcitx5/config rename to mutable/nixos/fcitx5/config diff --git a/.config/shared/nvim/.gitignore b/mutable/nvim/.gitignore similarity index 100% rename from .config/shared/nvim/.gitignore rename to mutable/nvim/.gitignore diff --git a/.config/shared/nvim/.neoconf.json b/mutable/nvim/.neoconf.json similarity index 100% rename from .config/shared/nvim/.neoconf.json rename to mutable/nvim/.neoconf.json diff --git a/.config/shared/nvim/.typos.toml b/mutable/nvim/.typos.toml similarity index 100% rename from .config/shared/nvim/.typos.toml rename to mutable/nvim/.typos.toml diff --git a/.config/shared/nvim/LICENSE b/mutable/nvim/LICENSE similarity index 100% rename from .config/shared/nvim/LICENSE rename to mutable/nvim/LICENSE diff --git a/.config/shared/nvim/README.md b/mutable/nvim/README.md similarity index 100% rename from .config/shared/nvim/README.md rename to mutable/nvim/README.md diff --git a/.config/shared/nvim/init.lua b/mutable/nvim/init.lua similarity index 100% rename from .config/shared/nvim/init.lua rename to mutable/nvim/init.lua diff --git a/.config/shared/nvim/lazy-lock.json b/mutable/nvim/lazy-lock.json similarity index 100% rename from .config/shared/nvim/lazy-lock.json rename to mutable/nvim/lazy-lock.json diff --git a/.config/shared/nvim/lazyvim.json b/mutable/nvim/lazyvim.json similarity index 98% rename from .config/shared/nvim/lazyvim.json rename to mutable/nvim/lazyvim.json index d8bcaf6..271ed85 100644 --- a/.config/shared/nvim/lazyvim.json +++ b/mutable/nvim/lazyvim.json @@ -7,4 +7,4 @@ "NEWS.md": "11866" }, "version": 8 -} \ No newline at end of file +} diff --git a/.config/shared/nvim/lua/config/autocmds.lua b/mutable/nvim/lua/config/autocmds.lua similarity index 100% rename from .config/shared/nvim/lua/config/autocmds.lua rename to mutable/nvim/lua/config/autocmds.lua diff --git a/.config/shared/nvim/lua/config/keymaps.lua b/mutable/nvim/lua/config/keymaps.lua similarity index 100% rename from .config/shared/nvim/lua/config/keymaps.lua rename to mutable/nvim/lua/config/keymaps.lua diff --git a/.config/shared/nvim/lua/config/lazy.lua b/mutable/nvim/lua/config/lazy.lua similarity index 100% rename from .config/shared/nvim/lua/config/lazy.lua rename to mutable/nvim/lua/config/lazy.lua diff --git a/.config/shared/nvim/lua/config/options.lua b/mutable/nvim/lua/config/options.lua similarity index 100% rename from .config/shared/nvim/lua/config/options.lua rename to mutable/nvim/lua/config/options.lua diff --git a/.config/shared/nvim/lua/plugins/base/snacks.lua b/mutable/nvim/lua/plugins/base/snacks.lua similarity index 100% rename from .config/shared/nvim/lua/plugins/base/snacks.lua rename to mutable/nvim/lua/plugins/base/snacks.lua diff --git a/.config/shared/nvim/lua/plugins/base/ufo.lua b/mutable/nvim/lua/plugins/base/ufo.lua similarity index 100% rename from .config/shared/nvim/lua/plugins/base/ufo.lua rename to mutable/nvim/lua/plugins/base/ufo.lua diff --git a/.config/shared/nvim/lua/plugins/base/vimdoc-ja.lua b/mutable/nvim/lua/plugins/base/vimdoc-ja.lua similarity index 100% rename from .config/shared/nvim/lua/plugins/base/vimdoc-ja.lua rename to mutable/nvim/lua/plugins/base/vimdoc-ja.lua diff --git a/.config/shared/nvim/lua/plugins/base/winresizer.lua b/mutable/nvim/lua/plugins/base/winresizer.lua similarity index 100% rename from .config/shared/nvim/lua/plugins/base/winresizer.lua rename to mutable/nvim/lua/plugins/base/winresizer.lua diff --git a/.config/shared/nvim/lua/plugins/base/yazi.lua b/mutable/nvim/lua/plugins/base/yazi.lua similarity index 100% rename from .config/shared/nvim/lua/plugins/base/yazi.lua rename to mutable/nvim/lua/plugins/base/yazi.lua diff --git a/.config/shared/nvim/lua/plugins/disable.lua b/mutable/nvim/lua/plugins/disable.lua similarity index 100% rename from .config/shared/nvim/lua/plugins/disable.lua rename to mutable/nvim/lua/plugins/disable.lua diff --git a/.config/shared/nvim/lua/plugins/editor/claude-code.lua b/mutable/nvim/lua/plugins/editor/claude-code.lua similarity index 100% rename from .config/shared/nvim/lua/plugins/editor/claude-code.lua rename to mutable/nvim/lua/plugins/editor/claude-code.lua diff --git a/.config/shared/nvim/lua/plugins/editor/codic.lua b/mutable/nvim/lua/plugins/editor/codic.lua similarity index 100% rename from .config/shared/nvim/lua/plugins/editor/codic.lua rename to mutable/nvim/lua/plugins/editor/codic.lua diff --git a/.config/shared/nvim/lua/plugins/editor/color-picker.lua b/mutable/nvim/lua/plugins/editor/color-picker.lua similarity index 100% rename from .config/shared/nvim/lua/plugins/editor/color-picker.lua rename to mutable/nvim/lua/plugins/editor/color-picker.lua diff --git a/.config/shared/nvim/lua/plugins/editor/compiler.lua b/mutable/nvim/lua/plugins/editor/compiler.lua similarity index 100% rename from .config/shared/nvim/lua/plugins/editor/compiler.lua rename to mutable/nvim/lua/plugins/editor/compiler.lua diff --git a/.config/shared/nvim/lua/plugins/editor/diffview.lua b/mutable/nvim/lua/plugins/editor/diffview.lua similarity index 100% rename from .config/shared/nvim/lua/plugins/editor/diffview.lua rename to mutable/nvim/lua/plugins/editor/diffview.lua diff --git a/.config/shared/nvim/lua/plugins/editor/emmet.lua b/mutable/nvim/lua/plugins/editor/emmet.lua similarity index 100% rename from .config/shared/nvim/lua/plugins/editor/emmet.lua rename to mutable/nvim/lua/plugins/editor/emmet.lua diff --git a/.config/shared/nvim/lua/plugins/editor/git.lua b/mutable/nvim/lua/plugins/editor/git.lua similarity index 100% rename from .config/shared/nvim/lua/plugins/editor/git.lua rename to mutable/nvim/lua/plugins/editor/git.lua diff --git a/.config/shared/nvim/lua/plugins/editor/html-preview.lua b/mutable/nvim/lua/plugins/editor/html-preview.lua similarity index 100% rename from .config/shared/nvim/lua/plugins/editor/html-preview.lua rename to mutable/nvim/lua/plugins/editor/html-preview.lua diff --git a/.config/shared/nvim/lua/plugins/editor/markdown-preview.lua b/mutable/nvim/lua/plugins/editor/markdown-preview.lua similarity index 85% rename from .config/shared/nvim/lua/plugins/editor/markdown-preview.lua rename to mutable/nvim/lua/plugins/editor/markdown-preview.lua index a047548..3ffa9fa 100644 --- a/.config/shared/nvim/lua/plugins/editor/markdown-preview.lua +++ b/mutable/nvim/lua/plugins/editor/markdown-preview.lua @@ -17,8 +17,6 @@ return { local function toggle() vim.cmd("MarkdownPreviewToggle") end - -- WezTerm から Ctrl+Shift+V を F24 として受け取ってトグル - vim.keymap.set({ "n", "i" }, "", toggle, { desc = "Markdown Preview (browser)" }) -- leader 経由のフォールバック vim.keymap.set("n", "mp", toggle, { desc = "Markdown Preview (browser)" }) end, diff --git a/.config/shared/nvim/lua/plugins/editor/mini-surround.lua b/mutable/nvim/lua/plugins/editor/mini-surround.lua similarity index 100% rename from .config/shared/nvim/lua/plugins/editor/mini-surround.lua rename to mutable/nvim/lua/plugins/editor/mini-surround.lua diff --git a/.config/shared/nvim/lua/plugins/editor/minty.lua b/mutable/nvim/lua/plugins/editor/minty.lua similarity index 100% rename from .config/shared/nvim/lua/plugins/editor/minty.lua rename to mutable/nvim/lua/plugins/editor/minty.lua diff --git a/.config/shared/nvim/lua/plugins/editor/rainbow-delimiters.lua b/mutable/nvim/lua/plugins/editor/rainbow-delimiters.lua similarity index 100% rename from .config/shared/nvim/lua/plugins/editor/rainbow-delimiters.lua rename to mutable/nvim/lua/plugins/editor/rainbow-delimiters.lua diff --git a/.config/shared/nvim/lua/plugins/editor/supermaven.lua b/mutable/nvim/lua/plugins/editor/supermaven.lua similarity index 100% rename from .config/shared/nvim/lua/plugins/editor/supermaven.lua rename to mutable/nvim/lua/plugins/editor/supermaven.lua diff --git a/.config/shared/nvim/lua/plugins/editor/test.lua b/mutable/nvim/lua/plugins/editor/test.lua similarity index 100% rename from .config/shared/nvim/lua/plugins/editor/test.lua rename to mutable/nvim/lua/plugins/editor/test.lua diff --git a/.config/shared/nvim/lua/plugins/editor/treesitter-context.lua b/mutable/nvim/lua/plugins/editor/treesitter-context.lua similarity index 100% rename from .config/shared/nvim/lua/plugins/editor/treesitter-context.lua rename to mutable/nvim/lua/plugins/editor/treesitter-context.lua diff --git a/.config/shared/nvim/lua/plugins/editor/treesitter.lua b/mutable/nvim/lua/plugins/editor/treesitter.lua similarity index 100% rename from .config/shared/nvim/lua/plugins/editor/treesitter.lua rename to mutable/nvim/lua/plugins/editor/treesitter.lua diff --git a/.config/shared/nvim/lua/plugins/img-clip.lua b/mutable/nvim/lua/plugins/img-clip.lua similarity index 100% rename from .config/shared/nvim/lua/plugins/img-clip.lua rename to mutable/nvim/lua/plugins/img-clip.lua diff --git a/.config/shared/nvim/lua/plugins/lsp/init.lua b/mutable/nvim/lua/plugins/lsp/init.lua similarity index 97% rename from .config/shared/nvim/lua/plugins/lsp/init.lua rename to mutable/nvim/lua/plugins/lsp/init.lua index 5b8bab2..784f3eb 100644 --- a/.config/shared/nvim/lua/plugins/lsp/init.lua +++ b/mutable/nvim/lua/plugins/lsp/init.lua @@ -1,5 +1,5 @@ return { - -- Disable markdownlint (use rumdl instead via CLI) + -- Markdownはlint対象外 { "mfussenegger/nvim-lint", opts = { diff --git a/.config/shared/nvim/lua/plugins/lsp/lazydev.lua b/mutable/nvim/lua/plugins/lsp/lazydev.lua similarity index 100% rename from .config/shared/nvim/lua/plugins/lsp/lazydev.lua rename to mutable/nvim/lua/plugins/lsp/lazydev.lua diff --git a/.config/shared/nvim/lua/plugins/lsp/version-lsp.lua b/mutable/nvim/lua/plugins/lsp/version-lsp.lua similarity index 100% rename from .config/shared/nvim/lua/plugins/lsp/version-lsp.lua rename to mutable/nvim/lua/plugins/lsp/version-lsp.lua diff --git a/.config/shared/nvim/lua/plugins/ui/bufferline.lua b/mutable/nvim/lua/plugins/ui/bufferline.lua similarity index 100% rename from .config/shared/nvim/lua/plugins/ui/bufferline.lua rename to mutable/nvim/lua/plugins/ui/bufferline.lua diff --git a/.config/shared/nvim/lua/plugins/ui/dracula.lua b/mutable/nvim/lua/plugins/ui/dracula.lua similarity index 100% rename from .config/shared/nvim/lua/plugins/ui/dracula.lua rename to mutable/nvim/lua/plugins/ui/dracula.lua diff --git a/.config/shared/nvim/lua/plugins/ui/hlchunk.lua b/mutable/nvim/lua/plugins/ui/hlchunk.lua similarity index 100% rename from .config/shared/nvim/lua/plugins/ui/hlchunk.lua rename to mutable/nvim/lua/plugins/ui/hlchunk.lua diff --git a/.config/shared/nvim/lua/plugins/ui/init.lua b/mutable/nvim/lua/plugins/ui/init.lua similarity index 100% rename from .config/shared/nvim/lua/plugins/ui/init.lua rename to mutable/nvim/lua/plugins/ui/init.lua diff --git a/.config/shared/nvim/lua/plugins/ui/lualine.lua b/mutable/nvim/lua/plugins/ui/lualine.lua similarity index 100% rename from .config/shared/nvim/lua/plugins/ui/lualine.lua rename to mutable/nvim/lua/plugins/ui/lualine.lua diff --git a/.config/shared/nvim/lua/plugins/ui/modicator.lua b/mutable/nvim/lua/plugins/ui/modicator.lua similarity index 100% rename from .config/shared/nvim/lua/plugins/ui/modicator.lua rename to mutable/nvim/lua/plugins/ui/modicator.lua diff --git a/.config/shared/nvim/lua/plugins/ui/noice.lua b/mutable/nvim/lua/plugins/ui/noice.lua similarity index 100% rename from .config/shared/nvim/lua/plugins/ui/noice.lua rename to mutable/nvim/lua/plugins/ui/noice.lua diff --git a/.config/shared/nvim/lua/plugins/ui/smear-cursor.lua b/mutable/nvim/lua/plugins/ui/smear-cursor.lua similarity index 100% rename from .config/shared/nvim/lua/plugins/ui/smear-cursor.lua rename to mutable/nvim/lua/plugins/ui/smear-cursor.lua diff --git a/.config/shared/nvim/stylua.toml b/mutable/nvim/stylua.toml similarity index 67% rename from .config/shared/nvim/stylua.toml rename to mutable/nvim/stylua.toml index 5d6c50d..0f90030 100644 --- a/.config/shared/nvim/stylua.toml +++ b/mutable/nvim/stylua.toml @@ -1,3 +1,3 @@ indent_type = "Spaces" indent_width = 2 -column_width = 120 \ No newline at end of file +column_width = 120 diff --git a/.config/shared/apm/.gitignore b/mutable/shared/apm/.gitignore similarity index 100% rename from .config/shared/apm/.gitignore rename to mutable/shared/apm/.gitignore diff --git a/.config/shared/apm/apm.lock.yaml b/mutable/shared/apm/apm.lock.yaml similarity index 99% rename from .config/shared/apm/apm.lock.yaml rename to mutable/shared/apm/apm.lock.yaml index 408003c..a28e2a1 100644 --- a/.config/shared/apm/apm.lock.yaml +++ b/mutable/shared/apm/apm.lock.yaml @@ -1,5 +1,5 @@ lockfile_version: '1' -generated_at: '2026-07-20T11:09:35.046865+00:00' +generated_at: '2026-07-24T19:05:23.536468+00:00' apm_version: 0.26.0 dependencies: - repo_url: _local/agent-llm @@ -21,11 +21,11 @@ dependencies: - .claude/skills/tool-pipeline/references/tui-guidelines.md deployed_file_hashes: .agents/skills/team/SKILL.md: sha256:c01f884842ffcaf9bb1b884dffd3a5539b9acd8bc57af1bdde27181cd2dc194d - .agents/skills/tool-pipeline/SKILL.md: sha256:ab70664420844f952a976e7782955dd1aac47c477fd79f03b999dae0be459a34 + .agents/skills/tool-pipeline/SKILL.md: sha256:85e6b2cfa85674ac38016c86abe399a0e6bc6a29c6d112f0a12ad269833b1481 .agents/skills/tool-pipeline/references/artifact-templates.md: sha256:b3f51f06107a751ca54690125b7eb285c6c8df18afc0317fb0f11d6fb57c44d3 .agents/skills/tool-pipeline/references/tui-guidelines.md: sha256:86c4d33b84af0b2a643d7e1b09cacc2065b3c590a6ac1484026ffeb0f9728b72 .claude/skills/team/SKILL.md: sha256:c01f884842ffcaf9bb1b884dffd3a5539b9acd8bc57af1bdde27181cd2dc194d - .claude/skills/tool-pipeline/SKILL.md: sha256:ab70664420844f952a976e7782955dd1aac47c477fd79f03b999dae0be459a34 + .claude/skills/tool-pipeline/SKILL.md: sha256:85e6b2cfa85674ac38016c86abe399a0e6bc6a29c6d112f0a12ad269833b1481 .claude/skills/tool-pipeline/references/artifact-templates.md: sha256:b3f51f06107a751ca54690125b7eb285c6c8df18afc0317fb0f11d6fb57c44d3 .claude/skills/tool-pipeline/references/tui-guidelines.md: sha256:86c4d33b84af0b2a643d7e1b09cacc2065b3c590a6ac1484026ffeb0f9728b72 source: local @@ -5161,7 +5161,7 @@ deployments: owners: - ./packages/agent-llm active_owner: ./packages/agent-llm - content_hash: sha256:ab70664420844f952a976e7782955dd1aac47c477fd79f03b999dae0be459a34 + content_hash: sha256:85e6b2cfa85674ac38016c86abe399a0e6bc6a29c6d112f0a12ad269833b1481 - kind: project-relative target: claude value: .claude/skills/tool-pipeline/references/artifact-templates.md @@ -8725,7 +8725,7 @@ deployments: owners: - ./packages/agent-llm active_owner: ./packages/agent-llm - content_hash: sha256:ab70664420844f952a976e7782955dd1aac47c477fd79f03b999dae0be459a34 + content_hash: sha256:85e6b2cfa85674ac38016c86abe399a0e6bc6a29c6d112f0a12ad269833b1481 - kind: project-relative target: codex value: .agents/skills/tool-pipeline/references/artifact-templates.md diff --git a/.config/shared/apm/apm.yml b/mutable/shared/apm/apm.yml similarity index 100% rename from .config/shared/apm/apm.yml rename to mutable/shared/apm/apm.yml diff --git a/.config/shared/apm/packages/agent-llm/.apm/skills/team/SKILL.md b/mutable/shared/apm/packages/agent-llm/.apm/skills/team/SKILL.md similarity index 100% rename from .config/shared/apm/packages/agent-llm/.apm/skills/team/SKILL.md rename to mutable/shared/apm/packages/agent-llm/.apm/skills/team/SKILL.md diff --git a/.config/shared/apm/packages/agent-llm/.apm/skills/tool-pipeline/SKILL.md b/mutable/shared/apm/packages/agent-llm/.apm/skills/tool-pipeline/SKILL.md similarity index 99% rename from .config/shared/apm/packages/agent-llm/.apm/skills/tool-pipeline/SKILL.md rename to mutable/shared/apm/packages/agent-llm/.apm/skills/tool-pipeline/SKILL.md index be373b2..c14abd6 100644 --- a/.config/shared/apm/packages/agent-llm/.apm/skills/tool-pipeline/SKILL.md +++ b/mutable/shared/apm/packages/agent-llm/.apm/skills/tool-pipeline/SKILL.md @@ -65,7 +65,7 @@ $SKILL_DIR/ ### サブエージェント配置 エージェント定義は `~/.claude/agents/` 配下に置く(Claude Code の subagent 探索パス)。 -このリポでは `.config/claude/agents/` に実体があり、`setup_windows.ps1` で `~/.claude/agents/` にリンクされる。 +このリポでは `chezmoi/private_dot_claude/agents/` をsource stateとして管理する。 | エージェント名 | 使用フェーズ | モデル | |---|---|---| diff --git a/.config/shared/apm/packages/agent-llm/.apm/skills/tool-pipeline/references/artifact-templates.md b/mutable/shared/apm/packages/agent-llm/.apm/skills/tool-pipeline/references/artifact-templates.md similarity index 100% rename from .config/shared/apm/packages/agent-llm/.apm/skills/tool-pipeline/references/artifact-templates.md rename to mutable/shared/apm/packages/agent-llm/.apm/skills/tool-pipeline/references/artifact-templates.md diff --git a/.config/shared/apm/packages/agent-llm/.apm/skills/tool-pipeline/references/tui-guidelines.md b/mutable/shared/apm/packages/agent-llm/.apm/skills/tool-pipeline/references/tui-guidelines.md similarity index 100% rename from .config/shared/apm/packages/agent-llm/.apm/skills/tool-pipeline/references/tui-guidelines.md rename to mutable/shared/apm/packages/agent-llm/.apm/skills/tool-pipeline/references/tui-guidelines.md diff --git a/.config/shared/apm/packages/agent-llm/apm.yml b/mutable/shared/apm/packages/agent-llm/apm.yml similarity index 100% rename from .config/shared/apm/packages/agent-llm/apm.yml rename to mutable/shared/apm/packages/agent-llm/apm.yml diff --git a/.config/shared/apm/packages/docs/.apm/skills/markdown-session-format/SKILL.md b/mutable/shared/apm/packages/docs/.apm/skills/markdown-session-format/SKILL.md similarity index 100% rename from .config/shared/apm/packages/docs/.apm/skills/markdown-session-format/SKILL.md rename to mutable/shared/apm/packages/docs/.apm/skills/markdown-session-format/SKILL.md diff --git a/.config/shared/apm/packages/docs/apm.yml b/mutable/shared/apm/packages/docs/apm.yml similarity index 100% rename from .config/shared/apm/packages/docs/apm.yml rename to mutable/shared/apm/packages/docs/apm.yml diff --git a/.config/shared/apm/packages/git-ops/.apm/skills/git-commit/SKILL.md b/mutable/shared/apm/packages/git-ops/.apm/skills/git-commit/SKILL.md similarity index 100% rename from .config/shared/apm/packages/git-ops/.apm/skills/git-commit/SKILL.md rename to mutable/shared/apm/packages/git-ops/.apm/skills/git-commit/SKILL.md diff --git a/.config/shared/apm/packages/git-ops/.apm/skills/github-thread-fetcher/SKILL.md b/mutable/shared/apm/packages/git-ops/.apm/skills/github-thread-fetcher/SKILL.md similarity index 100% rename from .config/shared/apm/packages/git-ops/.apm/skills/github-thread-fetcher/SKILL.md rename to mutable/shared/apm/packages/git-ops/.apm/skills/github-thread-fetcher/SKILL.md diff --git a/.config/shared/apm/packages/git-ops/.apm/skills/pr-summarizer/SKILL.md b/mutable/shared/apm/packages/git-ops/.apm/skills/pr-summarizer/SKILL.md similarity index 100% rename from .config/shared/apm/packages/git-ops/.apm/skills/pr-summarizer/SKILL.md rename to mutable/shared/apm/packages/git-ops/.apm/skills/pr-summarizer/SKILL.md diff --git a/.config/shared/apm/packages/git-ops/apm.yml b/mutable/shared/apm/packages/git-ops/apm.yml similarity index 100% rename from .config/shared/apm/packages/git-ops/apm.yml rename to mutable/shared/apm/packages/git-ops/apm.yml diff --git a/.gitconfig b/mutable/shared/gitconfig similarity index 96% rename from .gitconfig rename to mutable/shared/gitconfig index 8e82323..21110cc 100644 --- a/.gitconfig +++ b/mutable/shared/gitconfig @@ -37,7 +37,7 @@ email = tako.renraku1@gmail.com name = T4ko0522 [safe] - directory = %(prefix)///wsl.localhost/NixOS/home/takow/dotfiles + directory = %(prefix)///wsl.localhost/NixOS/home/t4ko/dotfiles [credential "https://github.com"] helper = helper = !gh auth git-credential diff --git a/.config/shared/lazygit/config.yml b/mutable/shared/lazygit/config.yml similarity index 100% rename from .config/shared/lazygit/config.yml rename to mutable/shared/lazygit/config.yml diff --git a/.config/shared/zed/keymap.json b/mutable/shared/zed/keymap.json similarity index 100% rename from .config/shared/zed/keymap.json rename to mutable/shared/zed/keymap.json diff --git a/.config/shared/zed/settings.json b/mutable/shared/zed/settings.json similarity index 100% rename from .config/shared/zed/settings.json rename to mutable/shared/zed/settings.json diff --git a/nix-configs/configuration-ci.nix b/nix-configs/configuration-ci.nix deleted file mode 100644 index 757aea0..0000000 --- a/nix-configs/configuration-ci.nix +++ /dev/null @@ -1,11 +0,0 @@ -{ - imports = [ - ./hosts/desktop/hardware-configuration.nix - ./modules - ]; - - networking.hostName = "nixos"; - - boot.loader.systemd-boot.enable = true; - boot.loader.efi.canTouchEfiVariables = true; -} diff --git a/nix-configs/modules/locale.nix b/nix-configs/feature/modules/core/locale.nix similarity index 100% rename from nix-configs/modules/locale.nix rename to nix-configs/feature/modules/core/locale.nix diff --git a/nix-configs/modules/nh.nix b/nix-configs/feature/modules/core/nh.nix similarity index 100% rename from nix-configs/modules/nh.nix rename to nix-configs/feature/modules/core/nh.nix diff --git a/nix-configs/feature/modules/core/nix-ld.nix b/nix-configs/feature/modules/core/nix-ld.nix new file mode 100644 index 0000000..1a9c769 --- /dev/null +++ b/nix-configs/feature/modules/core/nix-ld.nix @@ -0,0 +1,3 @@ +_: { + programs.nix-ld.enable = true; +} diff --git a/nix-configs/modules/nix.nix b/nix-configs/feature/modules/core/nix.nix similarity index 100% rename from nix-configs/modules/nix.nix rename to nix-configs/feature/modules/core/nix.nix diff --git a/nix-configs/modules/unfree.nix b/nix-configs/feature/modules/core/unfree.nix similarity index 100% rename from nix-configs/modules/unfree.nix rename to nix-configs/feature/modules/core/unfree.nix diff --git a/nix-configs/feature/modules/core/users.nix b/nix-configs/feature/modules/core/users.nix new file mode 100644 index 0000000..ae20f2f --- /dev/null +++ b/nix-configs/feature/modules/core/users.nix @@ -0,0 +1,20 @@ +{ + lib, + pkgs, + userExtraGroups, + username, + ... +}: { + users.users.${username} = { + isNormalUser = true; + description = "T4ko"; + extraGroups = userExtraGroups; + shell = pkgs.zsh; + }; + + users.groups = lib.optionalAttrs (lib.elem "plugdev" userExtraGroups) { + plugdev = {}; + }; + + programs.zsh.enable = true; +} diff --git a/nix-configs/feature/modules/desktop/audio.nix b/nix-configs/feature/modules/desktop/audio.nix new file mode 100644 index 0000000..f17e375 --- /dev/null +++ b/nix-configs/feature/modules/desktop/audio.nix @@ -0,0 +1,15 @@ +{ + services = { + xserver.enable = false; + printing.enable = true; + pulseaudio.enable = false; + pipewire = { + enable = true; + alsa.enable = true; + alsa.support32Bit = true; + pulse.enable = true; + }; + }; + + security.rtkit.enable = true; +} diff --git a/nix-configs/feature/modules/desktop/fonts.nix b/nix-configs/feature/modules/desktop/fonts.nix new file mode 100644 index 0000000..ac5fcdd --- /dev/null +++ b/nix-configs/feature/modules/desktop/fonts.nix @@ -0,0 +1,18 @@ +{pkgs, ...}: { + fonts.packages = with pkgs; [ + noto-fonts + noto-fonts-cjk-sans + noto-fonts-cjk-serif + noto-fonts-color-emoji + nerd-fonts.jetbrains-mono + nerd-fonts.symbols-only + plemoljp-nf + ]; + + fonts.fontconfig.defaultFonts = { + monospace = ["PlemolJP Console NF" "Noto Sans Mono CJK JP"]; + sansSerif = ["Noto Sans CJK JP" "Noto Sans"]; + serif = ["Noto Serif CJK JP" "Noto Serif"]; + emoji = ["Noto Color Emoji"]; + }; +} diff --git a/nix-configs/feature/modules/desktop/input-method.nix b/nix-configs/feature/modules/desktop/input-method.nix new file mode 100644 index 0000000..1f2b48d --- /dev/null +++ b/nix-configs/feature/modules/desktop/input-method.nix @@ -0,0 +1,41 @@ +{ + keyboardLayout, + pkgs, + ... +}: { + i18n.inputMethod = { + enable = true; + type = "fcitx5"; + fcitx5 = { + waylandFrontend = true; + addons = with pkgs; [ + fcitx5-mozc + fcitx5-gtk + fcitx5-material-color + qt6Packages.fcitx5-qt + ]; + settings.inputMethod = { + "Groups/0" = { + Name = "Default"; + "Default Layout" = keyboardLayout.fcitxLayout; + DefaultIM = "mozc"; + }; + "Groups/0/Items/0" = { + Name = "keyboard-jp"; + Layout = keyboardLayout.fcitxLayout; + }; + "Groups/0/Items/1" = { + Name = "mozc"; + Layout = keyboardLayout.fcitxLayout; + }; + GroupOrder."0" = "Default"; + }; + }; + }; + + environment.sessionVariables = { + GTK_IM_MODULE = "fcitx"; + QT_IM_MODULE = "fcitx"; + XMODIFIERS = "@im=fcitx"; + }; +} diff --git a/nix-configs/feature/modules/desktop/niri.nix b/nix-configs/feature/modules/desktop/niri.nix new file mode 100644 index 0000000..cbd195b --- /dev/null +++ b/nix-configs/feature/modules/desktop/niri.nix @@ -0,0 +1,11 @@ +{ + programs.niri.enable = true; + programs.dconf.enable = true; + security.polkit.enable = true; + hardware.graphics.enable = true; + + environment.sessionVariables = { + NIXOS_OZONE_WL = "1"; + MOZ_ENABLE_WAYLAND = "1"; + }; +} diff --git a/nix-configs/feature/modules/desktop/plymouth.nix b/nix-configs/feature/modules/desktop/plymouth.nix new file mode 100644 index 0000000..e9f3b56 --- /dev/null +++ b/nix-configs/feature/modules/desktop/plymouth.nix @@ -0,0 +1,28 @@ +{ + lib, + localPackages, + ... +}: let + themeName = "nixos-loading-default-logs"; +in { + boot = { + plymouth.nixos-loading = { + enable = true; + variant = "default"; + }; + plymouth = { + theme = lib.mkForce themeName; + themePackages = lib.mkForce [localPackages.plymouthTheme]; + }; + + consoleLogLevel = 7; + initrd.verbose = true; + + kernelParams = [ + "rd.udev.log_level=info" + "rd.systemd.show_status=true" + "udev.log_level=info" + "systemd.show_status=true" + ]; + }; +} diff --git a/nix-configs/feature/modules/desktop/portal.nix b/nix-configs/feature/modules/desktop/portal.nix new file mode 100644 index 0000000..41de31e --- /dev/null +++ b/nix-configs/feature/modules/desktop/portal.nix @@ -0,0 +1,7 @@ +{pkgs, ...}: { + xdg.portal = { + enable = true; + extraPortals = [pkgs.xdg-desktop-portal-gtk]; + configPackages = [pkgs.niri]; + }; +} diff --git a/nix-configs/profiles/regreet.nix b/nix-configs/feature/modules/desktop/regreet.nix similarity index 100% rename from nix-configs/profiles/regreet.nix rename to nix-configs/feature/modules/desktop/regreet.nix diff --git a/nix-configs/modules/kernel.nix b/nix-configs/feature/modules/hardware/kernel.nix similarity index 100% rename from nix-configs/modules/kernel.nix rename to nix-configs/feature/modules/hardware/kernel.nix diff --git a/nix-configs/modules/lanzaboote.nix b/nix-configs/feature/modules/hardware/lanzaboote.nix similarity index 100% rename from nix-configs/modules/lanzaboote.nix rename to nix-configs/feature/modules/hardware/lanzaboote.nix diff --git a/nix-configs/profiles/nvidia-hybrid.nix b/nix-configs/feature/modules/hardware/nvidia-hybrid.nix similarity index 100% rename from nix-configs/profiles/nvidia-hybrid.nix rename to nix-configs/feature/modules/hardware/nvidia-hybrid.nix diff --git a/nix-configs/profiles/nvidia.nix b/nix-configs/feature/modules/hardware/nvidia.nix similarity index 100% rename from nix-configs/profiles/nvidia.nix rename to nix-configs/feature/modules/hardware/nvidia.nix diff --git a/nix-configs/feature/modules/hardware/openrazer.nix b/nix-configs/feature/modules/hardware/openrazer.nix new file mode 100644 index 0000000..c876e58 --- /dev/null +++ b/nix-configs/feature/modules/hardware/openrazer.nix @@ -0,0 +1,11 @@ +{ + pkgs, + username, + ... +}: { + hardware.openrazer = { + enable = true; + users = [username]; + }; + environment.systemPackages = [pkgs.openrazer-daemon]; +} diff --git a/nix-configs/modules/qmk.nix b/nix-configs/feature/modules/hardware/qmk.nix similarity index 100% rename from nix-configs/modules/qmk.nix rename to nix-configs/feature/modules/hardware/qmk.nix diff --git a/nix-configs/modules/xkb.nix b/nix-configs/feature/modules/hardware/xkb.nix similarity index 100% rename from nix-configs/modules/xkb.nix rename to nix-configs/feature/modules/hardware/xkb.nix diff --git a/nix-configs/modules/bluetooth.nix b/nix-configs/feature/modules/services/bluetooth.nix similarity index 100% rename from nix-configs/modules/bluetooth.nix rename to nix-configs/feature/modules/services/bluetooth.nix diff --git a/nix-configs/modules/docker.nix b/nix-configs/feature/modules/services/docker.nix similarity index 54% rename from nix-configs/modules/docker.nix rename to nix-configs/feature/modules/services/docker.nix index 33ae340..48c8701 100644 --- a/nix-configs/modules/docker.nix +++ b/nix-configs/feature/modules/services/docker.nix @@ -1,8 +1,8 @@ -{ +{username, ...}: { virtualisation.docker = { enable = true; autoPrune.enable = true; }; - users.users."t4ko".extraGroups = ["docker"]; + users.users.${username}.extraGroups = ["docker"]; } diff --git a/nix-configs/feature/modules/services/networkmanager.nix b/nix-configs/feature/modules/services/networkmanager.nix new file mode 100644 index 0000000..0533ec2 --- /dev/null +++ b/nix-configs/feature/modules/services/networkmanager.nix @@ -0,0 +1,3 @@ +_: { + networking.networkmanager.enable = true; +} diff --git a/nix-configs/modules/tailscale.nix b/nix-configs/feature/modules/services/tailscale.nix similarity index 100% rename from nix-configs/modules/tailscale.nix rename to nix-configs/feature/modules/services/tailscale.nix diff --git a/nix-configs/feature/profiles/base.nix b/nix-configs/feature/profiles/base.nix new file mode 100644 index 0000000..50a687c --- /dev/null +++ b/nix-configs/feature/profiles/base.nix @@ -0,0 +1,10 @@ +{ + imports = [ + ../modules/core/locale.nix + ../modules/core/nh.nix + ../modules/core/nix.nix + ../modules/core/nix-ld.nix + ../modules/core/unfree.nix + ../modules/core/users.nix + ]; +} diff --git a/nix-configs/feature/profiles/gaming.nix b/nix-configs/feature/profiles/gaming.nix new file mode 100644 index 0000000..eb426f8 --- /dev/null +++ b/nix-configs/feature/profiles/gaming.nix @@ -0,0 +1,12 @@ +{pkgs, ...}: { + imports = [../modules/hardware/openrazer.nix]; + + programs.steam = { + enable = true; + extraCompatPackages = with pkgs; [proton-ge-bin]; + }; + + programs.gamemode.enable = true; + + hardware.graphics.enable32Bit = true; +} diff --git a/nix-configs/profiles/vr.nix b/nix-configs/feature/profiles/vr.nix similarity index 83% rename from nix-configs/profiles/vr.nix rename to nix-configs/feature/profiles/vr.nix index c6efe60..b683e11 100644 --- a/nix-configs/profiles/vr.nix +++ b/nix-configs/feature/profiles/vr.nix @@ -1,5 +1,6 @@ { config, + localPackages, pkgs, ... }: { @@ -19,20 +20,7 @@ # ドライバ lib を追加する (AT_SECURE でも絶対パスの RUNPATH は有効)。 services.wivrn = { enable = true; - package = - (pkgs.callPackage ../pkgs/wivrn/package.nix {cudaSupport = true;}).overrideAttrs - (old: { - postFixup = - (old.postFixup or "") - + '' - driverLib=${pkgs.addDriverRunpath.driverLink}/lib - for f in "$out"/bin/.wivrn-server-wrapped "$out"/lib/wivrn/*.so*; do - if [ -f "$f" ] && patchelf --print-rpath "$f" >/dev/null 2>&1; then - patchelf --add-rpath "$driverLib" "$f" - fi - done - ''; - }); + package = localPackages.wivrnNvenc; autoStart = true; openFirewall = true; # 無線ストリーミング用ポートを開放 highPriority = true; # 非同期リプロジェクション用の優先度を付与 diff --git a/nix-configs/feature/profiles/workstation.nix b/nix-configs/feature/profiles/workstation.nix new file mode 100644 index 0000000..add9650 --- /dev/null +++ b/nix-configs/feature/profiles/workstation.nix @@ -0,0 +1,18 @@ +{ + imports = [ + ./base.nix + ../modules/hardware/kernel.nix + ../modules/hardware/qmk.nix + ../modules/hardware/xkb.nix + ../modules/services/bluetooth.nix + ../modules/services/docker.nix + ../modules/services/networkmanager.nix + ../modules/services/tailscale.nix + ../modules/desktop/audio.nix + ../modules/desktop/fonts.nix + ../modules/desktop/input-method.nix + ../modules/desktop/niri.nix + ../modules/desktop/portal.nix + ../modules/desktop/regreet.nix + ]; +} diff --git a/nix-configs/feature/profiles/wsl.nix b/nix-configs/feature/profiles/wsl.nix new file mode 100644 index 0000000..5d6de34 --- /dev/null +++ b/nix-configs/feature/profiles/wsl.nix @@ -0,0 +1,9 @@ +{ + imports = [ + ../modules/core/nh.nix + ../modules/core/nix.nix + ../modules/core/nix-ld.nix + ../modules/core/unfree.nix + ../modules/core/users.nix + ]; +} diff --git a/nix-configs/home-ci.nix b/nix-configs/home-ci.nix deleted file mode 100644 index 8e88f47..0000000 --- a/nix-configs/home-ci.nix +++ /dev/null @@ -1,10 +0,0 @@ -{...}: { - imports = [ - ./home/identity.nix - ./home/packages/core.nix - ./home/packages/cli.nix - ./home/xdg.nix - ./home/zsh.nix - ./home/programs.nix - ]; -} diff --git a/nix-configs/home.nix b/nix-configs/home.nix deleted file mode 100644 index 982e2a4..0000000 --- a/nix-configs/home.nix +++ /dev/null @@ -1,22 +0,0 @@ -{...}: { - imports = [ - ./home/identity.nix - ./home/profiles/cursor.nix - ./home/packages.nix - ./home/xdg.nix - ./home/quick-shell.nix - ./home/niri.nix - ./home/lockscreen.nix - ./home/wallpaper.nix - ./home/swaync.nix - ./home/waybar.nix - ./home/razer.nix - ./home/vr.nix - ./home/zsh.nix - ./home/programs.nix - ./home/firefox.nix - ./home/vicinae.nix - ./home/spotify.nix - ./home/codex-desktop-linux.nix - ]; -} diff --git a/nix-configs/home/identity.nix b/nix-configs/home/identity.nix deleted file mode 100644 index 2f0b3c9..0000000 --- a/nix-configs/home/identity.nix +++ /dev/null @@ -1,12 +0,0 @@ -_: { - home = { - username = "t4ko"; - homeDirectory = "/home/t4ko"; - stateVersion = "26.05"; - - sessionVariables = { - EDITOR = "nvim"; - VISUAL = "nvim"; - }; - }; -} diff --git a/nix-configs/home/modules/agents/apm.nix b/nix-configs/home/modules/agents/apm.nix new file mode 100644 index 0000000..494f68b --- /dev/null +++ b/nix-configs/home/modules/agents/apm.nix @@ -0,0 +1,43 @@ +{ + config, + lib, + llm-agents, + pkgs, + ... +}: let + link = path: config.lib.file.mkOutOfStoreSymlink "${config.home.homeDirectory}/dotfiles/${path}"; +in { + home = { + file.".claude/skills".source = link "mutable/shared/apm/.claude/skills"; + + activation = { + apmInstallSkills = lib.hm.dag.entryAfter ["writeBoundary"] '' + cd "${config.home.homeDirectory}/dotfiles/mutable/shared/apm" + export GITHUB_TOKEN="$(${pkgs.gh}/bin/gh auth token 2>/dev/null || true)" + ${llm-agents.packages.${pkgs.stdenv.hostPlatform.system}.apm}/bin/apm install + ''; + + linkCodexSkills = lib.hm.dag.entryAfter ["apmInstallSkills"] '' + source_dir="${config.home.homeDirectory}/dotfiles/mutable/shared/apm/.agents/skills" + target_dir="${config.home.homeDirectory}/.codex/skills" + mkdir -p "$target_dir" + find "$target_dir" -maxdepth 1 -type l -lname "$source_dir/*" -delete + for skill in "$source_dir"/*; do + [ -d "$skill" ] || continue + ln -sfn "$skill" "$target_dir/$(basename "$skill")" + done + ''; + + linkOpencodeSkills = lib.hm.dag.entryAfter ["apmInstallSkills"] '' + source_dir="${config.home.homeDirectory}/dotfiles/mutable/shared/apm/.agents/skills" + target_dir="${config.home.homeDirectory}/.config/opencode/skills" + mkdir -p "$target_dir" + find "$target_dir" -maxdepth 1 -type l -lname "$source_dir/*" -delete + for skill in "$source_dir"/*; do + [ -d "$skill" ] || continue + ln -sfn "$skill" "$target_dir/$(basename "$skill")" + done + ''; + }; + }; +} diff --git a/nix-configs/home/codex-desktop-linux.nix b/nix-configs/home/modules/agents/codex-desktop.nix similarity index 86% rename from nix-configs/home/codex-desktop-linux.nix rename to nix-configs/home/modules/agents/codex-desktop.nix index e3659ac..f415abd 100644 --- a/nix-configs/home/codex-desktop-linux.nix +++ b/nix-configs/home/modules/agents/codex-desktop.nix @@ -9,6 +9,6 @@ # トップレベルの pkgs.codex は 0.133.0 と古く、タスク作成時にツール定義へ inputSchema を # 付与しないためバックエンドが "missing field `inputSchema`" で弾く。llm.nix で PATH に # llm-agents の codex と揃え、新しいコアを使わせる。 - cliPackage = llm-agents.packages.${pkgs.system}.codex; + cliPackage = llm-agents.packages.${pkgs.stdenv.hostPlatform.system}.codex; }; } diff --git a/nix-configs/home/modules/agents/codex.nix b/nix-configs/home/modules/agents/codex.nix new file mode 100644 index 0000000..1f975f7 --- /dev/null +++ b/nix-configs/home/modules/agents/codex.nix @@ -0,0 +1,58 @@ +{ + config, + lib, + pkgs, + ... +}: { + home = { + activation = { + seedCodexConfig = lib.hm.dag.entryAfter ["writeBoundary"] '' + codex_cfg="${config.home.homeDirectory}/.codex/config.toml" + codex_tmpl="${config.home.homeDirectory}/dotfiles/chezmoi/.chezmoitemplates/codex-config.toml" + mkdir -p "${config.home.homeDirectory}/.codex" + if [ -L "$codex_cfg" ] || [ ! -e "$codex_cfg" ]; then + rm -f "$codex_cfg" + cp "$codex_tmpl" "$codex_cfg" + chmod u+w "$codex_cfg" + fi + ''; + + migrateCodexSandboxState = lib.hm.dag.entryAfter ["seedCodexConfig"] '' + codex_dir="${config.home.homeDirectory}/.codex" + codex_cfg="$codex_dir/config.toml" + + if [ -f "$codex_cfg" ] \ + && ${pkgs.gnugrep}/bin/grep -q '^default_permissions = "personal"$' "$codex_cfg" \ + && ${pkgs.gnugrep}/bin/grep -q '^":root" = "write"$' "$codex_cfg"; then + ${pkgs.gnused}/bin/sed -i 's/^":root" = "write"$/":root" = "read"/' "$codex_cfg" + fi + + for state_file in "$codex_dir/.codex-global-state.json" "$codex_dir/.codex-global-state.json.bak"; do + [ -f "$state_file" ] || continue + if ${pkgs.jq}/bin/jq -e ' + any( + ((.["thread-writable-roots"] // {}) | to_entries[]?.value?); + type == "array" and any(.[]; . == "/") + ) + ' "$state_file" >/dev/null; then + state_tmp="$state_file.tmp.$$" + if ${pkgs.jq}/bin/jq ' + if type == "object" and (.["thread-writable-roots"] | type) == "object" then + .["thread-writable-roots"] |= with_entries( + .value |= if type == "array" then map(select(. != "/")) else . end + ) + else + . + end + ' "$state_file" > "$state_tmp"; then + ${pkgs.coreutils}/bin/chmod --reference="$state_file" "$state_tmp" + ${pkgs.coreutils}/bin/mv "$state_tmp" "$state_file" + else + ${pkgs.coreutils}/bin/rm -f "$state_tmp" + fi + fi + done + ''; + }; + }; +} diff --git a/nix-configs/home/firefox.nix b/nix-configs/home/modules/apps/firefox.nix similarity index 100% rename from nix-configs/home/firefox.nix rename to nix-configs/home/modules/apps/firefox.nix diff --git a/nix-configs/home/razer.nix b/nix-configs/home/modules/apps/razer.nix similarity index 100% rename from nix-configs/home/razer.nix rename to nix-configs/home/modules/apps/razer.nix diff --git a/nix-configs/home/spotify.nix b/nix-configs/home/modules/apps/spotify.nix similarity index 100% rename from nix-configs/home/spotify.nix rename to nix-configs/home/modules/apps/spotify.nix diff --git a/nix-configs/home/vicinae.nix b/nix-configs/home/modules/apps/vicinae.nix similarity index 95% rename from nix-configs/home/vicinae.nix rename to nix-configs/home/modules/apps/vicinae.nix index 7f07a24..86635b7 100644 --- a/nix-configs/home/vicinae.nix +++ b/nix-configs/home/modules/apps/vicinae.nix @@ -1,5 +1,5 @@ _: { - services.vicinae = { + programs.vicinae = { enable = true; systemd = { enable = true; diff --git a/nix-configs/home/vr.nix b/nix-configs/home/modules/apps/vr.nix similarity index 100% rename from nix-configs/home/vr.nix rename to nix-configs/home/modules/apps/vr.nix diff --git a/nix-configs/home/modules/core/identity.nix b/nix-configs/home/modules/core/identity.nix new file mode 100644 index 0000000..7189245 --- /dev/null +++ b/nix-configs/home/modules/core/identity.nix @@ -0,0 +1,16 @@ +{ + editor ? "nvim", + homeDirectory, + username, + ... +}: { + home = { + inherit homeDirectory username; + stateVersion = "26.05"; + + sessionVariables = { + EDITOR = editor; + VISUAL = editor; + }; + }; +} diff --git a/nix-configs/home/programs.nix b/nix-configs/home/modules/core/programs.nix similarity index 78% rename from nix-configs/home/programs.nix rename to nix-configs/home/modules/core/programs.nix index e068dd4..cd0f3d5 100644 --- a/nix-configs/home/programs.nix +++ b/nix-configs/home/modules/core/programs.nix @@ -1,12 +1,5 @@ {config, ...}: { programs = { - neovim = { - enable = true; - sideloadInitLua = true; - withPython3 = true; - extraPython3Packages = ps: [ps.pynvim]; - }; - go = { enable = true; env.GOPATH = "${config.home.homeDirectory}/go"; diff --git a/nix-configs/home/profiles/cursor.nix b/nix-configs/home/modules/desktop/appearance.nix similarity index 84% rename from nix-configs/home/profiles/cursor.nix rename to nix-configs/home/modules/desktop/appearance.nix index e64792c..223f33a 100644 --- a/nix-configs/home/profiles/cursor.nix +++ b/nix-configs/home/modules/desktop/appearance.nix @@ -1,8 +1,10 @@ -{pkgs, ...}: let - chiffonCursor = pkgs.callPackage ../../cursors/chiffon.nix {}; -in { +{ + localPackages, + pkgs, + ... +}: { home.pointerCursor = { - package = chiffonCursor; + package = localPackages.chiffonCursor; name = "Chiffon"; size = 24; gtk.enable = true; diff --git a/nix-configs/home/lockscreen.nix b/nix-configs/home/modules/desktop/lockscreen.nix similarity index 90% rename from nix-configs/home/lockscreen.nix rename to nix-configs/home/modules/desktop/lockscreen.nix index 23da929..f7f4081 100644 --- a/nix-configs/home/lockscreen.nix +++ b/nix-configs/home/modules/desktop/lockscreen.nix @@ -1,10 +1,11 @@ { config, lib, + localPackages, pkgs, ... }: let - c = import ../lib/catppuccin-mocha.nix; + c = import ../../../lib/theme.nix; niriCfg = config.t4ko.niri; wallpaperCfg = config.t4ko.wallpaper; restoreWallpaperCommand = @@ -38,20 +39,11 @@ -composite \ "$out" ''; - swaylock = pkgs.swaylock.overrideAttrs (old: { - postPatch = - (old.postPatch or "") - + '' - substituteInPlace password.c \ - --replace-fail "state->eventloop, 1500, set_input_idle, state" \ - "state->eventloop, 10000, set_input_idle, state" - ''; - }); lockscreen = pkgs.writeShellApplication { name = "lockscreen"; runtimeInputs = [ pkgs.niri - swaylock + localPackages.swaylockLongIdle ]; text = '' restore_monitors() { diff --git a/nix-configs/home/niri-keybind.nix b/nix-configs/home/modules/desktop/niri-keybind.nix similarity index 100% rename from nix-configs/home/niri-keybind.nix rename to nix-configs/home/modules/desktop/niri-keybind.nix diff --git a/nix-configs/home/niri.nix b/nix-configs/home/modules/desktop/niri.nix similarity index 99% rename from nix-configs/home/niri.nix rename to nix-configs/home/modules/desktop/niri.nix index cca1e48..721cbf8 100644 --- a/nix-configs/home/niri.nix +++ b/nix-configs/home/modules/desktop/niri.nix @@ -4,7 +4,7 @@ keyboardLayout, ... }: let - c = import ../lib/catppuccin-mocha.nix; + c = import ../../../lib/theme.nix; cfg = config.t4ko.niri; quickShell = config.t4ko.quickShell; lockscreenCommand = lib.getExe config.t4ko.lockscreen.command; diff --git a/nix-configs/home/quick-shell.nix b/nix-configs/home/modules/desktop/quick-shell.nix similarity index 97% rename from nix-configs/home/quick-shell.nix rename to nix-configs/home/modules/desktop/quick-shell.nix index 2309c3a..a86f4af 100644 --- a/nix-configs/home/quick-shell.nix +++ b/nix-configs/home/modules/desktop/quick-shell.nix @@ -5,8 +5,8 @@ }: let appId = "dev.t4ko.quickshell"; sessionName = "quick-shell"; - ghosttyConfig = ../../.config/nixos/ghostty-quick-shell.conf; - starshipConfig = ../../.config/nixos/starship-quick-shell.toml; + ghosttyConfig = ./quick-shell/files/ghostty.conf; + starshipConfig = ./quick-shell/files/starship.toml; quickShellSession = pkgs.writeShellApplication { name = "quick-shell-session"; diff --git a/.config/nixos/ghostty-quick-shell.conf b/nix-configs/home/modules/desktop/quick-shell/files/ghostty.conf similarity index 100% rename from .config/nixos/ghostty-quick-shell.conf rename to nix-configs/home/modules/desktop/quick-shell/files/ghostty.conf diff --git a/.config/nixos/starship-quick-shell.toml b/nix-configs/home/modules/desktop/quick-shell/files/starship.toml similarity index 100% rename from .config/nixos/starship-quick-shell.toml rename to nix-configs/home/modules/desktop/quick-shell/files/starship.toml diff --git a/nix-configs/home/swaync.nix b/nix-configs/home/modules/desktop/swaync.nix similarity index 93% rename from nix-configs/home/swaync.nix rename to nix-configs/home/modules/desktop/swaync.nix index e36cabb..b487d2f 100644 --- a/nix-configs/home/swaync.nix +++ b/nix-configs/home/modules/desktop/swaync.nix @@ -1,5 +1,5 @@ _: let - c = import ../lib/catppuccin-mocha.nix; + c = import ../../../lib/theme.nix; in { xdg.configFile."swaync/config.json".text = builtins.toJSON { positionX = "right"; @@ -51,5 +51,5 @@ in { @define-color yellow ${c.yellow}; @define-color red ${c.red}; '' - + builtins.readFile ../../.config/nixos/swaync/style.css; + + builtins.readFile ./swaync/files/style.css; } diff --git a/.config/nixos/swaync/style.css b/nix-configs/home/modules/desktop/swaync/files/style.css similarity index 100% rename from .config/nixos/swaync/style.css rename to nix-configs/home/modules/desktop/swaync/files/style.css diff --git a/nix-configs/home/wallpaper.nix b/nix-configs/home/modules/desktop/wallpaper.nix similarity index 99% rename from nix-configs/home/wallpaper.nix rename to nix-configs/home/modules/desktop/wallpaper.nix index fe1d4ea..761154e 100644 --- a/nix-configs/home/wallpaper.nix +++ b/nix-configs/home/modules/desktop/wallpaper.nix @@ -213,7 +213,7 @@ in { fallbackImage = lib.mkOption { type = lib.types.nullOr lib.types.path; - default = ../assets/wallpapers/nix.png; + default = ../../../assets/wallpapers/nix.png; description = '' Static wallpaper rendered by swaybg on every output. It is spawned before linux-wallpaperengine so that it stays visible whenever the engine fails to diff --git a/nix-configs/home/wallpaper/day.nix b/nix-configs/home/modules/desktop/wallpaper/day.nix similarity index 100% rename from nix-configs/home/wallpaper/day.nix rename to nix-configs/home/modules/desktop/wallpaper/day.nix diff --git a/nix-configs/home/wallpaper/evening.nix b/nix-configs/home/modules/desktop/wallpaper/evening.nix similarity index 100% rename from nix-configs/home/wallpaper/evening.nix rename to nix-configs/home/modules/desktop/wallpaper/evening.nix diff --git a/nix-configs/home/wallpaper/midnight.nix b/nix-configs/home/modules/desktop/wallpaper/midnight.nix similarity index 100% rename from nix-configs/home/wallpaper/midnight.nix rename to nix-configs/home/modules/desktop/wallpaper/midnight.nix diff --git a/nix-configs/home/wallpaper/morning.nix b/nix-configs/home/modules/desktop/wallpaper/morning.nix similarity index 100% rename from nix-configs/home/wallpaper/morning.nix rename to nix-configs/home/modules/desktop/wallpaper/morning.nix diff --git a/nix-configs/home/wallpaper/night.nix b/nix-configs/home/modules/desktop/wallpaper/night.nix similarity index 100% rename from nix-configs/home/wallpaper/night.nix rename to nix-configs/home/modules/desktop/wallpaper/night.nix diff --git a/nix-configs/home/waybar.nix b/nix-configs/home/modules/desktop/waybar.nix similarity index 99% rename from nix-configs/home/waybar.nix rename to nix-configs/home/modules/desktop/waybar.nix index 068b868..439723f 100644 --- a/nix-configs/home/waybar.nix +++ b/nix-configs/home/modules/desktop/waybar.nix @@ -1,5 +1,5 @@ {pkgs, ...}: let - c = import ../lib/catppuccin-mocha.nix; + c = import ../../../lib/theme.nix; powerMenu = pkgs.writeShellScriptBin "waybar-power-menu" '' if ${pkgs.procps}/bin/pgrep -u "$USER" -x nwg-bar >/dev/null; then ${pkgs.procps}/bin/pkill -u "$USER" -x nwg-bar @@ -475,7 +475,7 @@ in { @define-color peach ${c.peach}; @define-color red ${c.red}; '' - + builtins.readFile ../../.config/nixos/waybar/style.css; + + builtins.readFile ./waybar/files/style.css; }; systemd.user.services.waybar.Service.ExecStartPre = "${pkgs.runtimeShell} -c '${pkgs.procps}/bin/pkill -u %u -f \"(^|/)waybar($|[[:space:]])\" || true'"; diff --git a/.config/nixos/waybar/style.css b/nix-configs/home/modules/desktop/waybar/files/style.css similarity index 100% rename from .config/nixos/waybar/style.css rename to nix-configs/home/modules/desktop/waybar/files/style.css diff --git a/nix-configs/home/modules/editors/nixvim/autocmds.nix b/nix-configs/home/modules/editors/nixvim/autocmds.nix new file mode 100644 index 0000000..9c8c14b --- /dev/null +++ b/nix-configs/home/modules/editors/nixvim/autocmds.nix @@ -0,0 +1,54 @@ +{ + extraConfigLuaPost = '' + vim.api.nvim_create_autocmd("TextYankPost", { + group = vim.api.nvim_create_augroup("yank_to_clipboard", { clear = true }), + callback = function() + if vim.v.event.operator == "y" then vim.fn.setreg("+", vim.fn.getreg('"')) end + end, + }) + + vim.api.nvim_create_autocmd("QuitPre", { + callback = function() + local current = vim.api.nvim_get_current_win() + for _, window in ipairs(vim.api.nvim_list_wins()) do + if window ~= current and vim.bo[vim.api.nvim_win_get_buf(window)].buftype == "" then return end + end + vim.cmd.only({ bang = true }) + end, + }) + + vim.api.nvim_create_user_command("InsertDatetime", function() + local row, column = unpack(vim.api.nvim_win_get_cursor(0)) + vim.api.nvim_buf_set_text(0, row - 1, column, row - 1, column, { vim.fn.strftime("%Y-%m-%d %H:%M:%S") }) + end, {}) + + vim.api.nvim_create_user_command("CountCleanTextLength", function() + local lines = vim.api.nvim_buf_get_lines(0, 0, -1, false) + local text = table.concat(lines, "\n") + text = text:gsub("```.-```", ""):gsub("`.-`", ""):gsub("%[%^%d+%]", "") + text = text:gsub("\n%[%^%d+%]:[^\n]*", ""):gsub("]+>", "") + text = text:gsub("%[([^%]]-)%]%([^%)]+%)", "%1") + text = text:gsub("#+", ""):gsub("%*%*", ""):gsub("%*", ""):gsub("_", ""):gsub("[%[%]%(%)]", ""):gsub("-", "") + print("ファイル全体の文字数(記法除去後): " .. #text:gsub("%s+", "")) + end, {}) + + vim.api.nvim_create_user_command("CoAuthoredBy", function(command) + if command.args == "" then + vim.notify("Usage: :CoAuthoredBy ", vim.log.levels.ERROR) + return + end + vim.system({ + "gh", "api", "/users/" .. command.args, "-q", + "\"Co-Authored-By: \\(.name) <\\(.id)+\\(.login)@users.noreply.github.com>\"", + }, { text = true, timeout = 10000 }, function(result) + vim.schedule(function() + if result.code ~= 0 then + vim.notify("Failed to get GitHub user: " .. (result.stderr or ""), vim.log.levels.ERROR) + return + end + vim.api.nvim_put({ result.stdout:gsub("\n$", "") }, "l", true, true) + end) + end) + end, { nargs = 1, desc = "Insert a Co-Authored-By trailer" }) + ''; +} diff --git a/nix-configs/home/modules/editors/nixvim/default.nix b/nix-configs/home/modules/editors/nixvim/default.nix new file mode 100644 index 0000000..9b1ac7e --- /dev/null +++ b/nix-configs/home/modules/editors/nixvim/default.nix @@ -0,0 +1,37 @@ +{ + localPackages, + pkgs, + ... +}: { + programs.nixvim = { + enable = true; + defaultEditor = true; + viAlias = true; + vimAlias = true; + withPython3 = true; + extraPython3Packages = ps: [ps.pynvim]; + + # Nixvim は独自の nixpkgs を評価するため、既存の NixOS 許可を明示的に継承する。 + nixpkgs.config.allowUnfree = true; + + # Nixvim に閉じた外部依存。Home Manager の PATH に依存しない。 + extraPackages = with pkgs; [ + fd + fzf + gh + git + lazygit + nodejs + ripgrep + yazi + ]; + + imports = [ + ./options.nix + ./keymaps.nix + ./autocmds.nix + ./lsp.nix + (import ./plugins {inherit localPackages;}) + ]; + }; +} diff --git a/.config/shared/nvim/ftdetect/mdc.lua b/nix-configs/home/modules/editors/nixvim/files/ftdetect/mdc.lua similarity index 100% rename from .config/shared/nvim/ftdetect/mdc.lua rename to nix-configs/home/modules/editors/nixvim/files/ftdetect/mdc.lua diff --git a/.config/shared/nvim/ftdetect/zsh.lua b/nix-configs/home/modules/editors/nixvim/files/ftdetect/zsh.lua similarity index 100% rename from .config/shared/nvim/ftdetect/zsh.lua rename to nix-configs/home/modules/editors/nixvim/files/ftdetect/zsh.lua diff --git a/.config/shared/nvim/spell/tech.utf-8.add b/nix-configs/home/modules/editors/nixvim/files/spell/tech.utf-8.add similarity index 99% rename from .config/shared/nvim/spell/tech.utf-8.add rename to nix-configs/home/modules/editors/nixvim/files/spell/tech.utf-8.add index 5a792a1..1b97221 100644 --- a/.config/shared/nvim/spell/tech.utf-8.add +++ b/nix-configs/home/modules/editors/nixvim/files/spell/tech.utf-8.add @@ -14852,8 +14852,6 @@ markdown-pdf markdown-table markdown-to-jsx markdown-toc -markdownlint -markdownlint-cli marked marker MARKER diff --git a/nix-configs/home/modules/editors/nixvim/keymaps.nix b/nix-configs/home/modules/editors/nixvim/keymaps.nix new file mode 100644 index 0000000..f249768 --- /dev/null +++ b/nix-configs/home/modules/editors/nixvim/keymaps.nix @@ -0,0 +1,102 @@ +{ + extraConfigLuaPost = '' + local map = vim.keymap.set + local silent = { noremap = true, silent = true } + + map({ "n", "x", "o" }, ";,", ",", { desc = "Repeat f/F/t/T in reverse" }) + map({ "n", "v" }, "p", '"+p', silent) + map({ "n", "v" }, "P", '"+P', silent) + map("i", "", "", silent) + map("i", "", "", silent) + map("n", "", "", silent) + map("i", "", "", silent) + + map("n", "+", "", silent) + map("n", "-", "", silent) + map("n", "", ":tabnext", silent) + map("n", "", ":tabprevious", silent) + map("n", "ss", ":split", silent) + map("n", "sv", ":vsplit", silent) + map("n", "sh", "h", silent) + map("n", "sk", "k", silent) + map("n", "sj", "j", silent) + map("n", "sl", "l", silent) + map("n", "", "<", silent) + map("n", "", ">", silent) + map("n", "", "+", silent) + map("n", "", "-", silent) + map("n", "", vim.diagnostic.goto_next, { noremap = true, silent = true, desc = "Next diagnostic" }) + + map({ "n", "x" }, "", "10h", { desc = "Move 10 chars left" }) + map({ "n", "x" }, "", "10j", { desc = "Move 10 lines down" }) + map({ "n", "x" }, "", "10k", { desc = "Move 10 lines up" }) + map({ "n", "x" }, "", "10l", { desc = "Move 10 chars right" }) + + local function git_root() + local buffer_name = vim.api.nvim_buf_get_name(0) + local buffer_dir = buffer_name == "" and vim.fn.getcwd() or vim.fn.fnamemodify(buffer_name, ":h") + local result = vim.system({ "git", "-C", buffer_dir, "rev-parse", "--show-toplevel" }, { text = true, timeout = 3000 }):wait() + return result.code == 0 and vim.trim(result.stdout) or vim.fn.getcwd() + end + + map("n", "", function() Snacks.terminal() end, { desc = "Terminal" }) + map("n", "", function() Snacks.terminal(nil, { cwd = git_root() }) end, { desc = "Terminal (project root)" }) + map("n", "nn", function() Snacks.notifier.show_history() end, { desc = "Notification history" }) + map("n", "gg", function() Snacks.lazygit({ cwd = vim.fn.getcwd() }) end, { desc = "LazyGit (cwd)" }) + map("n", "gG", function() Snacks.lazygit({ cwd = git_root() }) end, { desc = "LazyGit (project root)" }) + map("n", "", function() Snacks.picker.files({ cwd = git_root(), hidden = git_root():match("dotfiles$") ~= nil }) end, { desc = "Find files" }) + map("n", "/", function() Snacks.picker.grep({ cwd = git_root(), hidden = git_root():match("dotfiles$") ~= nil }) end, { desc = "Grep" }) + map("n", "p", function() Snacks.picker.pickers() end, { desc = "Pickers" }) + map("n", "y", "Yazi", { desc = "Open Yazi" }) + map("n", "P", "PasteImage", { desc = "Paste image" }) + map({ "n", "i" }, "", "MarkdownPreviewToggle", { desc = "Markdown preview" }) + map("n", "gd", "DiffviewOpen", { desc = "Open diff view" }) + map("n", "gD", "DiffviewClose", { desc = "Close diff view" }) + map("n", "gl", "DiffviewFileHistory", { desc = "Git history" }) + map("n", "gL", "DiffviewFileHistory %", { desc = "File history" }) + map("n", "uC", function() require("treesitter-context").toggle() end, { desc = "Toggle Treesitter context" }) + map("n", "[c", function() require("treesitter-context").go_to_context(vim.v.count1) end, { desc = "Jump to upper context" }) + map("n", "zR", function() require("ufo").openAllFolds() end, { desc = "Open all folds" }) + map("n", "zM", function() require("ufo").closeAllFolds() end, { desc = "Close all folds" }) + map("n", "K", function() + if not require("ufo").peekFoldedLinesUnderCursor() then vim.lsp.buf.hover() end + end, { desc = "Peek fold or hover" }) + map({ "n", "v" }, "wr", "WinResizerStartResize", { desc = "Resize window" }) + map({ "n", "v" }, "r", "WinResizerStartResize", { desc = "Resize window" }) + + map("n", "gh", function() + local target = vim.fn.expand("") + if target:match("^https?://") then vim.ui.open(target) else vim.cmd("normal! gF!") end + end, { desc = "Open link or file" }) + map("n", "gx", function() + local word = vim.fn.expand("") + local arn = word:match("[\"`']?(arn:aws[a-z%-]*:[^\"`'%s]+)[\"`']?") + vim.ui.open(arn and "https://console.aws.amazon.com/go/view?arn=" .. arn or vim.fn.expand("")) + end, { desc = "Open URL or AWS ARN" }) + map("n", "gR", function() + local repository = vim.fn.expand("") + if repository:match(".+/[^/]+") then vim.ui.open("https://github.com/" .. repository) else vim.cmd("normal! gF!") end + end, { desc = "Open GitHub repository" }) + map("n", "#", function() + vim.api.nvim_feedkeys(":%s/" .. vim.fn.expand("") .. "//g", "n", false) + vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes("", true, true, true), "n", false) + vim.opt.hlsearch = true + end, { desc = "Substitute word under cursor" }) + + local scroll_cycle = { position = 0, at = 0 } + map("n", "zz", function() + scroll_cycle.position, scroll_cycle.at = 1, vim.uv.now() + vim.cmd("normal! zz") + end, { desc = "Scroll center" }) + map("n", "z", function() + if scroll_cycle.position > 0 and vim.uv.now() - scroll_cycle.at < 1000 then + scroll_cycle.at = vim.uv.now() + scroll_cycle.position = scroll_cycle.position % 3 + 1 + vim.cmd("normal! " .. ({ "zz", "zt", "zb" })[scroll_cycle.position]) + else + scroll_cycle.position = 0 + vim.cmd("normal! z" .. vim.fn.getcharstr()) + end + end, { desc = "Cycle scroll position" }) + ''; +} diff --git a/nix-configs/home/modules/editors/nixvim/lsp.nix b/nix-configs/home/modules/editors/nixvim/lsp.nix new file mode 100644 index 0000000..cf00b73 --- /dev/null +++ b/nix-configs/home/modules/editors/nixvim/lsp.nix @@ -0,0 +1,70 @@ +{ + lsp = { + inlayHints.enable = true; + servers = { + biome.enable = true; + cssls.enable = true; + docker_compose_language_service.enable = true; + dockerls.enable = true; + eslint.enable = true; + gopls.enable = true; + jsonls.enable = true; + marksman.enable = true; + nil_ls.enable = true; + pyright.enable = true; + ruff.enable = true; + tailwindcss.enable = true; + taplo.enable = true; + vtsls.enable = true; + }; + }; + + plugins = { + blink-cmp = { + enable = true; + setupLspCapabilities = true; + settings = { + completion = { + documentation.window.border = "rounded"; + menu.border = "rounded"; + }; + keymap.preset = "default"; + sources = { + cmdline = []; + providers.lazydev = { + module = "lazydev.integrations.blink"; + name = "LazyDev"; + score_offset = 100; + }; + per_filetype.lua = ["lsp" "path" "snippets" "buffer" "lazydev"]; + }; + }; + }; + + lazydev = { + enable = true; + settings.library = [ + { + path = "\${3rd}/luv/library"; + words = ["vim%.uv"]; + } + { + path = "snacks.nvim"; + words = ["Snacks"]; + } + ]; + }; + + lsp.enable = true; + }; + + extraConfigLuaPost = '' + vim.diagnostic.config({ + virtual_text = { + format = function(diagnostic) + return string.format("%s (%s)", diagnostic.message, diagnostic.source or "Unknown") + end, + }, + }) + ''; +} diff --git a/nix-configs/home/modules/editors/nixvim/options.nix b/nix-configs/home/modules/editors/nixvim/options.nix new file mode 100644 index 0000000..1c551d8 --- /dev/null +++ b/nix-configs/home/modules/editors/nixvim/options.nix @@ -0,0 +1,77 @@ +{ + globals = { + mapleader = ","; + maplocalleader = "\\"; + ai_cmp = false; + loaded_ruby_provider = 0; + loaded_perl_provider = 0; + loaded_node_provider = 0; + + terminal_color_0 = "#45475a"; + terminal_color_1 = "#f38ba8"; + terminal_color_2 = "#a6e3a1"; + terminal_color_3 = "#f9e2af"; + terminal_color_4 = "#89b4fa"; + terminal_color_5 = "#f5c2e7"; + terminal_color_6 = "#94e2d5"; + terminal_color_7 = "#bac2de"; + terminal_color_8 = "#585b70"; + terminal_color_9 = "#f38ba8"; + terminal_color_10 = "#a6e3a1"; + terminal_color_11 = "#f9e2af"; + terminal_color_12 = "#89b4fa"; + terminal_color_13 = "#f5c2e7"; + terminal_color_14 = "#94e2d5"; + terminal_color_15 = "#a6adc8"; + }; + + opts = { + clipboard = ""; + helplang = ["ja"]; + pumblend = 10; + spelllang = ["en" "cjk"]; + splitbelow = true; + splitright = true; + termguicolors = true; + whichwrap = "b,s,h,l,<,>,[,],~"; + winblend = 20; + }; + + extraConfigLuaPost = '' + vim.api.nvim_set_hl(0, "ActiveWindowSeparator", { fg = "#69F5CD" }) + vim.api.nvim_set_hl(0, "InactiveWindowSeparator", { fg = "#555555" }) + vim.api.nvim_set_hl(0, "SpellCap", {}) + + vim.api.nvim_create_autocmd("ColorScheme", { + callback = function() + vim.api.nvim_set_hl(0, "SpellCap", {}) + end, + }) + + vim.api.nvim_create_autocmd("CmdlineEnter", { + callback = function() + vim.opt.winblend = 0 + end, + }) + + vim.api.nvim_create_autocmd("CmdlineLeave", { + callback = function() + vim.opt.winblend = 20 + end, + }) + + vim.api.nvim_create_autocmd({ "WinEnter", "BufWinEnter" }, { + callback = function() + vim.wo.winhighlight = "WinSeparator:ActiveWindowSeparator" + end, + }) + + vim.api.nvim_create_autocmd("WinLeave", { + callback = function() + vim.wo.winhighlight = "" + end, + }) + + vim.cmd("cabbrev H belowright vertical help") + ''; +} diff --git a/nix-configs/home/modules/editors/nixvim/plugins/ai.nix b/nix-configs/home/modules/editors/nixvim/plugins/ai.nix new file mode 100644 index 0000000..2e0a88b --- /dev/null +++ b/nix-configs/home/modules/editors/nixvim/plugins/ai.nix @@ -0,0 +1,12 @@ +{ + plugins.claudecode = { + enable = true; + settings = { + diff_opts = { + layout = "vertical"; + open_in_new_tab = true; + }; + terminal.provider = "snacks"; + }; + }; +} diff --git a/nix-configs/home/modules/editors/nixvim/plugins/default.nix b/nix-configs/home/modules/editors/nixvim/plugins/default.nix new file mode 100644 index 0000000..3eb5249 --- /dev/null +++ b/nix-configs/home/modules/editors/nixvim/plugins/default.nix @@ -0,0 +1,20 @@ +{localPackages}: {pkgs, ...}: { + imports = [ + ./ai.nix + ./editor.nix + ./git.nix + ./languages.nix + ./navigation.nix + ./ui.nix + ]; + + extraPlugins = with pkgs.vimPlugins; [ + bracey-vim + dracula-nvim + incline-nvim + nvim-ufo + promise-async + localPackages.vimdocJa + localPackages.winresizer + ]; +} diff --git a/nix-configs/home/modules/editors/nixvim/plugins/editor.nix b/nix-configs/home/modules/editors/nixvim/plugins/editor.nix new file mode 100644 index 0000000..c86242d --- /dev/null +++ b/nix-configs/home/modules/editors/nixvim/plugins/editor.nix @@ -0,0 +1,75 @@ +{lib, ...}: { + plugins = { + compiler.enable = true; + grug-far.enable = true; + img-clip = { + enable = true; + settings.default = { + dir_path = "assets"; + extension = "png"; + prompt_for_file_name = true; + relative_to_current_file = true; + show_dir_path_in_prompt = false; + use_absolute_path = false; + }; + }; + inc-rename.enable = true; + mini = { + enable = true; + modules = { + ai = {}; + hipatterns = {}; + pairs = {}; + surround = { + mappings = { + add = "gsa"; + delete = "gsd"; + find = "gsf"; + find_left = "gsF"; + highlight = "gsh"; + replace = "gsr"; + update_n_lines = "gsn"; + }; + }; + }; + }; + persistence.enable = true; + rainbow-delimiters.enable = true; + todo-comments.enable = true; + }; + + extraConfigLuaPost = lib.mkOrder 1120 '' + vim.o.cursorline = true + vim.o.number = true + vim.o.foldcolumn = "1" + vim.o.foldlevel = 99 + vim.o.foldlevelstart = 99 + vim.o.foldenable = true + require("ufo").setup({ + fold_virt_text_handler = function(virtual_text, start_line, end_line, width, truncate) + local suffix = (" 󰁂 %d "):format(end_line - start_line) + local target_width, current_width = width - vim.fn.strdisplaywidth(suffix), 0 + local result = {} + for _, chunk in ipairs(virtual_text) do + local text, highlight = chunk[1], chunk[2] + local text_width = vim.fn.strdisplaywidth(text) + if target_width > current_width + text_width then + table.insert(result, chunk) + else + text = truncate(text, target_width - current_width) + table.insert(result, { text, highlight }) + suffix = suffix .. string.rep(" ", math.max(0, target_width - current_width - vim.fn.strdisplaywidth(text))) + break + end + current_width = current_width + text_width + end + table.insert(result, { suffix, "MoreMsg" }) + return result + end, + provider_selector = function(buffer, filetype) + if filetype == "markdown" then return markdown_fold_provider end + return { "treesitter", "indent" } + end, + }) + ''; +} diff --git a/nix-configs/home/modules/editors/nixvim/plugins/git.nix b/nix-configs/home/modules/editors/nixvim/plugins/git.nix new file mode 100644 index 0000000..ee1ec9c --- /dev/null +++ b/nix-configs/home/modules/editors/nixvim/plugins/git.nix @@ -0,0 +1,6 @@ +{ + plugins = { + diffview.enable = true; + gitsigns.enable = true; + }; +} diff --git a/nix-configs/home/modules/editors/nixvim/plugins/languages.nix b/nix-configs/home/modules/editors/nixvim/plugins/languages.nix new file mode 100644 index 0000000..76014bd --- /dev/null +++ b/nix-configs/home/modules/editors/nixvim/plugins/languages.nix @@ -0,0 +1,149 @@ +{ + config, + lib, + pkgs, + ... +}: { + extraPackages = with pkgs; [ + gofumpt + gotools + nixfmt + prettier + statix + stylua + ]; + + extraFiles = { + "ftdetect/mdc.lua".source = ../files/ftdetect/mdc.lua; + "ftdetect/zsh.lua".source = ../files/ftdetect/zsh.lua; + "spell/tech.utf-8.add".source = ../files/spell/tech.utf-8.add; + }; + + plugins = { + emmet.enable = true; + markdown-preview = { + enable = true; + settings = { + auto_close = 0; + browser = ""; + combine_preview = 0; + combine_preview_auto_refresh = 1; + filetypes = ["markdown"]; + open_to_the_world = 0; + theme = "dark"; + }; + }; + render-markdown.enable = true; + rustaceanvim.enable = true; + treesitter = { + enable = true; + grammarPackages = with config.plugins.treesitter.package.builtGrammars; [ + bash + c + css + dockerfile + go + html + javascript + json + lua + markdown + markdown_inline + nix + python + rust + scss + toml + tsx + typescript + vim + vimdoc + yaml + zsh + ]; + highlight.enable = true; + indent.enable = true; + }; + treesitter-context = { + enable = true; + settings = { + max_lines = 3; + min_window_height = 20; + mode = "cursor"; + multiline_threshold = 1; + trim_scope = "outer"; + }; + }; + ts-autotag.enable = true; + ts-comments.enable = true; + venv-selector.enable = true; + }; + + extraConfigLuaPost = lib.mkMerge [ + (lib.mkOrder 1100 '' + local function markdown_fold_provider(buffer) + local lines, folds, blocks, headings = vim.api.nvim_buf_get_lines(buffer, 0, -1, false), {}, {}, {} + local in_code, code_start = false, nil + local function trim_empty(last) + while last > 0 and lines[last + 1] and lines[last + 1]:match("^%s*$") do last = last - 1 end + return last + end + local function close_headings(level, last) + while #headings > 0 and headings[#headings].level >= level do + local heading = table.remove(headings) + local finish = trim_empty(last - 1) + if finish > heading.line then table.insert(folds, { startLine = heading.line, endLine = finish }) end + end + end + for index, line in ipairs(lines) do + local line_number = index - 1 + if line:match("^```") or line:match("^~~~") then + if in_code then + in_code = false + if line_number > code_start then table.insert(folds, { startLine = code_start, endLine = line_number }) end + else + in_code, code_start = true, line_number + end + end + if not in_code then + if line:match("^:::details") or line:match("^:::message") then + table.insert(blocks, line_number) + elseif line:match("^:::$") and #blocks > 0 then + table.insert(folds, { startLine = table.remove(blocks), endLine = line_number }) + end + local hashes = line:match("^(#+)%s") + if hashes then + close_headings(#hashes, line_number) + table.insert(headings, { line = line_number, level = #hashes }) + end + end + end + local last = trim_empty(#lines - 1) + for _, heading in ipairs(headings) do + if last > heading.line then table.insert(folds, { startLine = heading.line, endLine = last }) end + end + return folds + end + '') + (lib.mkOrder 1140 '' + vim.g.bracey_auto_start_browser = 1 + vim.g.bracey_refresh_on_save = 1 + vim.g.bracey_server_allow_remote_connections = 0 + vim.g.user_emmet_leader_key = "" + vim.g.user_emmet_settings = { + variables = { lang = "ja" }, + html = { + indentation = " ", + snippets = { + ["html:5"] = "\n\n\n\t\n\t\n\t\n\t\n\n\n\t''${child}|\n\n", + }, + }, + } + + local spellfiles = vim.fn.globpath(vim.o.runtimepath, "spell/tech.utf-8.add", false, true) + if #spellfiles > 0 then + vim.opt.spellfile = { spellfiles[1], vim.fn.stdpath("data") .. "/spell/local.utf-8.add" } + end + '') + ]; +} diff --git a/nix-configs/home/modules/editors/nixvim/plugins/navigation.nix b/nix-configs/home/modules/editors/nixvim/plugins/navigation.nix new file mode 100644 index 0000000..c065dd0 --- /dev/null +++ b/nix-configs/home/modules/editors/nixvim/plugins/navigation.nix @@ -0,0 +1,29 @@ +{ + plugins = { + flash.enable = true; + snacks = { + enable = true; + settings = { + image = { + doc = { + enabled = true; + inline = true; + max_height = 40; + max_width = 80; + }; + enabled = true; + }; + scroll.enabled = false; + }; + }; + trouble.enable = true; + which-key.enable = true; + yazi = { + enable = true; + settings = { + keymaps.show_help = ""; + open_for_directories = false; + }; + }; + }; +} diff --git a/nix-configs/home/modules/editors/nixvim/plugins/ui.nix b/nix-configs/home/modules/editors/nixvim/plugins/ui.nix new file mode 100644 index 0000000..ce90496 --- /dev/null +++ b/nix-configs/home/modules/editors/nixvim/plugins/ui.nix @@ -0,0 +1,118 @@ +{lib, ...}: { + plugins = { + bufferline.enable = true; + hlchunk = { + enable = true; + settings.chunk = { + chars = { + horizontal_line = "─"; + left_bottom = "╰"; + left_top = "╭"; + right_arrow = ">"; + vertical_line = "│"; + }; + enable = true; + style = "#806d9c"; + }; + }; + lualine = { + enable = true; + settings.options.theme = "dracula-nvim"; + }; + modicator = { + enable = true; + settings = { + highlights.defaults.bold = true; + integration.lualine.enabled = false; + show_warnings = false; + }; + }; + noice = { + enable = true; + settings = { + lsp = { + hover = { + enabled = true; + silent = true; + }; + signature.enabled = true; + }; + presets = { + bottom_search = true; + command_palette = true; + inc_rename = true; + long_message_to_split = true; + lsp_doc_border = true; + }; + routes = [ + { + filter = { + event = "msg_show"; + find = "written"; + kind = ""; + }; + opts.skip = true; + } + { + filter = { + event = "msg_show"; + kind = "search_count"; + }; + opts.skip = true; + } + ]; + }; + }; + notify = { + enable = true; + settings = { + background_colour = "#1e1e2e"; + render = "compact"; + stages = "fade"; + timeout = 3000; + }; + }; + smear-cursor = { + enable = true; + settings = { + distance_stop_animating = 0.5; + hide_target_hack = false; + stiffness = 0.8; + trailing_exponent = 2; + trailing_stiffness = 0.5; + }; + }; + web-devicons.enable = true; + }; + + extraConfigLuaPost = lib.mkMerge [ + (lib.mkOrder 1110 '' + local dracula = require("dracula") + dracula.setup({ + italic_comment = true, + overrides = function(colors) + return { + CursorLineNr = { fg = colors.purple, bold = true }, + LineNr = { fg = colors.white }, + LineNrAbove = { fg = colors.white }, + LineNrBelow = { fg = colors.white }, + } + end, + transparent_bg = false, + }) + vim.cmd.colorscheme("dracula") + '') + (lib.mkOrder 1130 '' + require("incline").setup({ + hide = { cursorline = true }, + highlight = { + groups = { + InclineNormal = { guibg = "#BD93F9", guifg = "#282A36" }, + InclineNormalNC = { guibg = "#44475A", guifg = "#6272A4" }, + }, + }, + window = { margin = { vertical = 0, horizontal = 1 } }, + }) + '') + ]; +} diff --git a/nix-configs/home/modules/packages/ai.nix b/nix-configs/home/modules/packages/ai.nix new file mode 100644 index 0000000..c97aa84 --- /dev/null +++ b/nix-configs/home/modules/packages/ai.nix @@ -0,0 +1,12 @@ +{ + llm-agents, + pkgs, + ... +}: { + home.packages = with llm-agents.packages.${pkgs.stdenv.hostPlatform.system}; [ + claude-code + codex + opencode + apm + ]; +} diff --git a/nix-configs/home/packages/cli.nix b/nix-configs/home/modules/packages/cli.nix similarity index 93% rename from nix-configs/home/packages/cli.nix rename to nix-configs/home/modules/packages/cli.nix index 9b2a414..012536b 100644 --- a/nix-configs/home/packages/cli.nix +++ b/nix-configs/home/modules/packages/cli.nix @@ -2,6 +2,7 @@ home.packages = with pkgs; [ # actrun bat + chezmoi delta difftastic diffnav @@ -14,6 +15,7 @@ gping gtop gh-dash + git just lsd ripgrep diff --git a/nix-configs/home/packages/core.nix b/nix-configs/home/modules/packages/core-cli.nix similarity index 78% rename from nix-configs/home/packages/core.nix rename to nix-configs/home/modules/packages/core-cli.nix index 9fdea09..912bffc 100644 --- a/nix-configs/home/packages/core.nix +++ b/nix-configs/home/modules/packages/core-cli.nix @@ -4,16 +4,12 @@ fastfetch fd fzf - ghostty jq lazygit nil peco starship tree-sitter - vim - wezterm yazi - zed-editor ]; } diff --git a/nix-configs/profiles/desktop-apps.nix b/nix-configs/home/modules/packages/desktop.nix similarity index 69% rename from nix-configs/profiles/desktop-apps.nix rename to nix-configs/home/modules/packages/desktop.nix index 1d242d6..96505e2 100644 --- a/nix-configs/profiles/desktop-apps.nix +++ b/nix-configs/home/modules/packages/desktop.nix @@ -1,23 +1,25 @@ {pkgs, ...}: { - environment.systemPackages = with pkgs; [ + imports = [./core-cli.nix]; + + home.packages = with pkgs; [ + brave fuzzel gh + google-chrome + ghostty lazygit + linux-wallpaperengine nautilus - networkmanagerapplet pavucontrol playerctl qt6Packages.fcitx5-configtool - linux-wallpaperengine + spotify swaybg swayidle swaylock - vial vesktop - xwayland-satellite - brave - google-chrome - prismlauncher - spotify + vial + wezterm + zed-editor ]; } diff --git a/nix-configs/home/packages/development.nix b/nix-configs/home/modules/packages/development.nix similarity index 75% rename from nix-configs/home/packages/development.nix rename to nix-configs/home/modules/packages/development.nix index df62f67..5ed01e2 100644 --- a/nix-configs/home/packages/development.nix +++ b/nix-configs/home/modules/packages/development.nix @@ -1,8 +1,12 @@ -{pkgs, ...}: { +{ + localPackages, + pkgs, + ... +}: { home.packages = with pkgs; [ rustup nodejs - (pkgs.callPackage ../../pkgs/vite-plus/package.nix {}) + localPackages.vitePlus deno bun python3 diff --git a/nix-configs/home/packages/gaming.nix b/nix-configs/home/modules/packages/gaming.nix similarity index 100% rename from nix-configs/home/packages/gaming.nix rename to nix-configs/home/modules/packages/gaming.nix diff --git a/nix-configs/home/packages/lsp.nix b/nix-configs/home/modules/packages/language-servers.nix similarity index 93% rename from nix-configs/home/packages/lsp.nix rename to nix-configs/home/modules/packages/language-servers.nix index b9ed013..3d4018e 100644 --- a/nix-configs/home/packages/lsp.nix +++ b/nix-configs/home/modules/packages/language-servers.nix @@ -6,7 +6,6 @@ gofumpt gopls gotools - markdownlint-cli2 marksman nixfmt prettier diff --git a/nix-configs/home/packages/media.nix b/nix-configs/home/modules/packages/media.nix similarity index 77% rename from nix-configs/home/packages/media.nix rename to nix-configs/home/modules/packages/media.nix index f42b7a7..5f5a5f6 100644 --- a/nix-configs/home/packages/media.nix +++ b/nix-configs/home/modules/packages/media.nix @@ -1,17 +1,16 @@ { config, lib, + localPackages, pkgs, ... -}: let - librepods = pkgs.callPackage ../../pkgs/librepods/package.nix {}; -in { +}: { home.packages = with pkgs; [ audacity ffmpeg gimp imv - librepods + localPackages.librepods kooha mpv obs-studio diff --git a/nix-configs/home/modules/packages/wayland.nix b/nix-configs/home/modules/packages/wayland.nix new file mode 100644 index 0000000..cd5902f --- /dev/null +++ b/nix-configs/home/modules/packages/wayland.nix @@ -0,0 +1,20 @@ +{ + localPackages, + pkgs, + ... +}: { + home.packages = with pkgs; [ + blueman + brightnessctl + cava + libnotify + networkmanagerapplet + pamixer + localPackages.swaynotificationcenterSlide + localPackages.waycal + waybar + wl-clipboard + xwayland-satellite + xdg-utils + ]; +} diff --git a/nix-configs/home/modules/packages/wsl-cli.nix b/nix-configs/home/modules/packages/wsl-cli.nix new file mode 100644 index 0000000..8af5353 --- /dev/null +++ b/nix-configs/home/modules/packages/wsl-cli.nix @@ -0,0 +1,3 @@ +{pkgs, ...}: { + home.packages = [pkgs.vim]; +} diff --git a/nix-configs/home/zsh.nix b/nix-configs/home/modules/shell/zsh.nix similarity index 72% rename from nix-configs/home/zsh.nix rename to nix-configs/home/modules/shell/zsh.nix index 8d357ac..6b3cf15 100644 --- a/nix-configs/home/zsh.nix +++ b/nix-configs/home/modules/shell/zsh.nix @@ -1,9 +1,15 @@ { config, + editor, lib, pkgs, ... }: { + xdg.configFile = lib.mkIf (editor == "nvim") { + "zsh/rc".source = ./zsh/files/rc; + "zsh/starship-nix.toml".source = ./zsh/files/starship-nix.toml; + }; + programs.zsh = { enable = true; dotDir = "${config.xdg.configHome}/zsh"; @@ -11,7 +17,10 @@ enableCompletion = false; history = { - path = "${config.xdg.configHome}/zsh/.zsh_history"; + path = + if editor == "nvim" + then "${config.xdg.configHome}/zsh/.zsh_history" + else "${config.xdg.stateHome}/zsh/history"; size = 100000; save = 100000; extended = true; @@ -23,27 +32,32 @@ }; sessionVariables = { - MANPAGER = "nvim +Man!"; + MANPAGER = + if editor == "nvim" + then "nvim +Man!" + else "less"; LESSHISTFILE = "\${XDG_STATE_HOME:-$HOME/.local/state}/less/history"; LISTMAX = "50"; }; - envExtra = '' - setopt no_global_rcs - - export ZRCDIR="$ZDOTDIR/rc" - export LOCAL_ZSH_DIR="$HOME/.config/local/zsh" + envExtra = + '' + setopt no_global_rcs - export EDITOR=nvim - export VISUAL="$EDITOR" - export GIT_EDITOR="$EDITOR" + export EDITOR=${editor} + export VISUAL="$EDITOR" + export GIT_EDITOR="$EDITOR" - export GOPATH="$HOME/go" - export GO111MODULE=on - path=("$HOME/.local/bin" "$GOPATH/bin" "$HOME/.cargo/bin" $path) - ''; + export GOPATH="$HOME/go" + export GO111MODULE=on + path=("$HOME/.local/bin" "$GOPATH/bin" "$HOME/.cargo/bin" $path) + '' + + lib.optionalString (editor == "nvim") '' + export ZRCDIR="$ZDOTDIR/rc" + export LOCAL_ZSH_DIR="$HOME/.config/local/zsh" + ''; - initContent = lib.mkMerge [ + initContent = lib.mkIf (editor == "nvim") (lib.mkMerge [ (lib.mkOrder 560 '' fpath+=(${pkgs.zsh-completions}/share/zsh/site-functions) '') @@ -96,6 +110,6 @@ zstyle ':autocomplete:*' list-lines 10 source ${pkgs.zsh-autocomplete}/share/zsh-autocomplete/zsh-autocomplete.plugin.zsh '' - ]; + ]); }; } diff --git a/.config/nixos/zsh/rc/alias.zsh b/nix-configs/home/modules/shell/zsh/files/rc/alias.zsh similarity index 92% rename from .config/nixos/zsh/rc/alias.zsh rename to nix-configs/home/modules/shell/zsh/files/rc/alias.zsh index 2524a7a..b88ef25 100644 --- a/.config/nixos/zsh/rc/alias.zsh +++ b/nix-configs/home/modules/shell/zsh/files/rc/alias.zsh @@ -29,10 +29,6 @@ fi alias lg='lazygit' alias ff='fastfetch' alias y='yy' -# 旧 `cx` エイリアスが読み込まれたままの既存シェルでも、関数版へ移行する。 -unalias cx 2>/dev/null -alias cxa='cx-account' - function open { local target="${1:-.}" diff --git a/.config/nixos/zsh/rc/bindkey.zsh b/nix-configs/home/modules/shell/zsh/files/rc/bindkey.zsh similarity index 100% rename from .config/nixos/zsh/rc/bindkey.zsh rename to nix-configs/home/modules/shell/zsh/files/rc/bindkey.zsh diff --git a/.config/nixos/zsh/rc/functions/fancy-ctrl-z b/nix-configs/home/modules/shell/zsh/files/rc/functions/fancy-ctrl-z similarity index 100% rename from .config/nixos/zsh/rc/functions/fancy-ctrl-z rename to nix-configs/home/modules/shell/zsh/files/rc/functions/fancy-ctrl-z diff --git a/.config/nixos/zsh/rc/functions/ghq-fzf b/nix-configs/home/modules/shell/zsh/files/rc/functions/ghq-fzf similarity index 100% rename from .config/nixos/zsh/rc/functions/ghq-fzf rename to nix-configs/home/modules/shell/zsh/files/rc/functions/ghq-fzf diff --git a/.config/nixos/zsh/rc/functions/nix b/nix-configs/home/modules/shell/zsh/files/rc/functions/nix similarity index 94% rename from .config/nixos/zsh/rc/functions/nix rename to nix-configs/home/modules/shell/zsh/files/rc/functions/nix index 6dd2707..4bd08b6 100644 --- a/.config/nixos/zsh/rc/functions/nix +++ b/nix-configs/home/modules/shell/zsh/files/rc/functions/nix @@ -22,7 +22,7 @@ if [[ "$1" == "develop" && -t 1 ]]; then esac done # dev shell 内では starship を Nix テーマ配色に差し替える (子 zsh の環境だけに適用)。 - local nix_starship="$HOME/dotfiles/.config/nixos/starship-nix.toml" + local nix_starship="$XDG_CONFIG_HOME/zsh/starship-nix.toml" if [[ -r "$nix_starship" ]]; then STARSHIP_CONFIG="$nix_starship" command nix "$@" --command zsh else diff --git a/.config/nixos/zsh/rc/functions/nix-shell b/nix-configs/home/modules/shell/zsh/files/rc/functions/nix-shell similarity index 90% rename from .config/nixos/zsh/rc/functions/nix-shell rename to nix-configs/home/modules/shell/zsh/files/rc/functions/nix-shell index 68a1087..3f24d71 100644 --- a/.config/nixos/zsh/rc/functions/nix-shell +++ b/nix-configs/home/modules/shell/zsh/files/rc/functions/nix-shell @@ -15,7 +15,7 @@ if [[ -t 1 ]]; then esac done # nix() と同様に dev shell 内では starship を Nix テーマ配色に差し替える。 - local nix_starship="$HOME/dotfiles/.config/nixos/starship-nix.toml" + local nix_starship="$XDG_CONFIG_HOME/zsh/starship-nix.toml" if [[ -r "$nix_starship" ]]; then STARSHIP_CONFIG="$nix_starship" command nix-shell "$@" --command zsh else diff --git a/.config/nixos/zsh/rc/functions/yy b/nix-configs/home/modules/shell/zsh/files/rc/functions/yy similarity index 100% rename from .config/nixos/zsh/rc/functions/yy rename to nix-configs/home/modules/shell/zsh/files/rc/functions/yy diff --git a/.config/nixos/zsh/rc/option.zsh b/nix-configs/home/modules/shell/zsh/files/rc/option.zsh similarity index 100% rename from .config/nixos/zsh/rc/option.zsh rename to nix-configs/home/modules/shell/zsh/files/rc/option.zsh diff --git a/.config/nixos/starship-nix.toml b/nix-configs/home/modules/shell/zsh/files/starship-nix.toml similarity index 100% rename from .config/nixos/starship-nix.toml rename to nix-configs/home/modules/shell/zsh/files/starship-nix.toml diff --git a/nix-configs/home/modules/xdg/files.nix b/nix-configs/home/modules/xdg/files.nix new file mode 100644 index 0000000..0524137 --- /dev/null +++ b/nix-configs/home/modules/xdg/files.nix @@ -0,0 +1,7 @@ +{config, ...}: let + link = path: config.lib.file.mkOutOfStoreSymlink "${config.home.homeDirectory}/dotfiles/${path}"; +in { + xdg.configFile = { + "fcitx5/config".source = link "mutable/nixos/fcitx5/config"; + }; +} diff --git a/nix-configs/home/modules/xdg/mime-apps.nix b/nix-configs/home/modules/xdg/mime-apps.nix new file mode 100644 index 0000000..049a84a --- /dev/null +++ b/nix-configs/home/modules/xdg/mime-apps.nix @@ -0,0 +1,42 @@ +{ + xdg = { + mimeApps = { + enable = true; + defaultApplications = { + "application/xhtml+xml" = "brave-browser.desktop"; + "audio/aac" = "mpv.desktop"; + "audio/flac" = "mpv.desktop"; + "audio/mpeg" = "mpv.desktop"; + "audio/ogg" = "mpv.desktop"; + "audio/opus" = "mpv.desktop"; + "audio/wav" = "mpv.desktop"; + "audio/x-m4a" = "mpv.desktop"; + "image/avif" = "imv.desktop"; + "image/bmp" = "imv.desktop"; + "image/gif" = "imv.desktop"; + "image/jpeg" = "imv.desktop"; + "image/png" = "imv.desktop"; + "image/svg+xml" = "imv.desktop"; + "image/tiff" = "imv.desktop"; + "image/webp" = "imv.desktop"; + "inode/directory" = "org.gnome.Nautilus.desktop"; + "video/mp4" = "mpv.desktop"; + "video/mpeg" = "mpv.desktop"; + "video/quicktime" = "mpv.desktop"; + "video/webm" = "mpv.desktop"; + "video/x-matroska" = "mpv.desktop"; + "video/x-msvideo" = "mpv.desktop"; + "text/html" = "brave-browser.desktop"; + "x-scheme-handler/about" = "brave-browser.desktop"; + "x-scheme-handler/claude-cli" = "claude-code-url-handler.desktop"; + "x-scheme-handler/discord" = "vesktop.desktop"; + "x-scheme-handler/http" = "brave-browser.desktop"; + "x-scheme-handler/https" = "brave-browser.desktop"; + "x-scheme-handler/unknown" = "brave-browser.desktop"; + }; + }; + + configFile."mimeapps.list".force = true; + dataFile."applications/mimeapps.list".force = true; + }; +} diff --git a/nix-configs/home/packages.nix b/nix-configs/home/packages.nix deleted file mode 100644 index a2b79ec..0000000 --- a/nix-configs/home/packages.nix +++ /dev/null @@ -1,12 +0,0 @@ -{...}: { - imports = [ - ./packages/core.nix - ./packages/cli.nix - ./packages/development.nix - ./packages/lsp.nix - ./packages/llm.nix - ./packages/media.nix - ./packages/gaming.nix - ./packages/wayland.nix - ]; -} diff --git a/nix-configs/home/packages/llm.nix b/nix-configs/home/packages/llm.nix deleted file mode 100644 index 6ca704e..0000000 --- a/nix-configs/home/packages/llm.nix +++ /dev/null @@ -1,16 +0,0 @@ -{ - claudex, - llm-agents, - pkgs, - ... -}: let - claudexPackage = pkgs.callPackage ../../pkgs/claudex/package.nix {src = claudex;}; -in { - home.packages = with llm-agents.packages.${pkgs.system}; [ - claude-code - claudexPackage - codex - opencode - apm - ]; -} diff --git a/nix-configs/home/packages/wayland.nix b/nix-configs/home/packages/wayland.nix deleted file mode 100644 index aead4d1..0000000 --- a/nix-configs/home/packages/wayland.nix +++ /dev/null @@ -1,62 +0,0 @@ -{pkgs, ...}: let - swaynotificationcenterWithSlideDismiss = pkgs.swaynotificationcenter.overrideAttrs (oldAttrs: { - patches = (oldAttrs.patches or []) ++ [./patches/swaync-control-center-slide.patch]; - postPatch = - (oldAttrs.postPatch or "") - + '' - substituteInPlace data/ui/notification.blp \ - --replace-fail "transition-type: crossfade;" "transition-type: slide_right;" - ''; - }); - - waycal = pkgs.rustPlatform.buildRustPackage rec { - pname = "waycal"; - version = "0.2.0"; - - src = pkgs.fetchFromGitHub { - owner = "forrestknight"; - repo = "waycal"; - rev = "237640a09242408e767d68e2080b0f011fecc8e3"; - hash = "sha256-h/+L1cAVdamfUGcz5wFGgLNcXCq/O3/LSQJ4Ap8kS2E="; - }; - - cargoHash = "sha256-zOOG8vF0d3+X85O6bu0Y5XKNZSjcufKMHXQmZ54jCXw="; - nativeBuildInputs = [pkgs.pkg-config]; - buildInputs = [ - pkgs.gtk4 - pkgs.gtk4-layer-shell - ]; - - postPatch = '' - substituteInPlace src/main.rs \ - --replace-fail '#1a2125' '#1e1e2e' \ - --replace-fail '#8FBC8F' '#cba6f7' \ - --replace-fail '#c9d1d9' '#cdd6f4' \ - --replace-fail '#6a7a71' '#7f849c' \ - --replace-fail 'rgba(26, 33, 37, 0.96)' 'rgba(30, 30, 46, 0.96)' \ - --replace-fail 'rgba(143, 188, 143, 0.18)' 'rgba(203, 166, 247, 0.18)' - ''; - - meta = { - description = "Tiny GTK4 calendar popup for Waybar"; - homepage = "https://www.waycal.dev"; - license = pkgs.lib.licenses.mit; - mainProgram = "waycal"; - }; - }; -in { - home.packages = with pkgs; [ - blueman - brightnessctl - cava - libnotify - networkmanagerapplet - pamixer - swaynotificationcenterWithSlideDismiss - waycal - waybar - wl-clipboard - xwayland-satellite - xdg-utils - ]; -} diff --git a/nix-configs/home/profiles/ci.nix b/nix-configs/home/profiles/ci.nix new file mode 100644 index 0000000..9deff2f --- /dev/null +++ b/nix-configs/home/profiles/ci.nix @@ -0,0 +1,13 @@ +{ + imports = [ + ../modules/core/identity.nix + ../modules/core/programs.nix + ../modules/packages/core-cli.nix + ../modules/packages/cli.nix + ../modules/shell/zsh.nix + ../modules/agents/apm.nix + ../modules/agents/codex.nix + ../modules/xdg/files.nix + ../modules/xdg/mime-apps.nix + ]; +} diff --git a/nix-configs/home/profiles/workstation.nix b/nix-configs/home/profiles/workstation.nix new file mode 100644 index 0000000..1e9a2c5 --- /dev/null +++ b/nix-configs/home/profiles/workstation.nix @@ -0,0 +1,33 @@ +{...}: { + imports = [ + ../modules/core/identity.nix + ../modules/core/programs.nix + ../modules/shell/zsh.nix + ../modules/packages/desktop.nix + ../modules/packages/cli.nix + ../modules/packages/development.nix + ../modules/packages/language-servers.nix + ../modules/packages/ai.nix + ../modules/packages/media.nix + ../modules/packages/gaming.nix + ../modules/packages/wayland.nix + ../modules/desktop/appearance.nix + ../modules/desktop/quick-shell.nix + ../modules/desktop/niri.nix + ../modules/desktop/lockscreen.nix + ../modules/desktop/wallpaper.nix + ../modules/desktop/swaync.nix + ../modules/desktop/waybar.nix + ../modules/apps/razer.nix + ../modules/apps/vr.nix + ../modules/editors/nixvim + ../modules/apps/firefox.nix + ../modules/apps/vicinae.nix + ../modules/apps/spotify.nix + ../modules/agents/apm.nix + ../modules/agents/codex.nix + ../modules/agents/codex-desktop.nix + ../modules/xdg/files.nix + ../modules/xdg/mime-apps.nix + ]; +} diff --git a/nix-configs/home/profiles/wsl.nix b/nix-configs/home/profiles/wsl.nix new file mode 100644 index 0000000..1a0deb9 --- /dev/null +++ b/nix-configs/home/profiles/wsl.nix @@ -0,0 +1,10 @@ +{ + imports = [ + ../modules/core/identity.nix + ../modules/core/programs.nix + ../modules/packages/core-cli.nix + ../modules/packages/cli.nix + ../modules/packages/wsl-cli.nix + ../modules/shell/zsh.nix + ]; +} diff --git a/nix-configs/home/xdg.nix b/nix-configs/home/xdg.nix deleted file mode 100644 index 788982c..0000000 --- a/nix-configs/home/xdg.nix +++ /dev/null @@ -1,208 +0,0 @@ -{ - config, - lib, - pkgs, - llm-agents, - ... -}: let - # link (out-of-store): mkOutOfStoreSymlink で store の外にある「書き込み可能な実体」を指す。 - # dotfilesDir (= self.outPath) は store 内 (読み取り専用) なので、ライブの作業ツリー - # (~/dotfiles) を基準に symlink を張る。プログラム自身が設定 dir/file へ書き戻すもの - # (lazygit の state.yml、nvim の lazy-lock.json、zsh の .zwc、codex/claude のランタイム状態、 - # GUI 由来で再書き込みされる fcitx5 など) に使う。編集に rebuild は不要。 - link = path: config.lib.file.mkOutOfStoreSymlink "${config.home.homeDirectory}/dotfiles/${path}"; - - # store (in-store): path をそのまま nix store へコピーし、読み取り専用で配置する。 - # プログラムが書き込まない静的設定に使う。変更には rebuild (just os-switch) が必要になる - # 代わりに再現性が上がり、誤編集で壊れない。flake 評価で参照するため対象は Git track 必須。 - store = path: ../../. + "/${path}"; - - claudeSettings = lib.recursiveUpdate (builtins.fromJSON (builtins.readFile (store ".config/shared/claude/settings.json"))) ( - builtins.fromJSON (builtins.readFile (store ".config/nixos/claude/settings.hooks.json")) - ); -in { - xdg = { - mimeApps = { - enable = true; - defaultApplications = { - "application/xhtml+xml" = "brave-browser.desktop"; - "audio/aac" = "mpv.desktop"; - "audio/flac" = "mpv.desktop"; - "audio/mpeg" = "mpv.desktop"; - "audio/ogg" = "mpv.desktop"; - "audio/opus" = "mpv.desktop"; - "audio/wav" = "mpv.desktop"; - "audio/x-m4a" = "mpv.desktop"; - "image/avif" = "imv.desktop"; - "image/bmp" = "imv.desktop"; - "image/gif" = "imv.desktop"; - "image/jpeg" = "imv.desktop"; - "image/png" = "imv.desktop"; - "image/svg+xml" = "imv.desktop"; - "image/tiff" = "imv.desktop"; - "image/webp" = "imv.desktop"; - "inode/directory" = "org.gnome.Nautilus.desktop"; - "video/mp4" = "mpv.desktop"; - "video/mpeg" = "mpv.desktop"; - "video/quicktime" = "mpv.desktop"; - "video/webm" = "mpv.desktop"; - "video/x-matroska" = "mpv.desktop"; - "video/x-msvideo" = "mpv.desktop"; - "text/html" = "brave-browser.desktop"; - "x-scheme-handler/about" = "brave-browser.desktop"; - "x-scheme-handler/claude-cli" = "claude-code-url-handler.desktop"; - "x-scheme-handler/discord" = "vesktop.desktop"; - "x-scheme-handler/http" = "brave-browser.desktop"; - "x-scheme-handler/https" = "brave-browser.desktop"; - "x-scheme-handler/unknown" = "brave-browser.desktop"; - }; - }; - - configFile = { - "mimeapps.list".force = true; - # in-store: プログラムが書き込まない静的設定。 - "fastfetch".source = store ".config/shared/fastfetch"; - "claudex/config.toml".source = link ".config/shared/claudex/config.toml"; # profile の追加・更新を claudex から行う - "starship.toml".source = store ".config/shared/starship.toml"; - "vim".source = store ".config/shared/vim"; - "wezterm".source = store ".config/shared/wezterm"; - "yazi".source = store ".config/shared/yazi"; - # out-of-store: プログラム自身が dir/file へ書き戻すもの。 - "lazygit".source = link ".config/shared/lazygit"; # state.yml を書き込む - "nvim".source = link ".config/shared/nvim"; # lazy-lock.json を書き込む - "zed".source = link ".config/shared/zed"; # GUI 設定変更で settings.json を書き戻す - "zsh/rc".source = link ".config/nixos/zsh/rc"; # .zwc を zcompile する - "fcitx5/config".source = link ".config/nixos/fcitx5/config"; # GUI 設定で再書き込み - }; - - dataFile."applications/mimeapps.list".force = true; - }; - - home.file = { - # in-store: プログラムが書き込まない静的設定。 - ".git_template/hooks".source = store ".git_template/hooks"; - ".codex/AGENTS.md".source = store ".config/shared/codex/AGENTS.md"; - ".codex/agents".source = store ".config/shared/codex/agents"; - ".codex/rules".source = store ".config/shared/codex/rules"; - ".claude/CLAUDE.md".source = store ".config/shared/claude/CLAUDE.md"; - ".claude/agents".source = store ".config/shared/claude/agents"; - ".claude/statusline.sh".source = store ".config/shared/claude/statusline.sh"; - ".claude/claude-icon.svg".source = store ".config/shared/claude/claude-icon.svg"; - ".claude/claude-notify-hook.sh" = { - source = store ".config/nixos/claude/claude-notify-hook.sh"; - executable = true; - }; - - # out-of-store: プログラム自身が書き戻すもの。 - ".gitconfig".source = link ".gitconfig"; # git config --global で書き込む - # .codex/config.toml は home.activation.seedCodexConfig で管理する (下記)。 - # out-of-store symlink にすると codex が marketplaces/plugins/mcp_servers 等の実行時状態を - # dotfiles の git 追跡ファイルへ書き戻し汚染するため、静的テンプレートから初回シードした - # 「実ファイル」を codex に所有させ、git ツリーから切り離す。 - ".claude/skills".source = link ".config/shared/apm/.claude/skills"; # apm install の生成物 (source は .config/shared/apm/packages//.apm/skills/) - }; - - # Claude settings.json: 共通 base に NixOS 固有 hooks をマージして生成する。 - # Windows 側の setup_windows.ps1 と同じく、通知 hook の依存は OS 固有ディレクトリに閉じ込める。 - home.activation.generateClaudeSettings = lib.hm.dag.entryAfter ["writeBoundary"] '' - claude_dir="${config.home.homeDirectory}/.claude" - mkdir -p "$claude_dir" - rm -f "$claude_dir/settings.json" - cat > "$claude_dir/settings.json" <<'EOF' - ${builtins.toJSON claudeSettings} - EOF - chmod 0644 "$claude_dir/settings.json" - ''; - - # Codex config.toml: 静的テンプレートから ~/.codex/config.toml を「実ファイル」として初回シードする。 - # codex は起動時に marketplaces/plugins/mcp_servers 等をこのファイルへ書き戻すため、out-of-store - # symlink にすると dotfiles の git 追跡ファイルが汚染される。実ファイル化して codex に所有させ、 - # dotfiles 側は静的な初期値テンプレートとしてのみ保持する (再生成可能に保つ)。 - # 既存が symlink (旧構成の名残) または未作成の場合のみテンプレートで初期化し、実ファイルは温存する。 - home.activation.seedCodexConfig = lib.hm.dag.entryAfter ["writeBoundary"] '' - codex_cfg="${config.home.homeDirectory}/.codex/config.toml" - codex_tmpl="${config.home.homeDirectory}/dotfiles/.config/shared/codex/config.toml" - mkdir -p "${config.home.homeDirectory}/.codex" - if [ -L "$codex_cfg" ] || [ ! -e "$codex_cfg" ]; then - rm -f "$codex_cfg" - cp "$codex_tmpl" "$codex_cfg" - chmod u+w "$codex_cfg" - fi - ''; - - # Codex の設定と Desktop の thread state は実行時に書き換えられるため、 - # 過去の root-wide write を安全な値へ一度だけ移行する。 - home.activation.migrateCodexSandboxState = lib.hm.dag.entryAfter ["seedCodexConfig"] '' - codex_dir="${config.home.homeDirectory}/.codex" - codex_cfg="$codex_dir/config.toml" - - # 旧 personal profile の `:root = "write"` は workspace root として `/` を - # Desktop に渡し得る。現在のテンプレートと同じ read-only root に揃える。 - if [ -f "$codex_cfg" ] \ - && ${pkgs.gnugrep}/bin/grep -q '^default_permissions = "personal"$' "$codex_cfg" \ - && ${pkgs.gnugrep}/bin/grep -q '^":root" = "write"$' "$codex_cfg"; then - ${pkgs.gnused}/bin/sed -i 's/^":root" = "write"$/":root" = "read"/' "$codex_cfg" - fi - - # Retained roots are merged into later Desktop requests. Remove only `/` from - # this specific state key; project roots and all other Codex state are preserved. - for state_file in "$codex_dir/.codex-global-state.json" "$codex_dir/.codex-global-state.json.bak"; do - [ -f "$state_file" ] || continue - if ${pkgs.jq}/bin/jq -e ' - any( - ((.["thread-writable-roots"] // {}) | to_entries[]?.value?); - type == "array" and any(.[]; . == "/") - ) - ' "$state_file" >/dev/null; then - state_tmp="$state_file.tmp.$$" - if ${pkgs.jq}/bin/jq ' - if type == "object" and (.["thread-writable-roots"] | type) == "object" then - .["thread-writable-roots"] |= with_entries( - .value |= if type == "array" then map(select(. != "/")) else . end - ) - else - . - end - ' "$state_file" > "$state_tmp"; then - ${pkgs.coreutils}/bin/chmod --reference="$state_file" "$state_tmp" - ${pkgs.coreutils}/bin/mv "$state_tmp" "$state_file" - else - ${pkgs.coreutils}/bin/rm -f "$state_tmp" - fi - fi - done - ''; - - # apm install: .config/shared/apm/packages//.apm/skills/ (source) から各targetのskills dirへdeployする。 - # APMはCodex向けskillを`.agents/skills`に生成する。Codexは~/.codex/skills/.systemを保持する必要があるため、skillごとのリンクを後段で作る。 - home.activation.apmInstallSkills = lib.hm.dag.entryAfter ["writeBoundary"] '' - cd "${config.home.homeDirectory}/dotfiles/.config/shared/apm" - # activation は systemd 環境で走るため ~/.zshenv は読まれない。gh CLI の keyring からトークンを渡し、 - # apm install が mizchi/skills などを clone する際に GitHub 認証が通るようにする。 - export GITHUB_TOKEN="$(${pkgs.gh}/bin/gh auth token 2>/dev/null || true)" - ${llm-agents.packages.${pkgs.system}.apm}/bin/apm install - ''; - - home.activation.linkCodexSkills = lib.hm.dag.entryAfter ["apmInstallSkills"] '' - source_dir="${config.home.homeDirectory}/dotfiles/.config/shared/apm/.agents/skills" - target_dir="${config.home.homeDirectory}/.codex/skills" - mkdir -p "$target_dir" - find "$target_dir" -maxdepth 1 -type l -lname "$source_dir/*" -delete - for skill in "$source_dir"/*; do - [ -d "$skill" ] || continue - ln -sfn "$skill" "$target_dir/$(basename "$skill")" - done - ''; - - # opencode 向け skill: apm 生成物 (.agents/skills) を ~/.config/opencode/skills/ へ張る。 - home.activation.linkOpencodeSkills = lib.hm.dag.entryAfter ["apmInstallSkills"] '' - source_dir="${config.home.homeDirectory}/dotfiles/.config/shared/apm/.agents/skills" - target_dir="${config.home.homeDirectory}/.config/opencode/skills" - mkdir -p "$target_dir" - find "$target_dir" -maxdepth 1 -type l -lname "$source_dir/*" -delete - for skill in "$source_dir"/*; do - [ -d "$skill" ] || continue - ln -sfn "$skill" "$target_dir/$(basename "$skill")" - done - ''; -} diff --git a/nix-configs/hosts/ci/default.nix b/nix-configs/hosts/ci/default.nix new file mode 100644 index 0000000..670c035 --- /dev/null +++ b/nix-configs/hosts/ci/default.nix @@ -0,0 +1,19 @@ +{ + imports = [ + ../desktop/hardware-configuration.nix + ../../feature/profiles/base.nix + ../../feature/modules/hardware/kernel.nix + ../../feature/modules/hardware/qmk.nix + ../../feature/modules/hardware/xkb.nix + ../../feature/modules/services/bluetooth.nix + ../../feature/modules/services/docker.nix + ../../feature/modules/services/networkmanager.nix + ../../feature/modules/services/tailscale.nix + ]; + + networking.hostName = "nixos"; + system.stateVersion = "26.05"; + + boot.loader.systemd-boot.enable = true; + boot.loader.efi.canTouchEfiVariables = true; +} diff --git a/nix-configs/hosts/desktop/default.nix b/nix-configs/hosts/desktop/default.nix index 2ff3487..8ba0df2 100644 --- a/nix-configs/hosts/desktop/default.nix +++ b/nix-configs/hosts/desktop/default.nix @@ -1,46 +1,19 @@ { imports = [ ./hardware-configuration.nix - ../../modules - ../../modules/lanzaboote.nix - ../../modules/plymouth.nix - ../../profiles/desktop.nix - ../../profiles/nvidia.nix - ../../profiles/gaming.nix - ../../profiles/vr.nix - ../../profiles/desktop-apps.nix + ../../feature/profiles/workstation.nix + ../../feature/modules/hardware/lanzaboote.nix + ../../feature/modules/desktop/plymouth.nix + ../../feature/modules/hardware/nvidia.nix + ../../feature/profiles/gaming.nix + ../../feature/profiles/vr.nix ]; networking.hostName = "desktop"; + system.stateVersion = "26.05"; t4ko.regreet.mainOutput = "DP-2"; - home-manager.users.t4ko.t4ko.niri.monitors = { - "DP-1" = { - mode = "1920x1080@144.000"; - position = { - x = 3840; - y = -840; - }; - transform = "90"; - }; - "DP-2" = { - focusAtStartup = true; - mode = "1920x1080@360.000"; - position = { - x = 0; - y = 0; - }; - }; - "HDMI-A-1" = { - mode = "1920x1080@75.000"; - position = { - x = 1920; - y = 0; - }; - }; - }; - boot.loader.systemd-boot.enable = true; boot.loader.efi.canTouchEfiVariables = true; } diff --git a/nix-configs/hosts/desktop/home.nix b/nix-configs/hosts/desktop/home.nix new file mode 100644 index 0000000..76a3819 --- /dev/null +++ b/nix-configs/hosts/desktop/home.nix @@ -0,0 +1,29 @@ +{ + imports = [../../home/profiles/workstation.nix]; + + t4ko.niri.monitors = { + "DP-1" = { + mode = "1920x1080@144.000"; + position = { + x = 3840; + y = -840; + }; + transform = "90"; + }; + "DP-2" = { + focusAtStartup = true; + mode = "1920x1080@360.000"; + position = { + x = 0; + y = 0; + }; + }; + "HDMI-A-1" = { + mode = "1920x1080@75.000"; + position = { + x = 1920; + y = 0; + }; + }; + }; +} diff --git a/nix-configs/hosts/laptop/default.nix b/nix-configs/hosts/laptop/default.nix index 46d9256..2364bd6 100644 --- a/nix-configs/hosts/laptop/default.nix +++ b/nix-configs/hosts/laptop/default.nix @@ -1,16 +1,15 @@ { imports = [ ./hardware-configuration.nix - ../../modules - ../../modules/plymouth.nix - ../../profiles/desktop.nix - ../../profiles/nvidia-hybrid.nix - ../../profiles/gaming.nix - # ../../profiles/vr.nix - ../../profiles/desktop-apps.nix + ../../feature/profiles/workstation.nix + ../../feature/modules/desktop/plymouth.nix + ../../feature/modules/hardware/nvidia-hybrid.nix + ../../feature/profiles/gaming.nix + # ../../feature/profiles/vr.nix ]; networking.hostName = "laptop"; + system.stateVersion = "26.05"; t4ko.regreet.mainOutput = "HDMI-A-1"; @@ -47,24 +46,6 @@ ]; }; - home-manager.users.t4ko.t4ko.niri.monitors = { - "eDP-1" = { - mode = "1920x1080@165.016"; - position = { - x = 0; - y = 0; - }; - }; - "HDMI-A-1" = { - focusAtStartup = true; - mode = "1920x1080@60.000"; - position = { - x = 1920; - y = 0; - }; - }; - }; - boot.loader.systemd-boot.enable = true; boot.loader.efi.canTouchEfiVariables = true; } diff --git a/nix-configs/hosts/laptop/home.nix b/nix-configs/hosts/laptop/home.nix new file mode 100644 index 0000000..e4e501a --- /dev/null +++ b/nix-configs/hosts/laptop/home.nix @@ -0,0 +1,21 @@ +{ + imports = [../../home/profiles/workstation.nix]; + + t4ko.niri.monitors = { + "eDP-1" = { + mode = "1920x1080@165.016"; + position = { + x = 0; + y = 0; + }; + }; + "HDMI-A-1" = { + focusAtStartup = true; + mode = "1920x1080@60.000"; + position = { + x = 1920; + y = 0; + }; + }; + }; +} diff --git a/nix-configs/hosts/wsl/default.nix b/nix-configs/hosts/wsl/default.nix new file mode 100644 index 0000000..9427523 --- /dev/null +++ b/nix-configs/hosts/wsl/default.nix @@ -0,0 +1,27 @@ +{username, ...}: { + imports = [ + ../../feature/profiles/wsl.nix + ]; + + networking.hostName = "nixos-wsl"; + + wsl = { + enable = true; + defaultUser = username; + interop.includePath = true; + wslConf = { + automount = { + enabled = true; + options = "metadata,umask=22,fmask=11"; + }; + boot.systemd = true; + interop = { + enabled = true; + appendWindowsPath = true; + }; + user.default = username; + }; + }; + + system.stateVersion = "26.05"; +} diff --git a/nix-configs/hosts/wsl/home.nix b/nix-configs/hosts/wsl/home.nix new file mode 100644 index 0000000..f2bbd60 --- /dev/null +++ b/nix-configs/hosts/wsl/home.nix @@ -0,0 +1,3 @@ +{ + imports = [../../home/profiles/wsl.nix]; +} diff --git a/nix-configs/lib/mk-nixos.nix b/nix-configs/lib/mk-nixos.nix new file mode 100644 index 0000000..6ba5b51 --- /dev/null +++ b/nix-configs/lib/mk-nixos.nix @@ -0,0 +1,70 @@ +{ + codex-desktop-linux, + home-manager, + llm-agents, + nixos-loading-plymouth, + nixpkgs, + nixvim, + spotify-cli, + system, + vicinae, +}: { + configuration, + dotfilesDir, + editor ? "nvim", + extraModules ? [], + homeConfiguration, + homeDirectory ? "/home/${username}", + keyboardLayout, + platformModules ? [ + vicinae.nixosModules.default + nixos-loading-plymouth.nixosModules.default + ], + sharedHomeModules ? [ + vicinae.homeManagerModules.default + codex-desktop-linux.homeManagerModules.default + ], + systemOverlays ? [spotify-cli.overlays.default], + userExtraGroups ? [ + "audio" + "input" + "networkmanager" + "plugdev" + "wheel" + ], + username ? "t4ko", +}: let + localPackages = import ../pkgs { + nixosLoadingPlymouth = nixos-loading-plymouth; + pkgs = nixpkgs.legacyPackages.${system}; + }; +in + nixpkgs.lib.nixosSystem { + inherit system; + specialArgs = { + inherit dotfilesDir homeDirectory keyboardLayout localPackages userExtraGroups username; + nixosLoadingPlymouth = nixos-loading-plymouth; + }; + modules = + [ + home-manager.nixosModules.home-manager + configuration + ] + ++ platformModules + ++ extraModules + ++ [ + { + nixpkgs.overlays = systemOverlays; + home-manager = { + useGlobalPkgs = true; + useUserPackages = true; + backupFileExtension = "hm-backup"; + extraSpecialArgs = { + inherit dotfilesDir editor homeDirectory keyboardLayout llm-agents localPackages username; + }; + sharedModules = [nixvim.homeModules.nixvim] ++ sharedHomeModules; + users.${username} = import homeConfiguration; + }; + } + ]; + } diff --git a/nix-configs/lib/catppuccin-mocha.nix b/nix-configs/lib/theme.nix similarity index 96% rename from nix-configs/lib/catppuccin-mocha.nix rename to nix-configs/lib/theme.nix index 333612c..c5d7357 100644 --- a/nix-configs/lib/catppuccin-mocha.nix +++ b/nix-configs/lib/theme.nix @@ -1,3 +1,4 @@ +# catpuccin { base = "#1e1e2e"; mantle = "#181825"; diff --git a/nix-configs/modules/base.nix b/nix-configs/modules/base.nix deleted file mode 100644 index b045e82..0000000 --- a/nix-configs/modules/base.nix +++ /dev/null @@ -1,11 +0,0 @@ -{pkgs, ...}: { - networking.networkmanager.enable = true; - programs.nix-ld.enable = true; - - environment.systemPackages = with pkgs; [ - git - vim - ]; - - system.stateVersion = "26.05"; -} diff --git a/nix-configs/modules/default.nix b/nix-configs/modules/default.nix deleted file mode 100644 index 45ecaca..0000000 --- a/nix-configs/modules/default.nix +++ /dev/null @@ -1,16 +0,0 @@ -{ - imports = [ - ./base.nix - ./bluetooth.nix - ./docker.nix - ./kernel.nix - ./locale.nix - ./nh.nix - ./nix.nix - ./qmk.nix - ./tailscale.nix - ./unfree.nix - ./users.nix - ./xkb.nix - ]; -} diff --git a/nix-configs/modules/plymouth.nix b/nix-configs/modules/plymouth.nix deleted file mode 100644 index 9481fd7..0000000 --- a/nix-configs/modules/plymouth.nix +++ /dev/null @@ -1,53 +0,0 @@ -{ - lib, - nixosLoadingPlymouth, - pkgs, - ... -}: let - themeName = "nixos-loading-default-logs"; - themePackage = pkgs.stdenvNoCC.mkDerivation { - pname = themeName; - version = "0.1.0"; - dontUnpack = true; - - installPhase = '' - themeDir="$out/share/plymouth/themes/${themeName}" - mkdir -p "$themeDir" - cp -r "${nixosLoadingPlymouth.packages.${pkgs.stdenv.hostPlatform.system}.nixos-loading-default}/share/plymouth/themes/nixos-loading-default/." "$themeDir/" - rm "$themeDir/nixos-loading-default.plymouth" - cp "${../assets/plymouth/nixos-loading-logs.script}" "$themeDir/nixos-loading-logs.script" - - cat > "$themeDir/${themeName}.plymouth" < Result<()> { - .await?; - - // 存储到 keyring 并回写 ~/.codex/auth.json -- super::source::store_keyring(profile_name, &token)?; - super::source::write_codex_credentials_atomic(&token)?; -+ if let Err(err) = super::source::store_keyring(profile_name, &token) { -+ tracing::warn!( -+ "failed to store ChatGPT OAuth token in keyring for profile '{profile_name}': {err}" -+ ); -+ } - - println!("ChatGPT OAuth token stored for profile '{profile_name}'."); - Ok(()) -@@ -287,8 +291,12 @@ async fn login_chatgpt_headless(profile_name: &str) -> Result<()> { - ) - .await?; - -- super::source::store_keyring(profile_name, &token)?; - super::source::write_codex_credentials_atomic(&token)?; -+ if let Err(err) = super::source::store_keyring(profile_name, &token) { -+ tracing::warn!( -+ "failed to store ChatGPT OAuth token in keyring for profile '{profile_name}': {err}" -+ ); -+ } - - println!("ChatGPT OAuth token stored for profile '{profile_name}'."); - Ok(()) diff --git a/nix-configs/pkgs/claudex/package.nix b/nix-configs/pkgs/claudex/package.nix deleted file mode 100644 index 7b08c3f..0000000 --- a/nix-configs/pkgs/claudex/package.nix +++ /dev/null @@ -1,32 +0,0 @@ -{ - applyPatches, - cacert, - lib, - rustPlatform, - src, -}: -rustPlatform.buildRustPackage { - pname = "claudex"; - version = "0.2.4"; - - src = applyPatches { - inherit src; - name = "claudex-source"; - patches = [ - ./reasoning-effort.patch - ./oauth-keyring-fallback.patch - ]; - }; - - cargoHash = "sha256-10Mmiofblkrc7DVw6y2U+odeue0Mv1UuLNHy4ClV91o="; - - SSL_CERT_FILE = "${cacert}/etc/ssl/certs/ca-bundle.crt"; - - meta = { - description = "Multi-instance Claude Code manager with an AI-provider translation proxy"; - homepage = "https://claudex.space"; - license = lib.licenses.mit; - mainProgram = "claudex"; - platforms = lib.platforms.linux; - }; -} diff --git a/nix-configs/pkgs/claudex/reasoning-effort.patch b/nix-configs/pkgs/claudex/reasoning-effort.patch deleted file mode 100644 index c9e2509..0000000 --- a/nix-configs/pkgs/claudex/reasoning-effort.patch +++ /dev/null @@ -1,76 +0,0 @@ -diff --git a/src/config/mod.rs b/src/config/mod.rs -index 0c01f80..d02b1d6 100644 ---- a/src/config/mod.rs -+++ b/src/config/mod.rs -@@ -119,6 +119,9 @@ pub struct ProfileConfig { - /// 最大输出 token 数上限(可选,用于限制转发给 provider 的 max_tokens) - #[serde(default)] - pub max_tokens: Option, -+ /// OpenAI Responses API の reasoning effort(例: "high") -+ #[serde(default)] -+ pub reasoning_effort: Option, - /// 从翻译后的请求体中剥离的参数名列表 - /// 用于处理上游端点不支持某些参数的情况(如 Codex ChatGPT 不支持 temperature) - /// 设为 "auto" 时根据 base_url 自动推断 -@@ -218,6 +221,7 @@ impl Default for ProfileConfig { - oauth_provider: None, - models: ProfileModels::default(), - max_tokens: None, -+ reasoning_effort: None, - strip_params: StripParams::default(), - query_params: HashMap::new(), - } -diff --git a/src/proxy/adapter/responses.rs b/src/proxy/adapter/responses.rs -index 9d71b8e..51430b5 100644 ---- a/src/proxy/adapter/responses.rs -+++ b/src/proxy/adapter/responses.rs -@@ -1,6 +1,6 @@ - use anyhow::Result; - use reqwest::RequestBuilder; --use serde_json::Value; -+use serde_json::{json, Value}; - - use super::{ByteStream, ProviderAdapter, TranslatedRequest}; - use crate::config::ProfileConfig; -@@ -18,11 +18,14 @@ impl ProviderAdapter for ResponsesAdapter { - body: &Value, - profile: &ProfileConfig, - ) -> Result { -- let (responses_body, tool_name_map) = -+ let (mut responses_body, tool_name_map) = - crate::proxy::translate::responses::anthropic_to_responses( - body, - &profile.default_model, - )?; -+ if let Some(effort) = &profile.reasoning_effort { -+ responses_body["reasoning"] = json!({ "effort": effort }); -+ } - Ok(TranslatedRequest { - body: responses_body, - tool_name_map, -@@ -57,3 +60,25 @@ impl ProviderAdapter for ResponsesAdapter { - crate::proxy::translate::responses_stream::translate_responses_stream(stream, tool_name_map) - } - } -+ -+#[cfg(test)] -+mod tests { -+ use super::*; -+ use crate::config::ProfileConfig; -+ -+ #[test] -+ fn test_reasoning_effort_is_added_to_responses_request() { -+ let profile = ProfileConfig { -+ default_model: "gpt-5.6-terra".to_string(), -+ reasoning_effort: Some("high".to_string()), -+ ..Default::default() -+ }; -+ let body = serde_json::json!({ -+ "messages": [{"role": "user", "content": "Hello"}], -+ }); -+ -+ let translated = ResponsesAdapter.translate_request(&body, &profile).unwrap(); -+ -+ assert_eq!(translated.body["reasoning"], json!({ "effort": "high" })); -+ } -+} diff --git a/nix-configs/pkgs/default.nix b/nix-configs/pkgs/default.nix new file mode 100644 index 0000000..129fcf4 --- /dev/null +++ b/nix-configs/pkgs/default.nix @@ -0,0 +1,34 @@ +{ + nixosLoadingPlymouth, + pkgs, +}: { + chiffonCursor = import ./chiffon-cursor/package.nix { + inherit pkgs; + inherit (pkgs) lib; + }; + librepods = pkgs.callPackage ./librepods/package.nix {}; + plymouthTheme = pkgs.callPackage ./plymouth-theme/package.nix { + script = ../assets/plymouth/nixos-loading-logs.script; + sourceTheme = nixosLoadingPlymouth.packages.${pkgs.stdenv.hostPlatform.system}.nixos-loading-default; + }; + swaylockLongIdle = pkgs.callPackage ./swaylock-long-idle/package.nix {}; + swaynotificationcenterSlide = pkgs.callPackage ./swaynotificationcenter/package.nix {}; + vimdocJa = pkgs.callPackage ./vim-plugins/vimdoc-ja/package.nix {}; + vitePlus = pkgs.callPackage ./vite-plus/package.nix {}; + waycal = pkgs.callPackage ./waycal/package.nix {}; + winresizer = pkgs.callPackage ./vim-plugins/winresizer/package.nix {}; + wivrnNvenc = + (pkgs.callPackage ./wivrn/package.nix {cudaSupport = true;}).overrideAttrs + (old: { + postFixup = + (old.postFixup or "") + + '' + driverLib=${pkgs.addDriverRunpath.driverLink}/lib + for f in "$out"/bin/.wivrn-server-wrapped "$out"/lib/wivrn/*.so*; do + if [ -f "$f" ] && patchelf --print-rpath "$f" >/dev/null 2>&1; then + patchelf --add-rpath "$driverLib" "$f" + fi + done + ''; + }); +} diff --git a/nix-configs/pkgs/plymouth-theme/package.nix b/nix-configs/pkgs/plymouth-theme/package.nix new file mode 100644 index 0000000..1f3616e --- /dev/null +++ b/nix-configs/pkgs/plymouth-theme/package.nix @@ -0,0 +1,31 @@ +{ + script, + sourceTheme, + stdenvNoCC, +}: let + themeName = "nixos-loading-default-logs"; +in + stdenvNoCC.mkDerivation { + pname = themeName; + version = "0.1.0"; + dontUnpack = true; + + installPhase = '' + themeDir="$out/share/plymouth/themes/${themeName}" + mkdir -p "$themeDir" + cp -r "${sourceTheme}/share/plymouth/themes/nixos-loading-default/." "$themeDir/" + rm "$themeDir/nixos-loading-default.plymouth" + cp "${script}" "$themeDir/nixos-loading-logs.script" + + cat > "$themeDir/${themeName}.plymouth" <eventloop, 1500, set_input_idle, state" \ + "state->eventloop, 10000, set_input_idle, state" + ''; +}) diff --git a/nix-configs/pkgs/swaynotificationcenter/package.nix b/nix-configs/pkgs/swaynotificationcenter/package.nix new file mode 100644 index 0000000..ec97314 --- /dev/null +++ b/nix-configs/pkgs/swaynotificationcenter/package.nix @@ -0,0 +1,10 @@ +{swaynotificationcenter}: +swaynotificationcenter.overrideAttrs (old: { + patches = (old.patches or []) ++ [./swaync-control-center-slide.patch]; + postPatch = + (old.postPatch or "") + + '' + substituteInPlace data/ui/notification.blp \ + --replace-fail "transition-type: crossfade;" "transition-type: slide_right;" + ''; +}) diff --git a/nix-configs/home/packages/patches/swaync-control-center-slide.patch b/nix-configs/pkgs/swaynotificationcenter/swaync-control-center-slide.patch similarity index 100% rename from nix-configs/home/packages/patches/swaync-control-center-slide.patch rename to nix-configs/pkgs/swaynotificationcenter/swaync-control-center-slide.patch diff --git a/nix-configs/pkgs/vim-plugins/vimdoc-ja/package.nix b/nix-configs/pkgs/vim-plugins/vimdoc-ja/package.nix new file mode 100644 index 0000000..debde17 --- /dev/null +++ b/nix-configs/pkgs/vim-plugins/vimdoc-ja/package.nix @@ -0,0 +1,14 @@ +{ + fetchFromGitHub, + vimUtils, +}: +vimUtils.buildVimPlugin { + pname = "vimdoc-ja"; + version = "2026-07-15"; + src = fetchFromGitHub { + owner = "vim-jp"; + repo = "vimdoc-ja"; + rev = "c8c3b339302b4e88be2859b3ba99a4f0a3a2f8bd"; + hash = "sha256-362QsKxCbqXrOru3p+ReoqtfwTLSSblNGzzxTE2DWoI="; + }; +} diff --git a/nix-configs/pkgs/vim-plugins/winresizer/package.nix b/nix-configs/pkgs/vim-plugins/winresizer/package.nix new file mode 100644 index 0000000..385c2d6 --- /dev/null +++ b/nix-configs/pkgs/vim-plugins/winresizer/package.nix @@ -0,0 +1,14 @@ +{ + fetchFromGitHub, + vimUtils, +}: +vimUtils.buildVimPlugin { + pname = "winresizer"; + version = "2026-07-15"; + src = fetchFromGitHub { + owner = "simeji"; + repo = "winresizer"; + rev = "299076f7f79e2e2f7706b2dfacbb3c074ce53257"; + hash = "sha256-rTTe6hFgEz9CFPJFDUjoD3SQr97V5E5Lg6J4c8mU+6s="; + }; +} diff --git a/nix-configs/pkgs/vite-plus/package.nix b/nix-configs/pkgs/vite-plus/package.nix index 786a9e9..6998764 100644 --- a/nix-configs/pkgs/vite-plus/package.nix +++ b/nix-configs/pkgs/vite-plus/package.nix @@ -5,14 +5,13 @@ lib, stdenv, }: -stdenv.mkDerivation { +stdenv.mkDerivation rec { pname = "vite-plus"; - version = "latest"; + version = "0.2.6"; src = fetchurl { - url = "https://github.com/voidzero-dev/vite-plus/releases/latest/download/vp-x86_64-unknown-linux-gnu.tar.gz"; - # Update this hash when the latest Vite+ release changes. - hash = "sha256-Pwu2w1AAtNFJWf9zRkTdjFsMfi5rP2ia7yw+UguBzUU="; + url = "https://github.com/voidzero-dev/vite-plus/releases/download/v${version}/vp-x86_64-unknown-linux-gnu.tar.gz"; + hash = "sha256-f46IAFyVK6+WkW50qQHNPJ6f4Wtoj9WEdOjsOhfTpkE="; }; nativeBuildInputs = [autoPatchelfHook]; diff --git a/nix-configs/pkgs/waycal/package.nix b/nix-configs/pkgs/waycal/package.nix new file mode 100644 index 0000000..5caa6ff --- /dev/null +++ b/nix-configs/pkgs/waycal/package.nix @@ -0,0 +1,40 @@ +{ + fetchFromGitHub, + gtk4, + gtk4-layer-shell, + lib, + pkg-config, + rustPlatform, +}: +rustPlatform.buildRustPackage rec { + pname = "waycal"; + version = "0.2.0"; + + src = fetchFromGitHub { + owner = "forrestknight"; + repo = "waycal"; + rev = "237640a09242408e767d68e2080b0f011fecc8e3"; + hash = "sha256-h/+L1cAVdamfUGcz5wFGgLNcXCq/O3/LSQJ4Ap8kS2E="; + }; + + cargoHash = "sha256-zOOG8vF0d3+X85O6bu0Y5XKNZSjcufKMHXQmZ54jCXw="; + nativeBuildInputs = [pkg-config]; + buildInputs = [gtk4 gtk4-layer-shell]; + + postPatch = '' + substituteInPlace src/main.rs \ + --replace-fail '#1a2125' '#1e1e2e' \ + --replace-fail '#8FBC8F' '#cba6f7' \ + --replace-fail '#c9d1d9' '#cdd6f4' \ + --replace-fail '#6a7a71' '#7f849c' \ + --replace-fail 'rgba(26, 33, 37, 0.96)' 'rgba(30, 30, 46, 0.96)' \ + --replace-fail 'rgba(143, 188, 143, 0.18)' 'rgba(203, 166, 247, 0.18)' + ''; + + meta = { + description = "Tiny GTK4 calendar popup for Waybar"; + homepage = "https://www.waycal.dev"; + license = lib.licenses.mit; + mainProgram = "waycal"; + }; +} diff --git a/nix-configs/profiles/desktop.nix b/nix-configs/profiles/desktop.nix deleted file mode 100644 index bfd27a1..0000000 --- a/nix-configs/profiles/desktop.nix +++ /dev/null @@ -1,103 +0,0 @@ -{ - keyboardLayout, - pkgs, - ... -}: { - imports = [ - ./regreet.nix - ]; - - i18n.inputMethod = { - enable = true; - type = "fcitx5"; - fcitx5 = { - waylandFrontend = true; - addons = with pkgs; [ - fcitx5-mozc - fcitx5-gtk - fcitx5-material-color - qt6Packages.fcitx5-qt - ]; - settings.inputMethod = { - "Groups/0" = { - Name = "Default"; - "Default Layout" = keyboardLayout.fcitxLayout; - DefaultIM = "mozc"; - }; - "Groups/0/Items/0" = { - Name = "keyboard-jp"; - Layout = keyboardLayout.fcitxLayout; - }; - "Groups/0/Items/1" = { - Name = "mozc"; - Layout = keyboardLayout.fcitxLayout; - }; - GroupOrder."0" = "Default"; - }; - }; - }; - - fonts.packages = with pkgs; [ - noto-fonts - noto-fonts-cjk-sans - noto-fonts-cjk-serif - noto-fonts-color-emoji - nerd-fonts.jetbrains-mono - nerd-fonts.symbols-only - plemoljp-nf - ]; - - fonts.fontconfig.defaultFonts = { - monospace = [ - "PlemolJP Console NF" - "Noto Sans Mono CJK JP" - ]; - sansSerif = [ - "Noto Sans CJK JP" - "Noto Sans" - ]; - serif = [ - "Noto Serif CJK JP" - "Noto Serif" - ]; - emoji = ["Noto Color Emoji"]; - }; - - services = { - xserver.enable = false; - - printing.enable = true; - - pulseaudio.enable = false; - pipewire = { - enable = true; - alsa.enable = true; - alsa.support32Bit = true; - pulse.enable = true; - }; - }; - - programs.niri.enable = true; - programs.dconf.enable = true; - - xdg.portal = { - enable = true; - extraPortals = with pkgs; [ - xdg-desktop-portal-gtk - ]; - configPackages = [pkgs.niri]; - }; - - security.polkit.enable = true; - security.rtkit.enable = true; - - environment.sessionVariables = { - NIXOS_OZONE_WL = "1"; - MOZ_ENABLE_WAYLAND = "1"; - GTK_IM_MODULE = "fcitx"; - QT_IM_MODULE = "fcitx"; - XMODIFIERS = "@im=fcitx"; - }; - - hardware.graphics.enable = true; -} diff --git a/nix-configs/profiles/gaming.nix b/nix-configs/profiles/gaming.nix deleted file mode 100644 index 3d4e991..0000000 --- a/nix-configs/profiles/gaming.nix +++ /dev/null @@ -1,18 +0,0 @@ -{pkgs, ...}: { - programs.steam = { - enable = true; - extraCompatPackages = with pkgs; [proton-ge-bin]; - }; - - programs.gamemode.enable = true; - - hardware.graphics.enable32Bit = true; - - # Razer デバイス制御 (OpenRazer カーネルモジュール + デーモン) - # GUI フロントエンドの polychromatic は home/packages/gaming.nix 側で導入済み - hardware.openrazer = { - enable = true; - users = ["t4ko"]; - }; - environment.systemPackages = [pkgs.openrazer-daemon]; -} diff --git a/scripts/bootstrap.ps1 b/scripts/bootstrap.ps1 index 5281f2b..5ff2828 100644 --- a/scripts/bootstrap.ps1 +++ b/scripts/bootstrap.ps1 @@ -1,7 +1,6 @@ #!/usr/bin/env pwsh # ----------------------------------------------------------------------------- -# bootstrap.ps1 — dotfiles の依存関係を一括インストール -# 完了後 `scripts\setup_windows.ps1` を実行してリンクを張る。 +# bootstrap.ps1 — Windows依存関係を導入し、chezmoi profileを適用する。 # ----------------------------------------------------------------------------- $ErrorActionPreference = 'Stop' @@ -127,12 +126,11 @@ foreach ($b in $scoopBuckets) { # --------------------------------------------------------------------------- $scoopPackages = @( 'main/7zip', + 'main/chezmoi', 'main/ffmpeg', 'main/gcc', 'main/starship', 'main/mise', - 'extras/komorebi', - 'extras/whkd', 'extras/lazygit', 'extras/yazi', 'extras/fastfetch', @@ -168,4 +166,11 @@ foreach ($pkg in $scoopPackages) { } Write-Host "`n[OK] Bootstrap completed." -ForegroundColor Green -Write-Host "次に: pwsh -ExecutionPolicy Bypass -File .\scripts\setup_windows.ps1" -ForegroundColor White + +$repo = Split-Path -Parent $PSScriptRoot +chezmoi --source $repo init --apply --promptChoice 'Environment profile=windows' +if ($LASTEXITCODE -ne 0) { + throw "chezmoi apply failed with exit code $LASTEXITCODE" +} + +Write-Host "[OK] Windows profile applied." -ForegroundColor Green diff --git a/scripts/check_chezmoi.sh b/scripts/check_chezmoi.sh new file mode 100644 index 0000000..1509afd --- /dev/null +++ b/scripts/check_chezmoi.sh @@ -0,0 +1,194 @@ +#!/usr/bin/env bash + +set -euo pipefail + +repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +ownership_file="$repo_root/docs/memo/dotfiles-ownership.tsv" +temp_dir="$(mktemp -d)" +trap 'rm -rf "$temp_dir"' EXIT + +if [[ "$(<"$repo_root/.chezmoiroot")" != "chezmoi" ]]; then + printf '%s\n' '.chezmoiroot must point to chezmoi' >&2 + exit 1 +fi + +for mutable_dir in mutable/nvim mutable/cava mutable/shared/apm mutable/shared/lazygit mutable/shared/zed mutable/nixos/fcitx5; do + if [[ ! -d "$repo_root/$mutable_dir" ]]; then + printf 'mutable source does not exist: %s\n' "$mutable_dir" >&2 + exit 1 + fi +done + +if [[ ! -f "$repo_root/mutable/shared/gitconfig" ]]; then + printf '%s\n' 'mutable source does not exist: mutable/shared/gitconfig' >&2 + exit 1 +fi + +declare -A targets=() +while IFS=$'\t' read -r profile target owner _mode _source; do + [[ -z "$profile" || "$profile" == profile ]] && continue + + case "$profile" in + windows | nixos | wsl) ;; + *) + printf 'invalid profile: %s\n' "$profile" >&2 + exit 1 + ;; + esac + + case "$owner" in + chezmoi | nix | unmanaged) ;; + *) + printf 'invalid owner: %s\n' "$owner" >&2 + exit 1 + ;; + esac + + key="$profile:$target" + if [[ -n "${targets[$key]:-}" ]]; then + printf 'duplicate ownership: %s\n' "$key" >&2 + exit 1 + fi + targets[$key]="$owner" +done < "$ownership_file" + +for profile in windows nixos wsl; do + rendered="$temp_dir/chezmoi-$profile.toml" + chezmoi \ + --config /dev/null \ + --config-format toml \ + execute-template \ + --init \ + --promptChoice "Environment profile=$profile" \ + --file "$repo_root/chezmoi/.chezmoi.toml.tmpl" > "$rendered" + + if ! grep -q "profile = \"$profile\"" "$rendered"; then + printf 'profile was not rendered: %s\n' "$profile" >&2 + exit 1 + fi + + if ! grep -q 'username = "t4ko"' "$rendered"; then + printf 'username was not rendered for profile: %s\n' "$profile" >&2 + exit 1 + fi + + rendered_script="$temp_dir/create-windows-junctions-$profile.ps1" + chezmoi \ + --config "$rendered" \ + execute-template \ + --file "$repo_root/chezmoi/run_after_create-windows-junctions.ps1.tmpl" > "$rendered_script" + if [[ "$profile" == windows ]]; then + if ! grep -q 'mutable\\nvim' "$rendered_script" \ + || ! grep -q 'mutable\\cava' "$rendered_script" \ + || ! grep -q 'CHEZMOI_WINDOWS_APPDATA' "$rendered_script" \ + || ! grep -q 'CHEZMOI_WINDOWS_DOCUMENTS' "$rendered_script" \ + || ! grep -q 'mutable\\shared\\zed' "$rendered_script"; then + printf '%s\n' 'Windows link script is incomplete' >&2 + exit 1 + fi + elif grep -q '[^[:space:]]' "$rendered_script"; then + printf 'Windows junction script rendered for profile: %s\n' "$profile" >&2 + exit 1 + fi + + source_path="$(chezmoi --source "$repo_root" --config "$rendered" source-path)" + if [[ "$source_path" != "$repo_root/chezmoi" ]]; then + printf 'unexpected source root: %s\n' "$source_path" >&2 + exit 1 + fi + + mkdir -p "$temp_dir/home-$profile" + managed_file="$temp_dir/managed-$profile" + chezmoi \ + --source "$repo_root" \ + --config "$rendered" \ + --destination "$temp_dir/home-$profile" \ + managed \ + --include files,symlinks \ + --path-style relative > "$managed_file" + + while IFS=$'\t' read -r row_profile target owner mode _source; do + [[ "$row_profile" == "$profile" ]] || continue + [[ "$mode" == junction || "$mode" == native-link ]] && continue + + is_managed=false + while IFS= read -r managed_target; do + if [[ "$managed_target" == "$target" || "$managed_target" == "$target/"* ]]; then + is_managed=true + break + fi + done < "$managed_file" + + if [[ "$owner" == chezmoi && "$is_managed" != true ]]; then + printf 'chezmoi target is missing for %s: %s\n' "$profile" "$target" >&2 + exit 1 + fi + if [[ "$owner" != chezmoi && "$is_managed" == true ]]; then + printf 'non-chezmoi target is managed for %s: %s\n' "$profile" "$target" >&2 + exit 1 + fi + done < "$ownership_file" + + chezmoi \ + --source "$repo_root" \ + --config "$rendered" \ + --destination "$temp_dir/home-$profile" \ + --no-tty \ + --dry-run \ + apply + + chezmoi \ + --source "$repo_root" \ + --config "$rendered" \ + --destination "$temp_dir/home-$profile" \ + --exclude scripts \ + --no-tty \ + apply + + if [[ "$profile" == windows ]]; then + codex_config="$temp_dir/home-$profile/.codex/config.toml" + printf '\n# preserve-existing-config\n' >> "$codex_config" + chezmoi \ + --source "$repo_root" \ + --config "$rendered" \ + --destination "$temp_dir/home-$profile" \ + --exclude scripts \ + --force \ + --no-tty \ + apply + if ! grep -q '# preserve-existing-config' "$codex_config"; then + printf '%s\n' 'chezmoi overwrote the existing Windows Codex config' >&2 + exit 1 + fi + fi + + claude_settings="$temp_dir/home-$profile/.claude/settings.json" + if [[ ! -f "$claude_settings" ]]; then + printf 'Claude settings were not rendered for profile: %s\n' "$profile" >&2 + exit 1 + fi + case "$profile" in + windows) + if ! grep -q '%USERPROFILE%.*ccwin-hook.ps1' "$claude_settings"; then + printf '%s\n' 'Windows Claude hooks were not rendered' >&2 + exit 1 + fi + if grep -Eq 'C:\\Users\\(HP|takow)' "$temp_dir/home-$profile/.config/yasb/config.yaml"; then + printf '%s\n' 'YASB contains a hard-coded user profile' >&2 + exit 1 + fi + ;; + nixos) + if ! grep -q 'claude-notify-hook.sh' "$claude_settings"; then + printf '%s\n' 'NixOS Claude hooks were not rendered' >&2 + exit 1 + fi + ;; + wsl) + if grep -q '"hooks"' "$claude_settings"; then + printf '%s\n' 'WSL Claude settings unexpectedly contain hooks' >&2 + exit 1 + fi + ;; + esac +done diff --git a/scripts/check_profiles.sh b/scripts/check_profiles.sh new file mode 100644 index 0000000..ef5d94b --- /dev/null +++ b/scripts/check_profiles.sh @@ -0,0 +1,55 @@ +#!/usr/bin/env bash + +set -euo pipefail + +flake="${1:-.}" + +expect() { + local expression=$1 + local expected=$2 + local actual + actual="$(nix eval "$flake#$expression" --raw)" + if [[ "$actual" != "$expected" ]]; then + printf 'profile contract failed: %s (expected %s, got %s)\n' "$expression" "$expected" "$actual" >&2 + exit 1 + fi +} + +expect nixosConfigurations.wsl.config.home-manager.users.t4ko.home.sessionVariables.EDITOR vim +expect nixosConfigurations.laptop.config.home-manager.users.t4ko.home.sessionVariables.EDITOR nvim +expect nixosConfigurations.laptop.config.networking.hostName laptop +expect nixosConfigurations.desktop.config.networking.hostName desktop +expect nixosConfigurations.wsl.config.networking.hostName nixos-wsl +expect nixosConfigurations.nixos-ci.config.networking.hostName nixos + +nix eval "$flake#nixosConfigurations.wsl.config.home-manager.users.t4ko.home.packages" \ + --apply 'packages: assert builtins.any (package: (package.pname or "") == "vim") packages; "ok"' \ + --raw >/dev/null + +nix eval "$flake#nixosConfigurations.nixos-ci.config.home-manager.users.t4ko.home.packages" \ + --apply 'packages: assert !(builtins.any (package: (package.pname or "") == "brave") packages); "ok"' \ + --raw >/dev/null + +for host in laptop desktop; do + nix eval "$flake#nixosConfigurations.$host.config.home-manager.users.t4ko.programs.nixvim.enable" \ + --apply 'enabled: assert enabled; "ok"' --raw >/dev/null + nix eval "$flake#nixosConfigurations.$host.config.home-manager.users.t4ko.xdg.configFile" \ + --apply 'files: assert builtins.hasAttr "niri/config.kdl" files; assert builtins.hasAttr "swaync/config.json" files; assert builtins.hasAttr "waybar/config" files; assert !builtins.hasAttr "fastfetch" files; assert !builtins.hasAttr "lazygit" files; assert !builtins.hasAttr "starship.toml" files; assert !builtins.hasAttr "vim" files; assert !builtins.hasAttr "wezterm" files; assert !builtins.hasAttr "yazi" files; assert !builtins.hasAttr "zed" files; "ok"' \ + --raw >/dev/null + nix eval "$flake#nixosConfigurations.$host.config.home-manager.users.t4ko.home.file" \ + --apply 'files: assert !builtins.hasAttr ".claude/CLAUDE.md" files; assert !builtins.hasAttr ".claude/settings.json" files; assert !builtins.hasAttr ".codex/AGENTS.md" files; assert !builtins.hasAttr ".gitconfig" files; assert !builtins.hasAttr ".git_template/hooks" files; "ok"' \ + --raw >/dev/null +done + +nix eval "$flake#nixosConfigurations.wsl.config.home-manager.users.t4ko.programs.nixvim.enable" \ + --apply 'enabled: assert !enabled; "ok"' --raw >/dev/null + +codex_seed="$(nix eval "$flake#nixosConfigurations.laptop.config.home-manager.users.t4ko.home.activation.seedCodexConfig.data" --raw)" +if [[ "$codex_seed" != *'/dotfiles/chezmoi/.chezmoitemplates/codex-config.toml'* ]]; then + printf '%s\n' 'Codex seed does not use the chezmoi template source' >&2 + exit 1 +fi +if [[ "$codex_seed" != *'[ -L "$codex_cfg" ] || [ ! -e "$codex_cfg" ]'* ]]; then + printf '%s\n' 'Codex seed does not preserve an existing regular config file' >&2 + exit 1 +fi diff --git a/scripts/check_wsl.sh b/scripts/check_wsl.sh new file mode 100644 index 0000000..35d3a6d --- /dev/null +++ b/scripts/check_wsl.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env bash + +set -euo pipefail + +repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +flake_ref="${1:-$repo_root}" + +assert_json() { + local attribute=$1 + local expected=$2 + local actual + + actual="$(nix eval "$flake_ref#nixosConfigurations.wsl.config.$attribute" --json)" + if [[ "$actual" != "$expected" ]]; then + printf '%s: expected %s, got %s\n' "$attribute" "$expected" "$actual" >&2 + exit 1 + fi +} + +assert_json wsl.enable true +assert_json wsl.defaultUser '"t4ko"' +assert_json home-manager.users.t4ko.home.username '"t4ko"' +assert_json home-manager.users.t4ko.home.homeDirectory '"/home/t4ko"' +assert_json home-manager.users.t4ko.home.sessionVariables.EDITOR '"vim"' +assert_json home-manager.users.t4ko.programs.neovim.enable false + +home_packages="$( + nix eval \ + "$flake_ref#nixosConfigurations.wsl.config.home-manager.users.t4ko.home.packages" \ + --apply 'packages: map (package: package.pname or package.name) packages' \ + --json +)" +for desktop_package in ghostty wezterm zed-editor; do + if [[ "$home_packages" == *"\"$desktop_package\""* ]]; then + printf 'desktop package is present in WSL: %s\n' "$desktop_package" >&2 + exit 1 + fi +done + +nix build "$flake_ref#nixosConfigurations.wsl.config.system.build.toplevel" diff --git a/scripts/optim_pwsh_profile.ps1 b/scripts/optim_pwsh_profile.ps1 deleted file mode 100644 index 2ec4a0a..0000000 --- a/scripts/optim_pwsh_profile.ps1 +++ /dev/null @@ -1,70 +0,0 @@ -# モジュール分割されたプロファイルを1ファイルにインライン展開し、 -# コメント・空行を除去して高速化した $PROFILE を書き出す。 -# setup_windows.ps1 から呼ばれる。 - -param( - [Parameter(Mandatory = $false)] - [string]$SourcePath, - [Parameter(Mandatory = $false)] - [string]$OutputPath -) - -$ErrorActionPreference = "Stop" - -if (-not $SourcePath) { - $repo = Split-Path -Parent $PSScriptRoot - $SourcePath = Join-Path $repo ".config/windows/powershell/Microsoft.PowerShell_profile.ps1" -} -if (-not $OutputPath) { - $OutputPath = $PROFILE -} - -if (-not (Test-Path -LiteralPath $SourcePath)) { - Write-Error "Source profile not found: $SourcePath" -} - -$sourceDir = Split-Path -Parent $SourcePath -# Windows PowerShell 5.1 / PowerShell 7 のどちらから呼ばれても日本語コメントが -# 文字化けして次行と連結されないよう、BOM なし UTF-8 を .NET API で直接読み書き -# する (Get-Content -Encoding UTF8 は PS 5.1 で BOM を期待し、BOM なしを誤読する)。 -function Read-Utf8Text([string]$Path) { - [System.IO.File]::ReadAllText($Path, [System.Text.UTF8Encoding]::new($false)) -} -$content = Read-Utf8Text $SourcePath - -# dot-source 行を対象ファイルの中身でインライン展開する -# パターン: . "$modulesDir\foo.ps1" → modules/foo.ps1 を読み込み -$content = [regex]::Replace($content, '^\.\s+"?\$modulesDir\\([^"]+)"?\s*$', { - param($m) - $modulePath = Join-Path $sourceDir "conf.d/$($m.Groups[1].Value)" - if (Test-Path -LiteralPath $modulePath) { - Read-Utf8Text $modulePath - } else { - Write-Warning "Module not found, skipping: $modulePath" - "" - } -}, [System.Text.RegularExpressions.RegexOptions]::Multiline) - -# $modulesDir 定義行を除去(インライン展開後は不要) -$content = $content -replace '(?m)^\$modulesDir\s*=.*$', '' - -# ブロックコメント除去 -$content = $content -replace '(?s)<#.*?#>', '' - -# 行コメント・空行を除去 -$lines = $content -split "`r?`n" -$kept = $lines | ForEach-Object { - $t = $_.Trim() - if ($t -eq '') { return $null } - if ($t.StartsWith('#')) { return $null } - $_ -} | Where-Object { $null -ne $_ } - -$output = ($kept -join "`n").Trim() -# 出力先ディレクトリが無いと WriteAllText が失敗する -$outputDir = Split-Path -Parent $OutputPath -if ($outputDir -and -not (Test-Path -LiteralPath $outputDir)) { - New-Item -ItemType Directory -Path $outputDir -Force | Out-Null -} -[System.IO.File]::WriteAllText($OutputPath, $output, [System.Text.UTF8Encoding]::new($false)) -Write-Host "Wrote optimized profile ($($kept.Count) lines): $OutputPath" diff --git a/scripts/setup_windows.ps1 b/scripts/setup_windows.ps1 deleted file mode 100644 index a3c86d7..0000000 --- a/scripts/setup_windows.ps1 +++ /dev/null @@ -1,236 +0,0 @@ -$ErrorActionPreference = "Stop" - -$repo = Split-Path -Parent $PSScriptRoot -$homeDir = [Environment]::GetFolderPath("UserProfile") -$localDir = [Environment]::GetFolderPath("LocalApplicationData") -$roamingDir = [Environment]::GetFolderPath("ApplicationData") -$scriptsDir = Join-Path $repo "scripts" - -# Src: repo からの相対パス -# Dst: 相対パス → $homeDir 基準、絶対パス → そのまま使用 -$targets = @( - @{ Src = ".gitconfig"; Dst = ".gitconfig" }, - # Claude: 共通ファイルは個別リンク。settings.json は base+hooks を後段でマージ生成する。 - @{ Src = ".config/shared/claude/CLAUDE.md"; Dst = ".claude/CLAUDE.md" }, - @{ Src = ".config/shared/claude/agents"; Dst = ".claude/agents" }, - @{ Src = ".config/shared/claude/skills"; Dst = ".claude/skills" }, - @{ Src = ".config/shared/claude/statusline.sh"; Dst = ".claude/statusline.sh" }, - @{ Src = ".config/shared/claude/claude-icon.svg"; Dst = ".claude/claude-icon.svg" }, - @{ Src = ".config/windows/claude/ccwin-hook.ps1"; Dst = ".claude/ccwin-hook.ps1" }, - @{ Src = ".config/shared/codex"; Dst = ".codex" }, - @{ Src = ".config/shared/lazygit"; Dst = ".config/lazygit" }, - @{ Src = ".config/shared/mise"; Dst = ".config/mise" }, - @{ Src = ".config/shared/nvim"; Dst = (Join-Path $localDir "nvim") }, - @{ Src = ".config/shared/vim"; Dst = ".config/vim" }, - @{ Src = ".config/shared/wezterm"; Dst = ".config/wezterm" }, - @{ Src = ".config/shared/yazi"; Dst = (Join-Path $roamingDir "yazi\config") }, - @{ Src = ".config/shared/starship.toml"; Dst = ".config/starship.toml" }, - @{ Src = ".config/shared/fastfetch"; Dst = ".config/fastfetch" }, - @{ Src = ".config/windows/ccwin-notify"; Dst = ".config/ccwin-notify" }, - @{ Src = ".config/windows/yasb"; Dst = ".config/yasb" }, - @{ Src = ".config/windows/cava"; Dst = ".config/cava" }, - @{ Src = ".config/windows/komorebi/komorebi.json"; Dst = "komorebi.json" }, - @{ Src = ".config/windows/komorebi/komorebi.bar.json"; Dst = "komorebi.bar.json" }, - @{ Src = ".config/windows/komorebi/applications.json"; Dst = "applications.json" }, - @{ Src = ".config/windows/whkdrc"; Dst = ".config/whkdrc" }, - @{ Src = ".config/shared/vscode/settings.json"; Dst = (Join-Path $roamingDir "Code\User\settings.json") }, - @{ Src = ".config/shared/vscode/keybindings.json"; Dst = (Join-Path $roamingDir "Code\User\keybindings.json") }, - @{ Src = ".config/shared/vscode/snippets"; Dst = (Join-Path $roamingDir "Code\User\snippets") }, - @{ Src = ".config/shared/zed/settings.json"; Dst = (Join-Path $roamingDir "Zed\settings.json") }, - @{ Src = ".config/shared/zed/keymap.json"; Dst = (Join-Path $roamingDir "Zed\keymap.json") }, - @{ Src = ".config/shared/zed/tasks.json"; Dst = (Join-Path $roamingDir "Zed\tasks.json") } -) - -function Remove-ExistingPath($path) { - if (-not (Test-Path -LiteralPath $path)) { - return $true - } - - # Replace any existing path (file/dir/link) so setup always converges - try { - Remove-Item -LiteralPath $path -Force -Recurse -ErrorAction Stop - } catch { - # 過去に管理者で作られた壊れた reparse point は Remove-Item が Access denied になる。 - # cmd /c rmdir|del は別経路で reparse point を消せるため最終フォールバックに使う。 - if (Test-Path -LiteralPath $path -PathType Container) { - Get-ChildItem -LiteralPath $path -Recurse -Force | Sort-Object { $_.FullName.Length } -Descending | ForEach-Object { - try { Remove-Item -LiteralPath $_.FullName -Force -ErrorAction Stop } catch { - Write-Host "Warning: Skipped locked file: $($_.FullName)" -ForegroundColor Yellow - } - } - try { Remove-Item -LiteralPath $path -Force -ErrorAction Stop } catch { - & cmd.exe /c "rmdir /S /Q `"$path`"" 2>&1 | Out-Null - } - } else { - & cmd.exe /c "del /F /Q `"$path`"" 2>&1 | Out-Null - } - if (Test-Path -LiteralPath $path) { - Write-Host "Warning: Could not remove path: $path" -ForegroundColor Yellow - return $false - } - } - return $true -} - -function New-Link($src, $dst, $isDir) { - if ($isDir) { - # Use junction for directories on Windows to avoid symlink privilege requirements. - New-Item -ItemType Junction -Path $dst -Target $src | Out-Null - return - } - - # Developer Mode 無効 + 非管理者で SymbolicLink を作ると、`l` フラグだけ立った - # 解決不能な reparse point が残ることがある (実害: os.Stat で Access denied)。 - # 作成直後に LinkType/Target が解決できなければ巻き戻し、HardLink → Copy の順で再試行する。 - try { - New-Item -ItemType SymbolicLink -Path $dst -Target $src -ErrorAction Stop | Out-Null - $created = Get-Item -LiteralPath $dst -Force - if (-not $created.LinkType -or -not $created.Target) { - Remove-Item -LiteralPath $dst -Force -ErrorAction SilentlyContinue - throw "SymbolicLink created but unresolvable" - } - return - } catch { - Write-Host "SymbolicLink failed ($($_.Exception.Message)), trying HardLink: $dst" -ForegroundColor Yellow - } - - try { - New-Item -ItemType HardLink -Path $dst -Target $src -ErrorAction Stop | Out-Null - return - } catch { - Write-Host "HardLink failed ($($_.Exception.Message)), falling back to Copy: $dst" -ForegroundColor Yellow - } - - Copy-Item -LiteralPath $src -Destination $dst -Force -} - -# 旧 setup は .claude をディレクトリ junction にしていた。ファイル単位リンクへ移行するため、 -# reparse point (junction/symlink) なら先に除去する。junction 内のファイルを個別 Remove すると -# リンク先 (repo) を破壊するため、この事前除去が必須。 -$claudeHome = Join-Path $homeDir ".claude" -$claudeItem = Get-Item -LiteralPath $claudeHome -Force -ErrorAction SilentlyContinue -if ($claudeItem -and ($claudeItem.Attributes -band [IO.FileAttributes]::ReparsePoint)) { - Remove-ExistingPath -path $claudeHome | Out-Null -} - -foreach ($entry in $targets) { - $src = Join-Path $repo $entry.Src - if (-not (Test-Path $src)) { - Write-Host "Skip missing source: $src" - continue - } - - # Dst が絶対パスならそのまま、相対パスなら $homeDir 基準 - if ([System.IO.Path]::IsPathRooted($entry.Dst)) { - $dst = $entry.Dst - } else { - $dst = Join-Path $homeDir $entry.Dst - } - - $dstParent = Split-Path -Parent $dst - if (-not (Test-Path $dstParent)) { - New-Item -ItemType Directory -Path $dstParent -Force | Out-Null - } - - if (-not (Remove-ExistingPath -path $dst)) { - continue - } - - $srcItem = Get-Item $src -Force - New-Link -src $src -dst $dst -isDir $srcItem.PSIsContainer - Write-Host "Linked: $dst -> $src" -} - -# Claude settings.json: 共通 base に Windows 固有 hooks をマージして生成する。 -# (Linux/Nix 側は base をそのまま生成。hooks は Windows 専用のため setup でのみ合成) -$claudeBase = Join-Path $repo ".config/shared/claude/settings.json" -$claudeHooks = Join-Path $repo ".config/windows/claude/settings.hooks.json" -$claudeDst = Join-Path $homeDir ".claude/settings.json" -if ((Test-Path $claudeBase) -and (Test-Path $claudeHooks)) { - Remove-ExistingPath -path $claudeDst | Out-Null - $claudeParent = Split-Path -Parent $claudeDst - if (-not (Test-Path $claudeParent)) { - New-Item -ItemType Directory -Path $claudeParent -Force | Out-Null - } - $base = Get-Content -LiteralPath $claudeBase -Raw | ConvertFrom-Json - $hooks = Get-Content -LiteralPath $claudeHooks -Raw | ConvertFrom-Json - $base | Add-Member -NotePropertyName hooks -NotePropertyValue $hooks.hooks -Force - $base | ConvertTo-Json -Depth 100 | Set-Content -LiteralPath $claudeDst -Encoding UTF8 - Write-Host "Generated: $claudeDst (shared base + windows hooks)" -} else { - Write-Host "Skip Claude settings merge: missing base or hooks fragment" -ForegroundColor Yellow -} - -# PowerShell profile: modules/ をjunctionでリンクし、プロファイルは最適化版を生成 -$profileSrc = Join-Path $repo ".config/windows/powershell" -$documentsDir = [Environment]::GetFolderPath("MyDocuments") -$profileDst = Join-Path $documentsDir "PowerShell" -if (Test-Path -LiteralPath $profileSrc) { - # 旧setupのディレクトリjunction等を除去してからクリーンに再構築 - Remove-ExistingPath -path $profileDst | Out-Null - New-Item -ItemType Directory -Path $profileDst -Force | Out-Null - - # modules/ ディレクトリをjunctionでリンク(Terminal-Icons等が参照可能になる) - $modulesSrc = Join-Path $profileSrc "modules" - $modulesDst = Join-Path $profileDst "modules" - if (Test-Path -LiteralPath $modulesSrc) { - New-Link -src $modulesSrc -dst $modulesDst -isDir $true - Write-Host "Linked: $modulesDst -> $modulesSrc" - } - - # conf.d をインライン展開した最適化プロファイルを $PROFILE に書き出す - $optimScript = Join-Path $scriptsDir "optim_pwsh_profile.ps1" - $profileOut = Join-Path $profileDst "Microsoft.PowerShell_profile.ps1" - & $optimScript -SourcePath (Join-Path $profileSrc "Microsoft.PowerShell_profile.ps1") -OutputPath $profileOut -} else { - Write-Host "Skip missing PowerShell profile source: $profileSrc" -} - -# Git hooks: core.hooksPath で参照するディレクトリにリンク -$hooksSrc = Join-Path $repo ".git_template/hooks" -if (Test-Path -LiteralPath $hooksSrc) { - $hooksDst = Join-Path $homeDir ".git_template/hooks" - if (-not (Remove-ExistingPath -path $hooksDst)) { - Write-Host "Warning: Could not update hooks directory" -ForegroundColor Yellow - } else { - New-Link -src $hooksSrc -dst $hooksDst -isDir $true - Write-Host "Linked: $hooksDst -> $hooksSrc" - } -} - -Write-Host "Git template setup completed." - -# Ensure dotfiles scripts dir is available from PATH in all shells. -$userPath = [Environment]::GetEnvironmentVariable("Path", "User") -$pathItems = @() -if (-not [string]::IsNullOrWhiteSpace($userPath)) { - $pathItems = $userPath -split ";" -} - -if ($pathItems -notcontains $scriptsDir) { - if ([string]::IsNullOrWhiteSpace($userPath)) { - $newUserPath = $scriptsDir - } else { - $newUserPath = "$userPath;$scriptsDir" - } - [Environment]::SetEnvironmentVariable("Path", $newUserPath, "User") - $env:Path = "$env:Path;$scriptsDir" - Write-Host "Added to user PATH: $scriptsDir" -} else { - Write-Host "Already in user PATH: $scriptsDir" -} - -# mise trust & install(未実行の場合のみ) -if (Get-Command "mise" -ErrorAction SilentlyContinue) { - $miseConfig = Join-Path $repo "mise.toml" - if (Test-Path $miseConfig) { - Write-Host "`n=== mise setup ===" -ForegroundColor White - mise trust $miseConfig - mise install - } -} else { - Write-Host "mise が見つかりません。bootstrap.ps1 を先に実行してください。" -ForegroundColor Yellow -} - -Write-Host "Windows setup completed." -ForegroundColor Green -& pwsh