Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
b55522e
docs: README を英語で書き直す
gapul Sep 2, 2026
59582e8
docs: NIXOS_WSL / terminal-browser-vimkeys / minecraft を英語にする
gapul Sep 2, 2026
3933646
docs: HOMESERVER_TODO を英語にする
gapul Sep 2, 2026
b1a42ed
docs: homelab-roadmap を英語にする
gapul Sep 2, 2026
2750a3f
docs: self-build-software を英語にする
gapul Sep 2, 2026
8be891d
docs: windows-roadmap を英語にする
gapul Sep 2, 2026
f315c26
docs: HOMELAB を英語にする
gapul Sep 2, 2026
66b07d9
docs: NIXOS_DUALBOOT を英語にする
gapul Sep 2, 2026
44db67a
docs: HOMESERVER_MIGRATION を英語にする
gapul Sep 2, 2026
b3daceb
docs: CHEATSHEET を英語にする
gapul Sep 3, 2026
ad221a2
docs: 小さめの README 6 本を英語にする
gapul Sep 3, 2026
5a76ca9
docs: nix/homelab・configs/apps・omniwm・scoop の README を英語にする
gapul Sep 3, 2026
7a8a7c2
docs: windows の README 3 本を英語にする
gapul Sep 3, 2026
a6933b4
docs: windows/autohotkey・privacy の README を英語にする
gapul Sep 3, 2026
e4aede8
docs: windows/SETUP-CHECKLIST を英語にする
gapul Sep 3, 2026
8452381
docs: obsidian・skk・esphome の README を英語にする
gapul Sep 3, 2026
f608875
docs: adguard・forgejo の README を英語にする
gapul Sep 3, 2026
4da94bb
docs: restic の README を英語にする
gapul Sep 3, 2026
59ddb06
docs: keyball39・macmini の README を英語にする
gapul Sep 3, 2026
7eca657
docs: hermes の README を英語にする
gapul Sep 3, 2026
102b97e
docs: popo 引き継ぎメモを英語にする
gapul Sep 3, 2026
99ea200
docs: mobile の README を英語にする
gapul Sep 3, 2026
a755b78
docs: android の README を英語にする
gapul Sep 3, 2026
e135359
docs: ios の README を英語にする
gapul Sep 3, 2026
65afbb7
docs: claude 設定の README を英語にする
gapul Sep 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
242 changes: 129 additions & 113 deletions README.md

Large diffs are not rendered by default.

47 changes: 25 additions & 22 deletions configs/apps/README.md
Original file line number Diff line number Diff line change
@@ -1,33 +1,36 @@
# GUI アプリ plist 管理
# GUI application plists

menubar / 入力系ユーティリティの設定を home-manager activation で復元する。
Puddle は websites(壁紙)と security-scoped bookmark を壊さないよう、
enforce したいキーのみ `defaults write`(surgical)。
Restoring the settings of menubar and input utilities through home-manager activation.

## 管理対象
Puddle is handled surgically — only the keys worth enforcing are written with
`defaults write` — so that its websites, meaning the wallpapers, and its security-scoped
bookmarks are not destroyed.

| App | 方式 | 説明 |
## What is managed

| App | Method | Notes |
|---|---|---|
| **Puddle** | surgical write (`nix/home/darwin.nix`) | 動的壁紙。websites/bookmark はライブ保持し全置換しない。behavior 3 キー(deactivateOnBattery / extendPuddleBelowMenuBar / showOnAllSpaces)のみ enforce |
| Puddle | Surgical writes, in `nix/home/darwin.nix` | Dynamic wallpaper. websites and bookmarks stay live and are never wholesale replaced. Only three behaviour keys are enforced: deactivateOnBattery, extendPuddleBelowMenuBar and showOnAllSpaces |

## menubar アイコンの表示/非表示
## Hiding and showing menubar icons

`NSStatusItem VisibleCC Item-*` = false で「アイコンを隠す」状態を管理対象に含める
(Maccy)。rebuild の import で隠し状態が表示に戻らないよう明示保持する。
位置キー `NSStatusItem Preferred Position*` は端末固有なので除外する。
`NSStatusItem VisibleCC Item-*` set to false is what "hide this icon" means, and it is managed
here for Maccy. Keeping it explicit stops a rebuild's import from making hidden icons visible
again. The position keys, `NSStatusItem Preferred Position*`, are machine-specific and are
excluded.

## 新 Mac での復元
## Restoring on a new Mac

`just rebuild`(home-manager activation)で Puddle の behavior 3 キーが
`defaults write` される。以下は GUI で手動:
`just rebuild`, through home-manager activation, writes Puddle's three behaviour keys. The rest
is done by hand in the GUI.

### Puddle
- 壁紙は `puddle apply` で入る(`~/.config/puddle/install.toml` の `wallpapers`)。
シェーダ本体は dotfiles ではなく gapul/puddle-shaders にあり、
`~/Library/Application Support/Puddle/Wallpapers/` へ展開される。
ここに残るのはワークスペース連動の inputs(実行時状態)だけ。
For Puddle, the wallpapers come from `puddle apply`, driven by `wallpapers` in
`~/.config/puddle/install.toml`. The shaders themselves are not in dotfiles; they are in
gapul/puddle-shaders and are unpacked into
`~/Library/Application Support/Puddle/Wallpapers/`. What stays here is only the
workspace-linked inputs, which are runtime state.

## 設定変更後の capture
## Capturing a change

Puddle plist を持たない(surgical write)。behavior を変えたら
`nix/modules/home/darwin-apps.nix` の puddlePrefs 内 `defaults write` を直接編集する。
Puddle has no plist here, since it is written surgically. After changing a behaviour, edit the
`defaults write` calls inside `puddlePrefs` in `nix/modules/home/darwin-apps.nix` directly.
14 changes: 8 additions & 6 deletions configs/apps/codexbar/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
# CodexBar 設定
# CodexBar configuration

`~/.config/codexbar/config.json` の実体です。out-of-store symlink で繋いであるので、
CodexBar の UI 操作がそのままこのファイルに書き込まれる。[omniwm](../../wm/omniwm/README.md) と同じ扱い。
This is the real `~/.config/codexbar/config.json`, linked in as an out-of-store symlink, so
anything changed through CodexBar's UI is written straight back here. Handled the same way as
[omniwm](../../wm/omniwm/README.md).

- 配線は `nix/home/darwin.nix`。新しい mac では rebuild すればリンクが張られる。
- `providers[].codexActiveSource` に Codex アカウントの UUID が入る。このリポジトリは public だが、
識別子だけで資格情報ではないのでそのまま追跡している。
The wiring is in `nix/home/darwin.nix`, so a rebuild on a new Mac creates the link.

`providers[].codexActiveSource` holds the UUID of the Codex account. This repository is public,
but that is an identifier rather than a credential, so it stays tracked.
35 changes: 21 additions & 14 deletions configs/apps/obsidian/README.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,26 @@
# Obsidian 設定スナップショット (追跡専用ミラー)
# Obsidian configuration snapshot, a tracking mirror only

このディレクトリは Obsidian の `.obsidian` 設定の **片方向スナップショット** です。
This directory is a one-way snapshot of Obsidian's `.obsidian` configuration.

- **本体は vault 側** (`~/Documents/notes/.obsidian`)。ここは履歴・差分閲覧用の**読み取りミラー**。
- 更新は `just obsidian-snapshot` で **vault → dotfiles の一方通行**。
逆向き (dotfiles → vault) には**絶対に**戻さない(戻すと二重オーナーになり同期が壊れる)。
- 日々の同期は Obsidian Git / Self-hosted LiveSync が担当。dotfiles は中身を所有しない。
The real thing lives in the vault, at `~/Documents/notes/.obsidian`. What is here is a
read-only mirror, for history and diffs.

## 公開リポジトリ前提の安全設計
It is updated with `just obsidian-snapshot`, which goes from the vault into dotfiles and never
the other way. Copying back would create two owners and break the sync.

このリポジトリは public。よって:
Day-to-day syncing is Obsidian Git and Self-hosted LiveSync's job. dotfiles does not own the
contents.

- **ホワイトリスト方式**: 安全と確認した json のみ収録
(`app` `appearance` `hotkeys` `community-plugins` `core-plugins` `graph` `daily-notes` `types` `canvas`)。
- **絶対に入れない**: `plugins/*/data.json`(LiveSync の CouchDB 認証・各種 API キーが入りうる)、
`workspace*.json`(端末状態)、`copilot-index-*` / `.smart-env`(キャッシュ)、プラグイン本体。
- `just obsidian-snapshot` は非空の秘密値を検出すると**中止**する。さらに commit 前に `gitleaks` を通す。
- 秘密ごと版管理したい設定は **sops 暗号化** (`just secrets` / `.sops.yaml`) してから置く。
## Designed for a public repository

This repository is public, so:

- Only files confirmed to be safe are included, by whitelist: `app`, `appearance`, `hotkeys`,
`community-plugins`, `core-plugins`, `graph`, `daily-notes`, `types` and `canvas`.
- Some things are never included: `plugins/*/data.json`, which can hold LiveSync's CouchDB
credentials and various API keys; `workspace*.json`, which is per-device state;
`copilot-index-*` and `.smart-env`, which are caches; and the plugins themselves.
- `just obsidian-snapshot` aborts if it finds a non-empty secret value, and `gitleaks` runs
before the commit as well.
- Configuration that has to be versioned along with its secrets is encrypted with sops first,
through `just secrets` and `.sops.yaml`.
175 changes: 91 additions & 84 deletions configs/cli/claude/README.md
Original file line number Diff line number Diff line change
@@ -1,108 +1,115 @@
# Claude Code

母艦とリモート (nssh 先) で持ち方が違う。
Held differently on the Mac and on remote machines reached through nssh.

## 母艦 — まるごと symlink
## On the Mac, symlinked wholesale

`nix/home/workstation.nix` out-of-store symlink を張っていて、ここにあるファイルが実体。
`nix/home/workstation.nix` creates out-of-store symlinks, so the files here are the real thing.

| 実体 | リンク先 |
| The real file | Linked to |
| --- | --- |
| `settings.json` | `$CLAUDE_CONFIG_DIR/settings.json` |
| `CLAUDE.md` | `$CLAUDE_CONFIG_DIR/CLAUDE.md` |
| `hooks/` `output-styles/` `bin/` | 同名のディレクトリ |
| `skills/{english-vocab,gapul-writing-voice,step-by-step-tutor}` | `skills/` の下 |
| `hooks/`, `output-styles/`, `bin/` | The directories of the same name |
| `skills/{english-vocab,gapul-writing-voice,step-by-step-tutor}` | Under `skills/` |

`settings.json` をまるごと持てるのは、母艦が `defaultMode: bypassPermissions` で
`permissions.allow` が育たないから。TUI からの書き戻しはそのままこのファイルに落ちるので、
`git diff` に出てきたらコミットすればいい。
Keeping the whole `settings.json` works because the Mac runs with
`defaultMode: bypassPermissions`, so `permissions.allow` never grows. Anything the TUI writes
back lands in this file, and when it shows up in `git diff` it can simply be committed.

セッション履歴・`.claude.json` (資格情報)・`settings.local.json` は state なので持たない。
vendored な skill (cloudflare/* など) も上流から取り直せるので管理しない。
Session history, `.claude.json`, which holds credentials, and `settings.local.json` are state
and are not kept. Vendored skills, such as cloudflare's, can be fetched again from upstream and
are not managed either.

## リモート (nssh 先) — 管理キーだけ merge
## On remote machines, merging only the managed keys

`settings.remote.json` の**管理キーだけ**を、ホストの既存 JSON へ
`scripts/merge-claude-settings.py` が上書き merge する。`~/.bashrc` に `bashrc.remote` を読む
行だけ足すのと同じ考え方で、管理外のキーはホスト側にそのまま残す。
`scripts/merge-claude-settings.py` merges only the managed keys from `settings.remote.json`
over whatever JSON the host already has. It is the same idea as adding a single line to
`~/.bashrc` that sources `bashrc.remote`: anything unmanaged stays as the host had it.

| | キー |
| | Keys |
| --- | --- |
| 管理対象 | `permissions.defaultMode` / `theme` / `effortLevel` / `editorMode` / `verbose` / `preferredNotifChannel` / `skipDangerousModePermissionPrompt` / `skipWorkflowUsageWarning` / `environmentVariables` |
| 管理外 (ホスト所有) | `permissions.allow` / `permissions.additionalDirectories` / `enabledPlugins` / `hooks` |

管理対象は**母艦の `settings.json` が実際に持っているキー**に限る。母艦が書いていない
キーを配ると、母艦は既定値・リモートだけ明示値という食い違いが生まれ、下の「母艦が正」
が成り立たなくなる。`tui` / `inputNeededNotifEnabled` / `agentPushNotifEnabled` は
リモート側の値から起こしてしまったもので、母艦に無いので外した (2026-08-13)。
既に配ってしまったホストの値は残るが、以後はホスト所有として扱う。

### なぜ母艦のように丸ごと symlink にしないのか

`defaultMode: bypassPermissions` を配った時点で `permissions.allow` は育たなくなるので、
「symlink にすると承認済みの許可が毎回消える」という元の理由は消えた (2026-08-15)。
それでも merge のままなのは、母艦の `settings.json` に**リモートへ持って行くと壊れる/
意味が無いキー**が混ざっているため。

- `hooks` — `/Users/gapul/.config/claude/hooks/*.sh` という絶対パス。Linux では存在しない
ので毎回失敗する。リモートは自前のフック (herdr 連携) を持っている
- `enabledPlugins` — 母艦は clangd / swift LSP。この箱に要るのは rust-analyzer で、
配ると入れ替わってしまう。ツールチェーンはホストごとに違うので触らない
- `extraKnownMarketplaces` — 上の plugin とセットでしか意味が無いので外す
- `disableDeepLinkRegistration` — macOS の `~/Applications` URL ハンドラの話で Linux には無い
- `defaultModel` — 母艦は `claude-sonnet-4-20250514` を固定している。これを配ると
リモートの既定モデルまで巻き戻る。**意図的に外している**ので、揃えたくなったら
ここに書き足すのではなく先に母艦側の固定を見直すこと

### 入れ子の扱い

`permissions` は `defaultMode` だけを管理する。merge は両側が object のキーだけ再帰する
ので、ホストが育てた `allow` / `additionalDirectories` は残る。配列は再帰しない
(`allow` を要素ごとに混ぜたいわけではない)。`--check` と `--adopt` も同じ構造をなぞる。

### bypassPermissions を配ることの意味

リモートでも Claude Code が権限確認なしで動く。共有機に入れる場合は、その箱で
Claude に許されることが自分のアカウントでできること全部になる、という前提で使う。

`CLAUDE.md` と自作 skill は書き換わらないので、リモートでも普通に symlink する。
`hooks/` `output-styles/` `bin/` は母艦のデスクトップ前提 (osascript 通知 / herdr /
Notion MCP) なので持ち込まない。

このスクリプトを母艦の `settings.json` へ向けてはいけない。書き込みが tmp+rename なので、
nix が張った symlink を実ファイルで置き換えて追跡を切る。母艦では `--adopt` (読むだけ) の
向きでのみ使う。

## どちらが勝つか — クライアント端末が正

管理キーの値は接続元の母艦を正とする。リモートで設定をいじっても、それはそのホスト限りの
一時的なものとして次の merge で上書きされる。値の更新は母艦から吸い上げる向きで行う。
| Managed | `permissions.defaultMode`, `theme`, `effortLevel`, `editorMode`, `verbose`, `preferredNotifChannel`, `skipDangerousModePermissionPrompt`, `skipWorkflowUsageWarning`, `environmentVariables` |
| Unmanaged, owned by the host | `permissions.allow`, `permissions.additionalDirectories`, `enabledPlugins`, `hooks` |

The managed set is limited to keys the Mac's own `settings.json` actually contains.
Distributing a key the Mac does not set would leave the Mac on the default while the remote had
an explicit value, which breaks the rule below that the Mac is authoritative. `tui`,
`inputNeededNotifEnabled` and `agentPushNotifEnabled` had been lifted from a remote machine's
values rather than the Mac's, and were removed on 2026-08-13. The values already distributed
stay where they are, and are treated as host-owned from now on.

### Why not symlink it the way the Mac does

Once `defaultMode: bypassPermissions` was distributed, `permissions.allow` stopped growing, so
the original reason — that symlinking would wipe accumulated approvals every time — went away
on 2026-08-15. It stays a merge because the Mac's `settings.json` contains keys that either
break or mean nothing on a remote machine.

- `hooks` — absolute paths like `/Users/gapul/.config/claude/hooks/*.sh`, which do not exist on
Linux and fail every time. Remote machines have their own hooks, integrated with herdr.
- `enabledPlugins` — the Mac has clangd and the Swift LSP. What a given box needs is
rust-analyzer, and distributing this would replace it. Toolchains differ per host, so it is
left alone.
- `extraKnownMarketplaces` — only meaningful together with those plugins, so it goes too.
- `disableDeepLinkRegistration` — a macOS `~/Applications` URL handler thing, with no Linux
equivalent.
- `defaultModel` — the Mac pins `claude-sonnet-4-20250514`. Distributing it would roll the
remote's default model back too. Leaving it out is deliberate; if they should match, revisit
the pin on the Mac first rather than adding it here.

### Nesting

Only `defaultMode` inside `permissions` is managed. The merge recurses only where both sides
have an object, so `allow` and `additionalDirectories` as the host grew them survive. Arrays are
not recursed into, since merging `allow` element by element is not the intent. `--check` and
`--adopt` follow the same structure.

### What distributing bypassPermissions means

Claude Code runs on the remote machine without asking for permission. On a shared machine, use
it on the understanding that whatever Claude is allowed to do there is everything your account
can do.

`CLAUDE.md` and the hand-written skills are never rewritten, so they are symlinked on remote
machines as normal. `hooks/`, `output-styles/` and `bin/` assume the Mac's desktop —
notifications through osascript, herdr, the Notion MCP — and are not carried across.

Never point this script at the Mac's own `settings.json`. It writes through a temporary file and
a rename, which would replace the symlink nix created with a real file and break tracking. On
the Mac, use it only in the `--adopt` direction, which just reads.

## Which side wins: the client machine

For the managed keys, the Mac you connect from is authoritative. Changing a setting on a remote
machine is temporary, local to that host, and gets overwritten by the next merge. Updates travel
in the other direction, pulled up from the Mac:

```
just claude-settings-adopt # 母艦の現在値を settings.remote.json へ取り込む
just claude-settings-adopt # pull the Mac's current values into settings.remote.json
```

吸い上げるのは `settings.remote.json` が既に持っている管理キーだけで、キーの集合は増えない
(`permissions` を巻き込まないため)。新しく管理したいキーがあるときは、先に
`settings.remote.json` へそのキーを手で足してから `adopt` を走らせる。
It pulls only the managed keys `settings.remote.json` already has; the set never grows, so that
`permissions` is not swept in. To manage a new key, add it to `settings.remote.json` by hand
first, then run `adopt`.

## theme = auto とライト/ダーク追従
## theme = auto, and following light and dark

`auto` TUI 上の表示が "Auto (match terminal)" で、**OS ではなく端末**を見る。
実装は端末への OSC 11 (背景色問い合わせ) の応答 `rgb:RRRR/GGGG/BBBB` を読み、
取れないときは `COLORFGBG` にフォールバックする。
`auto` appears in the TUI as "Auto (match terminal)", and it watches the terminal rather than
the OS. It sends OSC 11 to ask for the background colour, reads the `rgb:RRRR/GGGG/BBBB` reply,
and falls back to `COLORFGBG` when there is no answer.

つまり ssh 越しでも、応答するのは母艦の ghostty なので**そのまま追従する**。
`nix/lib/theme.nix` の dark/light 2 端点や `theme-watch` のような side channel
Claude には要らない。
That means it follows correctly even over ssh, because what answers is ghostty on the Mac.
Claude needs neither the two dark and light endpoints in `nix/lib/theme.nix` nor a side channel
like `theme-watch`.

ただし tmux の内側では OSC 11 に応答するのが tmux 自身になるため、外側の ghostty まで
問い合わせが届くかは tmux のバージョン依存。ここは nvim `&background` 自動判定と同じ
制約で、`configs/editors/nvim/lua/plugins/auto-dark-mode.lua` の OSC 111 に関する
コメントも参照。
Inside tmux, though, tmux itself answers the OSC 11, so whether the query reaches the outer
ghostty depends on the tmux version. This is the same constraint nvim's automatic `&background`
detection has; see the comments about OSC 111 in
`configs/editors/nvim/lua/plugins/auto-dark-mode.lua`.

## 適用
## Applying it

- 母艦: `just rebuild`
- リモート: `nssh <host>`
- 手で: `python3 scripts/merge-claude-settings.py ~/.claude/settings.json`
- On the Mac: `just rebuild`
- On a remote machine: `nssh <host>`
- By hand: `python3 scripts/merge-claude-settings.py ~/.claude/settings.json`
Loading
Loading