Compare commits

..

18 Commits

Author SHA1 Message Date
9bfc7702ae feat(scripts): add x-gitprofile for mise enter hook git-profile switching
Creates .mise.toml files with enter hooks that auto-switch git
profiles when entering project directories (e.g. ~/Code/ivuorinen,
~/Code/masf).
2026-03-20 22:23:07 +02:00
9c90d48372 docs(claude): document new hooks, skills, and context-mode 2026-03-20 21:56:31 +02:00
a20f21c8b3 feat(claude): add scaffolding and validation skills 2026-03-20 21:56:02 +02:00
a285e01601 feat(claude): register dotbot-validate and config-warn hooks 2026-03-20 21:55:49 +02:00
5d8baea825 feat(claude): add dotbot-validate and config-warn hooks 2026-03-20 21:55:37 +02:00
73ef292bd9 feat(claude): block edits to submodule paths in pre-edit hook 2026-03-20 21:54:39 +02:00
72934232d9 fix(git): use PATH-resolved gh in credential helper 2026-03-20 21:54:24 +02:00
4ca473b11c chore(git): allow .claude directory to be tracked in this repo 2026-03-20 21:54:14 +02:00
10cc23f471 fix(fish): fix code block indentation in secrets.d README
Change 3-space to 4-space indentation in ordered list code blocks
to satisfy the markdown-table-formatter's multiple-of-2 rule.
2026-03-20 04:38:46 +02:00
c17b4d6a8b docs(claude): improve CLAUDE.md with mise, secrets.d, and cleanup
Add mise tool manager section to Architecture. Add secrets.d gotcha
documenting the auto-source pattern. Remove duplicated context-mode
boilerplate block (already in global CLAUDE.md). Unpin Yarn version.
2026-03-20 04:38:35 +02:00
cff83e4738 refactor(claude): migrate hooks to external scripts and add new hooks
Replace inline command strings in settings.json with external scripts
in .claude/hooks/ for readability and maintainability. Consolidate
three PostToolUse formatters into one script and add markdown/yaml
formatting. Add new hooks: SessionStart context banner, Stop lint
gate, async Bats test runner, idle desktop notification, and
PostToolUseFailure logger.
2026-03-20 04:38:18 +02:00
2b867c3348 chore(serena): update project configuration
Auto-generated Serena project config update.
2026-03-20 04:23:06 +02:00
301ded44f3 refactor(mise): simplify tool management config
Simplify mise activate call in exports (remove dynamic shell
detection). Update mise/config.toml for current tool configuration.
Add brew autoremove step to cleanup script after removing old version
managers.
2026-03-20 04:21:33 +02:00
3a1461a647 fix(fish): guard nvim aliases and add eza fallbacks
Guard vim/vi → nvim aliases with type -q nvim check so they only
activate when nvim is installed. Add ls/ll/l/lsa fallbacks when eza
is not installed. Add brew shellenv fish eval in config.fish.
2026-03-20 04:21:10 +02:00
f2a3ae9a4b feat(fish): add secrets.d for secret env vars
Add config/fish/secrets.d/ directory pattern to .gitignore while
allowing *.example and README.md through. Add README and example file
documenting the secrets convention. Source secrets.d/*.fish files in
exports.fish so secret environment variables are loaded automatically.
2026-03-20 04:20:51 +02:00
98394f1220 refactor(go): remove goenv configs, use mise for Go
Delete goenv config files as goenv is superseded by mise for Go
version management. Clean up Go env vars in fish exports: drop
set -q guards and remove GOROOT export.
2026-03-20 04:20:20 +02:00
066207ef45 chore(homebrew): update Brewfile dependencies
Extensive Brewfile reorganization: adds new taps (anchore/grype,
caarlos0/tap, dagger/tap, ivuorinen/tap, jesseduffield/lazygit,
k8sgpt-ai/k8sgpt, snyk/tap), removes homebrew/bundle and
homebrew/services taps. Adds php@8.1, dotnet@8, kcov, libpq,
python@3.13, codeql, ungoogled-chromium and updated PHP extensions.
Removes git-crypt, ccusage, exercism, katana, languagetool, legitify,
telnet, xdg-ninja, tabby, reviewdog and others. Deletes now-unused
stub git-crypt install scripts.
2026-03-20 04:19:32 +02:00
renovate[bot]
2cdcac2a65 chore(deps): update dependency go (1.25.5 → 1.26.1) (#313)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-03-19 08:46:29 +02:00
33 changed files with 853 additions and 196 deletions

13
.claude/hooks/async-bats.sh Executable file
View File

@@ -0,0 +1,13 @@
#!/usr/bin/env bash
# Async Bats runner: run matching test file when a script is edited.
# Runs in background (async: true) — output appears on next turn.
fp=$(jq -r '.tool_input.file_path // empty')
[ -z "$fp" ] && exit 0
name=$(basename "$fp")
test_file="$CLAUDE_PROJECT_DIR/tests/${name}.bats"
[ ! -f "$test_file" ] && exit 0
echo "Running $test_file ..."
"$CLAUDE_PROJECT_DIR/node_modules/.bin/bats" "$test_file"

14
.claude/hooks/log-failures.sh Executable file
View File

@@ -0,0 +1,14 @@
#!/usr/bin/env bash
# PostToolUseFailure logger: append tool failures to a local log file.
log_file="$CLAUDE_PROJECT_DIR/.claude/hook-failures.log"
entry=$(jq -c '{
time: (now | strftime("%Y-%m-%dT%H:%M:%SZ")),
tool: .tool_name,
error: .error
}')
echo "$entry" >> "$log_file"
exit 0

13
.claude/hooks/notify-idle.sh Executable file
View File

@@ -0,0 +1,13 @@
#!/usr/bin/env bash
# Notification hook: alert when Claude goes idle.
# Uses pushover if available, falls back to macOS native notification.
msg=$(jq -r '.message // "Claude is waiting for input"')
if command -v pushover > /dev/null; then
pushover "Claude Code" "$msg"
elif command -v osascript > /dev/null; then
osascript -e "display notification \"$msg\" with title \"Claude Code\""
fi
exit 0

View File

@@ -0,0 +1,15 @@
#!/usr/bin/env bash
# Post-edit: warn when formatter/linter configs are changed,
# since they affect the entire repo's code style.
fp=$(jq -r '.tool_input.file_path // empty')
[ -z "$fp" ] || [ ! -f "$fp" ] && exit 0
case "$(basename "$fp")" in
.editorconfig | biome.json | .prettierrc.json | .shellcheckrc | stylua.toml | .yamllint.yml)
echo "NOTE: Formatter/linter config changed ($fp)." >&2
echo "Run 'pre-commit run --all-files' to verify consistency." >&2
;;
esac
exit 0

View File

@@ -0,0 +1,28 @@
#!/usr/bin/env bash
# Post-edit: validate Dotbot install.conf.yaml files after editing.
# Checks YAML syntax and verifies link targets exist.
fp=$(jq -r '.tool_input.file_path // empty')
[ -z "$fp" ] || [ ! -f "$fp" ] && exit 0
case "$fp" in
*install.conf.yaml) ;;
*) exit 0 ;;
esac
# YAML syntax check
if command -v yamllint > /dev/null; then
if ! output=$(yamllint -d relaxed "$fp" 2>&1); then
echo "Dotbot config YAML error in $fp:" >&2
echo "$output" >&2
exit 2
fi
elif command -v python3 > /dev/null; then
if ! output=$(python3 -c "import yaml; yaml.safe_load(open('$fp'))" 2>&1); then
echo "Dotbot config YAML parse error in $fp:" >&2
echo "$output" >&2
exit 2
fi
fi
exit 0

View File

@@ -0,0 +1,30 @@
#!/usr/bin/env bash
# Post-edit formatter: auto-format file based on extension.
# Receives tool output JSON on stdin.
fp=$(jq -r '.tool_input.file_path // empty')
[ -z "$fp" ] || [ ! -f "$fp" ] && exit 0
case "$fp" in
*.sh | */bin/*)
head -1 "$fp" | grep -qE '^#!.*(ba)?sh' \
&& command -v shfmt > /dev/null \
&& shfmt -i 2 -bn -ci -sr -fn -w "$fp"
;;
*.fish)
command -v fish_indent > /dev/null && fish_indent -w "$fp"
;;
*.lua)
command -v stylua > /dev/null && stylua "$fp"
;;
*.md)
command -v biome > /dev/null && biome format --write "$fp" 2> /dev/null
command -v markdown-table-formatter > /dev/null \
&& markdown-table-formatter "$fp" 2> /dev/null
;;
*.yml | *.yaml)
command -v prettier > /dev/null && prettier --write "$fp" 2> /dev/null
;;
esac
exit 0

35
.claude/hooks/pre-edit-block.sh Executable file
View File

@@ -0,0 +1,35 @@
#!/usr/bin/env bash
# Pre-edit guard: block vendor/lock files and secrets.d real fish files.
# Receives tool input JSON on stdin.
fp=$(jq -r '.tool_input.file_path // empty')
[ -z "$fp" ] && exit 0
case "$fp" in
*/fzf-tmux | */yarn.lock | */.yarn/*)
echo "BLOCKED: $fp is a vendor/lock file — do not edit directly" >&2
exit 2
;;
*/tools/dotbot/* | */tools/dotbot-include/* | */tools/antidote/*)
echo "BLOCKED: $fp is inside a git submodule — do not edit" >&2
exit 2
;;
*/config/tmux/plugins/*)
echo "BLOCKED: $fp is a tmux plugin submodule — do not edit" >&2
exit 2
;;
*/config/cheat/cheatsheets/community/* | */config/cheat/cheatsheets/tldr/*)
echo "BLOCKED: $fp is a cheat submodule — do not edit" >&2
exit 2
;;
*/secrets.d/*.fish)
case "$(basename "$fp")" in
*.example.fish | *.fish.example) exit 0 ;;
esac
echo "BLOCKED: do not edit $fp directly — it is gitignored." >&2
echo "Copy the matching .fish.example file and edit that locally." >&2
exit 2
;;
esac
exit 0

View File

@@ -0,0 +1,15 @@
#!/usr/bin/env bash
# SessionStart context: print branch, dirty file count, and last commit.
cd "$CLAUDE_PROJECT_DIR" || exit 0
branch=$(git branch --show-current 2> /dev/null)
dirty=$(git status --short 2> /dev/null | wc -l | tr -d ' ')
last=$(git log -1 --oneline 2> /dev/null)
echo "=== Dotfiles session context ==="
echo "Branch : ${branch:-unknown}"
echo "Dirty : ${dirty} file(s)"
echo "Last : ${last}"
exit 0

16
.claude/hooks/stop-lint-gate.sh Executable file
View File

@@ -0,0 +1,16 @@
#!/usr/bin/env bash
# Stop gate: run yarn lint before Claude finishes.
# Exit 2 sends feedback back and keeps Claude working.
cd "$CLAUDE_PROJECT_DIR" || exit 0
output=$(yarn lint 2>&1)
status=$?
if [ $status -ne 0 ]; then
echo "Lint failed — fix before finishing:" >&2
echo "$output" >&2
exit 2
fi
exit 0

View File

@@ -1,12 +1,23 @@
{
"hooks": {
"SessionStart": [
{
"hooks": [
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/session-start-context.sh",
"statusMessage": "Loading project context..."
}
]
}
],
"PreToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "fp=$(cat | jq -r '.tool_input.file_path // empty') && [ -n \"$fp\" ] && case \"$fp\" in */fzf-tmux|*/yarn.lock|*/.yarn/*) echo \"BLOCKED: $fp is a vendor/lock file — do not edit directly\" >&2; exit 2;; esac; exit 0"
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/pre-edit-block.sh"
}
]
}
@@ -17,15 +28,57 @@
"hooks": [
{
"type": "command",
"command": "fp=$(cat | jq -r '.tool_input.file_path // empty') && [ -n \"$fp\" ] && [ -f \"$fp\" ] && case \"$fp\" in *.sh|*/bin/*) head -1 \"$fp\" | grep -qE '^#!.*(ba)?sh' && command -v shfmt > /dev/null && shfmt -i 2 -bn -ci -sr -fn -w \"$fp\";; esac; exit 0"
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/post-edit-format.sh",
"statusMessage": "Formatting..."
},
{
"type": "command",
"command": "fp=$(cat | jq -r '.tool_input.file_path // empty') && [ -n \"$fp\" ] && [ -f \"$fp\" ] && case \"$fp\" in *.fish) command -v fish_indent > /dev/null && fish_indent -w \"$fp\";; esac; exit 0"
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/post-edit-dotbot-validate.sh",
"statusMessage": "Validating Dotbot config..."
},
{
"type": "command",
"command": "fp=$(cat | jq -r '.tool_input.file_path // empty') && [ -n \"$fp\" ] && [ -f \"$fp\" ] && case \"$fp\" in *.lua) command -v stylua > /dev/null && stylua \"$fp\";; esac; exit 0"
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/post-edit-config-warn.sh"
},
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/async-bats.sh",
"async": true,
"statusMessage": "Running tests..."
}
]
}
],
"PostToolUseFailure": [
{
"hooks": [
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/log-failures.sh",
"async": true
}
]
}
],
"Notification": [
{
"matcher": "idle_prompt",
"hooks": [
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/notify-idle.sh",
"async": true
}
]
}
],
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/stop-lint-gate.sh",
"statusMessage": "Running lint gate..."
}
]
}

View File

@@ -0,0 +1,38 @@
---
name: dotbot-validate
description: >-
Validate Dotbot install.conf.yaml files after editing.
Apply when writing or modifying any install.conf.yaml.
user-invocable: false
allowed-tools: Bash, Read
---
After editing any `install.conf.yaml` file, validate it:
## 1. YAML syntax
```bash
yamllint -d relaxed <file>
```
If yamllint is not available, fall back to:
```bash
python3 -c "import yaml; yaml.safe_load(open('<file>'))"
```
## 2. Link target verification
For each `link` entry, verify the source path exists relative
to the repo root. Report any missing source files.
## 3. Host-specific configs
Files in `hosts/<hostname>/install.conf.yaml` overlay the
global config. Verify that any `include` directives reference
existing files.
## Key locations
- `install.conf.yaml` — global config
- `hosts/*/install.conf.yaml` — per-host overlays

View File

@@ -0,0 +1,58 @@
---
name: host-override
description: >-
Create or extend host-specific config overlays
in hosts/<hostname>/ for machine-specific settings.
user-invocable: true
allowed-tools: Bash, Read, Write, Edit
---
When creating host-specific configuration overrides:
## 1. Determine hostname
```bash
hostname -s
```
## 2. Directory structure
Host overrides live in `hosts/<hostname>/` mirroring the
global layout:
```
hosts/<hostname>/
base/ -> ~/.*
config/ -> ~/.config/
install.conf.yaml
```
## 3. Create install.conf.yaml
If it doesn't exist, create `hosts/<hostname>/install.conf.yaml`
following the Dotbot format. Use `include` to layer on top of
the global config:
```yaml
- defaults:
link:
create: true
relink: true
force: true
```
## 4. Git config overrides
The most common override is `hosts/<hostname>/config/git/overrides/config`.
This is where host-specific git user, signing keys, and credential
helpers go. Always `[include]` the shared config:
```ini
[include]
path = ~/.dotfiles/config/git/shared
```
## 5. Test
Run `./install` to apply. Dotbot processes
`hosts/<hostname>/install.conf.yaml` after the global config.

View File

@@ -0,0 +1,40 @@
---
name: new-fish-function
description: >-
Scaffold a new fish function in config/fish/functions/
with proper conventions and event handling.
user-invocable: true
allowed-tools: Bash, Read, Write, Edit
---
When creating a new fish function in `config/fish/functions/`:
## 1. Create the function file
Create `config/fish/functions/<name>.fish`:
```fish
function <name> --description '<one-line description>'
# Function logic here
end
```
- One function per file, filename must match function name
- Always include `--description`
- Use `--argument-names` for named parameters
## 2. Conventions
- Do NOT use `_tide_` prefix (reserved for tide prompt plugin)
- Use `--wraps` if the function wraps an existing command
- For abbreviation-like functions, prefer fish abbreviations
in `config/fish/alias.fish` instead
## 3. Validate
Run the fish-validate skill checks:
```bash
fish --no-execute config/fish/functions/<name>.fish
fish_indent --check config/fish/functions/<name>.fish
```

View File

@@ -0,0 +1,53 @@
---
name: new-script
description: >-
Scaffold a new helper script in local/bin/ with proper
boilerplate, msgr sourcing, and documentation tag.
user-invocable: true
allowed-tools: Bash, Read, Write, Edit
---
When creating a new script in `local/bin/`, follow this template:
## 1. Script file
Create `local/bin/<name>` with:
```bash
#!/usr/bin/env bash
# @description <one-line description>
set -euo pipefail
# shellcheck source=msgr
. "$(dirname "$0")/msgr"
# Script logic here
```
- Use `msgr` functions for output: `msgr msg`, `msgr run`,
`msgr yay`, `msgr err`, `msgr warn`
- The `@description` tag is required — `dfm scripts` discovers
scripts by it
- POSIX scripts (`/bin/sh`) should NOT source msgr
## 2. Make executable
```bash
chmod +x local/bin/<name>
```
## 3. Generate docs
Run `dfm docs script <name>` or manually create `local/bin/<name>.md`
with a usage summary.
## 4. Validate
Run the shell-validate skill checks (syntax + shellcheck).
## Naming conventions
- `x-` prefix for standalone utilities (e.g., `x-ssl-expiry-date`)
- Short names for frequently used commands (e.g., `a`, `ad`, `ae`)
- `git-` prefix for git subcommands (e.g., `git-dirty`)

9
.gitignore vendored
View File

@@ -29,6 +29,9 @@ config/fish/completions/kubectl.fish
config/fish/completions/orbctl.fish
config/fish/fish_variables
config/fish/fish_variables.*
config/fish/secrets.d/*
!config/fish/secrets.d/*.example
!config/fish/secrets.d/README.md
config/gh/hosts.yml
config/git/credentials
config/git/local.d/*
@@ -61,3 +64,9 @@ node_modules
__pycache__
ssh/local.d/*
config/fish/fish_variables*
# Allow .claude directory (overrides global **/.claude/* ignore)
!.claude/
!.claude/**
.claude/**/*.log
.claude/settings.local.json

View File

@@ -1,4 +1,4 @@
[tools]
node = "24.14.0"
python = "3.14.3"
go = "1.25.5"
go = "1.26.1"

View File

@@ -1,10 +1,4 @@
# language of the project (csharp, python, rust, java, typescript, go, cpp, or ruby)
# * For C, use cpp
# * For JavaScript, use typescript
# Special requirements:
# * csharp: Requires the presence of a .sln file in the project folder.
language: bash
---
# whether to use the project's gitignore file to ignore files
# Added on 2025-04-07
ignore_all_files_in_gitignore: true
@@ -86,5 +80,81 @@ excluded_tools: []
# initial prompt for the project. It will always be given to the LLM upon activating the project
# (contrary to the memories, which are loaded on demand).
initial_prompt: ""
# the name by which the project can be referenced within Serena
project_name: ".dotfiles"
# list of tools to include that would otherwise be disabled (particularly optional tools that are disabled by default).
# This extends the existing inclusions (e.g. from the global configuration).
included_optional_tools: []
# fixed set of tools to use as the base tool set (if non-empty), replacing Serena's default set of tools.
# This cannot be combined with non-empty excluded_tools or included_optional_tools.
fixed_tools: []
# list of mode names to that are always to be included in the set of active modes
# The full set of modes to be activated is base_modes + default_modes.
# If the setting is undefined, the base_modes from the global configuration (serena_config.yml) apply.
# Otherwise, this setting overrides the global configuration.
# Set this to [] to disable base modes for this project.
# Set this to a list of mode names to always include the respective modes for this project.
base_modes:
# list of mode names that are to be activated by default.
# The full set of modes to be activated is base_modes + default_modes.
# If the setting is undefined, the default_modes from the global configuration (serena_config.yml) apply.
# Otherwise, this overrides the setting from the global configuration (serena_config.yml).
# This setting can, in turn, be overridden by CLI parameters (--mode).
default_modes:
# time budget (seconds) per tool call for the retrieval of additional symbol information
# such as docstrings or parameter information.
# This overrides the corresponding setting in the global configuration; see the documentation there.
# If null or missing, use the setting from the global configuration.
symbol_info_budget:
# The language backend to use for this project.
# If not set, the global setting from serena_config.yml is used.
# Valid values: LSP, JetBrains
# Note: the backend is fixed at startup. If a project with a different backend
# is activated post-init, an error will be returned.
language_backend:
# line ending convention to use when writing source files.
# Possible values: unset (use global setting), "lf", "crlf", or "native" (platform default)
# This does not affect Serena's own files (e.g. memories and configuration files), which always use native line endings.
line_ending:
# list of regex patterns which, when matched, mark a memory entry as readonly.
# Extends the list from the global configuration, merging the two lists.
read_only_memory_patterns: []
# the encoding used by text files in the project
# For a list of possible encodings, see https://docs.python.org/3.11/library/codecs.html#standard-encodings
encoding: utf-8
# list of languages for which language servers are started; choose from:
# al bash clojure cpp csharp
# csharp_omnisharp dart elixir elm erlang
# fortran fsharp go groovy haskell
# java julia kotlin lua markdown
# matlab nix pascal perl php
# php_phpactor powershell python python_jedi r
# rego ruby ruby_solargraph rust scala
# swift terraform toml typescript typescript_vts
# vue yaml zig
# (This list may be outdated. For the current list, see values of Language enum here:
# https://github.com/oraios/serena/blob/main/src/solidlsp/ls_config.py
# For some languages, there are alternative language servers, e.g. csharp_omnisharp, ruby_solargraph.)
# Note:
# - For C, use cpp
# - For JavaScript, use typescript
# - For Free Pascal/Lazarus, use pascal
# Special requirements:
# Some languages require additional setup/installations.
# See here for details: https://oraios.github.io/serena/01-about/020_programming-languages.html#language-servers
# When using multiple languages, the first language server that supports a given file will be used for that file.
# The first language is the default language and the respective language server will be used as a fallback.
# Note that when using the JetBrains backend, language servers are not used and this list is correspondingly ignored.
languages:
- bash
- lua

View File

@@ -98,6 +98,13 @@ and most scripts in `local/bin/`.
- `dfm scripts` — run scripts from `scripts/` (discovered via `@description` tags)
- `dfm tests` — test visualization helpers
### mise — Unified Tool Manager
`config/mise/config.toml` manages language runtimes (Node LTS, Python 3,
Go latest, Rust stable) and CLI tools (fd, ripgrep, eza, neovim, delta,
zoxide, etc.). Activated via `eval "$(mise activate bash)"` in
`config/exports`. Run `mise install` after adding new tools.
### Submodules
External dependencies are git submodules (Dotbot, plugins,
@@ -148,33 +155,50 @@ SC2174 (mkdir -p -m), SC2016 (single-quote expressions).
and excluded from prettier (see `.prettierignore`).
- **Python**: Two scripts (`x-compare-versions.py`,
`x-git-largest-files.py`) linted by Ruff (config in `pyproject.toml`).
- **Fish secrets**: `config/fish/secrets.d/*.fish` files are auto-sourced
by `exports.fish`. Copy `github.fish.example``github.fish` for local
secrets. These files are gitignored; only `*.example` and `README.md`
are tracked.
## Claude Code Configuration
- **Hooks** (`.claude/settings.json`):
- *PreToolUse*: Blocks edits to `fzf-tmux`, `yarn.lock`, `.yarn/`
- *PostToolUse*: Auto-runs `shfmt` on shell scripts after Edit/Write
- *PostToolUse*: Auto-runs `fish_indent` on `.fish` files after Edit/Write
- *PostToolUse*: Auto-runs `stylua` on `.lua` files after Edit/Write
- *PreToolUse*: Blocks edits to `fzf-tmux`, `yarn.lock`,
`.yarn/`, submodule paths, and real secrets.d files
- *PostToolUse*: Auto-formats files by extension
(shfmt, fish_indent, stylua, biome, prettier)
- *PostToolUse*: Validates Dotbot `install.conf.yaml`
after edits
- *PostToolUse*: Warns on formatter/linter config changes
- *Stop*: Runs `yarn lint` gate before finishing
- **Skills** (`.claude/skills/`):
- `shell-validate`: Auto-validates shell scripts (syntax + shellcheck)
- `fish-validate`: Auto-validates fish scripts (syntax + fish_indent)
- `shell-validate`: Auto-validates shell scripts
(syntax + shellcheck)
- `fish-validate`: Auto-validates fish scripts
(syntax + fish_indent)
- `lua-format`: Auto-formats Lua files with stylua
- `yaml-validate`: Auto-validates YAML files (yamllint + actionlint)
- `yaml-validate`: Auto-validates YAML files
(yamllint + actionlint)
- `dotbot-validate`: Validates Dotbot install.conf.yaml
- `new-script`: Scaffolds helper scripts in local/bin/
- `new-fish-function`: Scaffolds fish functions
- `host-override`: Creates host-specific config overlays
- **Subagents** (`.claude/agents/`):
- `code-reviewer`: Reviews shell/fish/lua changes for correctness and style
- **MCP Servers**:
- `context7`: Live documentation lookup for tools and libraries
- `code-reviewer`: Reviews shell/fish/lua changes
- **Plugins** (required):
- `context-mode`: Context window protection — must be
installed for this repo. See routing rules below.
- `context7`: Live documentation lookup
## Package Manager
Yarn (v4.12.0) is the package manager. Do not use npm.
Yarn (v4+) is the package manager. Do not use npm.
# context-mode — MANDATORY routing rules
You have context-mode MCP tools available. These rules are NOT optional —
they protect your context window from flooding.
A single unrouted command can dump 56 KB into context and waste the entire session.
they protect your context window from flooding. A single unrouted command
can dump 56 KB into context and waste the entire session.
## BLOCKED commands — do NOT attempt these
@@ -185,9 +209,9 @@ Instead use:
- `ctx_execute(language: "javascript", code: "const r = await fetch(...)")` to run HTTP calls in sandbox
### Inline HTTP — BLOCKED
Any Bash command containing `fetch('http`, `requests.get(`, `requests.post(`,
`http.get(`, or `http.request(` is intercepted and replaced with an error message.
Do NOT retry with Bash.
Any Bash command containing `fetch('http`, `requests.get(`,
`requests.post(`, `http.get(`, or `http.request(` is intercepted
and replaced with an error message. Do NOT retry with Bash.
Instead use:
- `ctx_execute(language, code)` to run HTTP calls in sandbox — only stdout enters context
@@ -199,8 +223,7 @@ Instead use:
## REDIRECTED tools — use sandbox equivalents
### Bash (>20 lines output)
Bash is ONLY for: `git`, `mkdir`, `rm`, `mv`, `cd`, `ls`, `yarn install`, `pip install`,
and other short-output commands.
Bash is ONLY for: `git`, `mkdir`, `rm`, `mv`, `cd`, `ls`, `npm install`, `pip install`, and other short-output commands.
For everything else, use:
- `ctx_batch_execute(commands, queries)` — run multiple commands + search in ONE call
- `ctx_execute(language: "shell", code: "...")` — run in sandbox, only stdout enters context
@@ -208,42 +231,41 @@ For everything else, use:
### Read (for analysis)
If you are reading a file to **Edit** it → Read is correct (Edit needs content in context).
If you are reading to **analyze, explore, or summarize**
use `ctx_execute_file(path, language, code)` instead.
Only your printed summary enters context. The raw file content stays in the sandbox.
use `ctx_execute_file(path, language, code)` instead. Only your
printed summary enters context. The raw file stays in the sandbox.
### Grep (large results)
Grep results can flood context.
Use `ctx_execute(language: "shell", code: "grep ...")` to run searches in sandbox.
Only your printed summary enters context.
Use `ctx_execute(language: "shell", code: "grep ...")` to run
searches in sandbox. Only your printed summary enters context.
## Tool selection hierarchy
1. **GATHER**: `ctx_batch_execute(commands, queries)` — Primary tool.
Runs all commands, auto-indexes output, returns search results.
ONE call replaces 30+ individual calls.
1. **GATHER**: `ctx_batch_execute(commands, queries)` — Primary
tool. Runs all commands, auto-indexes output, returns search
results. ONE call replaces 30+ individual calls.
2. **FOLLOW-UP**: `ctx_search(queries: ["q1", "q2", ...])`
Query indexed content. Pass ALL questions as array in ONE call.
3. **PROCESSING**: `ctx_execute(language, code)` |
`ctx_execute_file(path, language, code)`
Sandbox execution. Only stdout enters context.
`ctx_execute_file(path, language, code)` Sandbox execution.
Only stdout enters context.
4. **WEB**: `ctx_fetch_and_index(url, source)` then
`ctx_search(queries)` — Fetch, chunk, index, query.
Raw HTML never enters context.
5. **INDEX**: `ctx_index(content, source)`
Store content in FTS5 knowledge base for later search.
5. **INDEX**: `ctx_index(content, source)` Store content in FTS5 knowledge base for later search.
## Subagent routing
When spawning subagents (Agent/Task tool), the routing block is automatically
injected into their prompt. Bash-type subagents are upgraded to general-purpose
so they have access to MCP tools.
When spawning subagents (Agent/Task tool), the routing block is
automatically injected into their prompt. Bash-type subagents are
upgraded to general-purpose so they have access to MCP tools.
You do NOT need to manually instruct subagents about context-mode.
## Output constraints
- Keep responses under 500 words.
- Write artifacts (code, configs, PRDs) to FILES — never return them
as inline text. Return only: file path + 1-line description.
- Write artifacts (code, configs, PRDs) to FILES — never return
them as inline text. Return only: file path + 1-line description.
- When indexing content, use descriptive source labels so others can `ctx_search(source: "label")` later.
## ctx commands

View File

@@ -503,7 +503,7 @@ export SQLITE_HISTORY="${XDG_CACHE_HOME}/sqlite_history"
# mise — unified tool version manager
# https://mise.jdx.dev
if command -v mise &> /dev/null; then
eval "$(mise activate "$(basename "${SHELL:-bash}")")"
eval "$(mise activate bash)"
fi
if [ -f "$XDG_CONFIG_HOME/exports-secret" ]; then source "$XDG_CONFIG_HOME/exports-secret"; fi

View File

@@ -1,7 +1,9 @@
# Set aliases for fish shell
if type -q nvim
alias vim='nvim'
alias vi='nvim'
end
# eza aliases if eza is installed
if type -q eza >/dev/null
@@ -31,6 +33,19 @@ if type -q eza >/dev/null
function l --wraps='eza_git' --description eza
eza_git $argv
end
else
function ls --description 'ls (system fallback)'
command ls $argv
end
function ll --description 'ls -lh (system fallback)'
command ls -lh $argv
end
function l --description 'ls (system fallback)'
command ls $argv
end
function lsa --description 'ls -lah (system fallback)'
command ls -lah $argv
end
end
# Edit fish alias file
@@ -130,4 +145,6 @@ alias x-datetime="date +'%Y-%m-%d %H:%M:%S'"
alias x-timestamp="date +'%s'"
# Random abbreviations
if type -q onefetch
abbr --add stats onefetch --nerd-fonts --true-color never
end

View File

@@ -52,3 +52,4 @@ source ~/.orbstack/shell/init2.fish 2>/dev/null || :
if status is-interactive; and not set -q GITHUB_TOKEN
echo "Warning: GITHUB_TOKEN is not set" >&2
end
eval "$(/opt/homebrew/bin/brew shellenv fish)"

View File

@@ -97,8 +97,9 @@ set -q FZF_DEFAULT_OPTS; or set -x FZF_DEFAULT_OPTS \
set -q GNUPGHOME; or set -x GNUPGHOME "$XDG_DATA_HOME/gnupg"
# Go configuration
set -q GOPATH; or set -x GOPATH "$XDG_DATA_HOME/go"
set -q GOBIN; or set -x GOBIN "$XDG_BIN_HOME"
set -x GOPATH "$XDG_DATA_HOME/go"
set -x GOBIN "$XDG_BIN_HOME"
set -e GOROOT
# 1Password configuration
set -q OP_CACHE; or set -x OP_CACHE "$XDG_STATE_HOME/1password"
@@ -179,6 +180,15 @@ if test -f "$DOTFILES/hosts/$HOSTNAME/config/fish/exports-secret.fish"
source "$DOTFILES/hosts/$HOSTNAME/config/fish/exports-secret.fish"
end
# Source secret environment variables from secrets.d directory
if test -d "$DOTFILES/config/fish/secrets.d"
for secret_file in "$DOTFILES/config/fish/secrets.d"/*.fish
if test -f "$secret_file"
source "$secret_file"
end
end
end
# Configure tide prompt
set -gx tide_prompt_transient_enabled true
set -gx tide_prompt_add_newline_before true

View File

@@ -0,0 +1,72 @@
# Fish Shell Secrets Directory
This directory contains sensitive environment variables like API tokens and credentials.
## Usage
1. Copy an example file (e.g., `github.fish.example`) to remove the `.example` suffix:
```bash
cp github.fish.example github.fish
```
2. Edit the file and replace placeholder values with your actual secrets:
```bash
$EDITOR github.fish
```
3. Reload your fish shell or source the exports:
```fish
source ~/.config/fish/exports.fish
```
## Adding New Secret Files
Create a new `.fish` file in this directory with your environment variables:
```fish
# Example: openai.fish
set -x OPENAI_API_KEY "sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
```
Common secret patterns:
- `github.fish` - GitHub Personal Access Token (`GITHUB_TOKEN`)
- `aws.fish` - AWS credentials (`AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`)
- `openai.fish` - OpenAI API key (`OPENAI_API_KEY`)
- `anthropic.fish` - Anthropic API key (`ANTHROPIC_API_KEY`)
## Security Best Practices
- **Never commit actual secrets** - Only `.example` files are tracked by git
- **Use specific permissions** - Consider `chmod 600` for secret files
- **Rotate credentials regularly** - Update tokens when compromised
- **Use environment-specific files** - Separate dev/staging/prod credentials
- **Check before committing** - Run `git status` to verify secrets aren't staged
## How It Works
The `exports.fish` file automatically sources all `*.fish` files from this directory:
```fish
if test -d "$DOTFILES/config/fish/secrets.d"
for secret_file in "$DOTFILES/config/fish/secrets.d"/*.fish
if test -f "$secret_file"
source "$secret_file"
end
end
end
```
Files ending in `.example` are ignored by the loader but tracked by git as templates.
## Backward Compatibility
This directory supplements the existing `exports-secret.fish` pattern. Both methods work:
- **Legacy**: `config/fish/exports-secret.fish` (single file, still supported)
- **New**: `config/fish/secrets.d/*.fish` (multiple files, recommended)
Use whichever approach fits your workflow best.

View File

@@ -0,0 +1,5 @@
# GitHub Personal Access Token
# Copy this file to github.fish (remove .example) and set your token
# Generate token at: https://github.com/settings/tokens
set -x GITHUB_TOKEN "ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

View File

@@ -1,6 +0,0 @@
# Detect shell
if [ -n "$BASH_VERSION" ] || [ -n "$ZSH_VERSION" ]; then
export GOENV_PATH_ORDER=front
export GOENV_PREPEND_GOPATH=true
export GOENV_AUTO_INSTALL=true
fi

View File

@@ -1,3 +0,0 @@
set -gx GOENV_PATH_ORDER front
set -gx GOENV_PREPEND_GOPATH true
set -gx GOENV_AUTO_INSTALL true

View File

@@ -1,13 +1,18 @@
tap "1password/tap"
tap "anchore/grype"
tap "caarlos0/tap"
tap "cormacrelf/tap"
tap "dagger/tap"
tap "ddosify/tap"
tap "dm3ch/tap"
tap "doron-cohen/tap"
tap "gesquive/tap"
tap "github/gh"
tap "golangci/tap"
tap "homebrew/autoupdate"
tap "homebrew/bundle"
tap "homebrew/services"
tap "ivuorinen/tap"
tap "jesseduffield/lazygit"
tap "k8sgpt-ai/k8sgpt"
tap "keith/formulae"
tap "koekeishiya/formulae"
tap "mongodb/brew"
@@ -16,21 +21,10 @@ tap "pantheon-systems/external"
tap "reviewdog/tap"
tap "shivammathur/extensions"
tap "shivammathur/php"
tap "snyk/tap"
tap "tabbyml/tabby"
tap "teamookla/speedtest"
tap "xwmx/taps"
# Mozilla CA certificate store
brew "ca-certificates"
# Mozilla CA bundle for Python
brew "certifi"
# Cryptography and SSL/TLS Toolkit
brew "openssl@3"
# Cryptographic recipes and primitives for Python
brew "cryptography"
# YAML Parser
brew "libyaml"
# Display directories as trees (with optional color/HTML output)
brew "tree"
# Generic-purpose lossless compression algorithm by Google
brew "brotli"
# Library and utilities for processing GIFs
@@ -41,6 +35,8 @@ brew "highway"
brew "imath"
# JPEG image codec that aids compression and decompression
brew "jpeg-turbo"
# Library for manipulating PNG images
brew "libpng"
# Zstandard is a real-time compression algorithm
brew "zstd"
# New file format for still image compression
@@ -49,6 +45,10 @@ brew "jpeg-xl"
brew "aom"
# Apache Portable Runtime library
brew "apr"
# Mozilla CA certificate store
brew "ca-certificates"
# Cryptography and SSL/TLS Toolkit
brew "openssl@3"
# Companion library to apr, the Apache Portable Runtime library
brew "apr-util"
# Password hashing library and CLI utility
@@ -69,10 +69,10 @@ brew "autogen"
brew "automake"
# GNU internationalization (i18n) and localization (l10n) library
brew "gettext"
# Text-based UI library
brew "ncurses"
# Bourne-Again SHell, a UNIX command interpreter
brew "bash"
# GNU File, Shell, and Text utilities
brew "coreutils"
# Parser generator
brew "bison"
# Freely available high-quality data compressor
@@ -83,37 +83,27 @@ brew "freetype"
brew "fontconfig"
# Core application library for C
brew "glib"
# Multi-platform support library with a focus on asynchronous I/O
brew "libuv"
# CLI tool for analyzing Claude Code usage from local JSONL files
brew "ccusage"
# JSON Schema CLI
brew "check-jsonschema"
# Mozilla CA bundle for Python
brew "certifi"
# GNU File, Shell, and Text utilities
brew "coreutils"
# Cryptographic recipes and primitives for Python
brew "cryptography"
# Get a file from an HTTP, HTTPS or FTP server
brew "curl"
# Network authentication protocol
brew "krb5"
# OpenType text shaping engine
brew "harfbuzz"
# OWASP dependency-check
brew "dependency-check"
# Lightweight DNS forwarder and DHCP server
brew "dnsmasq"
# .NET Core
brew "dotnet@8", link: true
# Spellchecker wrapping library
brew "enchant"
# Command-line tool to interact with exercism.io
brew "exercism"
# Perl lib for reading and writing EXIF metadata
brew "exiftool"
# Validating, recursive, caching DNS resolver
brew "unbound"
# GNU Transport Layer Security (TLS) Library
brew "gnutls"
# Secure hashing function
brew "libb2"
# Framework for layout and rendering of i18n text
brew "pango"
# Play, record, convert, and stream audio and video
# Play, record, convert, and stream select audio and video codecs
brew "ffmpeg"
# Banner-like program prints strings as ASCII art
brew "figlet"
@@ -127,17 +117,19 @@ brew "freetds"
brew "fswatch"
# Graphics library to dynamically manipulate images
brew "gd"
# Conversion library
brew "libiconv"
# Distributed revision control system
brew "git"
# Enable transparent encryption/decryption of files in a git repo
brew "git-crypt"
# Small git utilities
brew "git-extras"
# Browse your latest git branches, formatted real fancy
brew "git-recent"
# GNU implementation of the famous stream editor
brew "gnu-sed"
# GNU Pretty Good Privacy (PGP) package
# Validating, recursive, caching DNS resolver
brew "unbound"
# GNU Transport Layer Security (TLS) Library
brew "gnutls"
# GNU Privacy Guard (OpenPGP)
brew "gnupg"
# Library access to GnuPG
brew "gpgme"
@@ -145,6 +137,8 @@ brew "gpgme"
brew "gpg-tui"
# Image manipulation
brew "netpbm"
# Framework for layout and rendering of i18n text
brew "pango"
# Library to render SVG files using Cairo
brew "librsvg"
# Graph visualization software from AT&T and Bell Labs
@@ -153,13 +147,15 @@ brew "graphviz"
brew "grep"
# Popular GNU data compression program
brew "gzip"
# Secure hashing function
brew "libb2"
# Improved top (interactive process viewer)
brew "htop"
# Portable abstraction of the hierarchical topology of modern architectures
brew "hwloc"
# ISO/IEC 23008-12:2017 HEIF file format decoder and encoder
brew "libheif"
# Tools and libraries to manipulate images in many formats
# Tools and libraries to manipulate images in select formats
brew "imagemagick"
# Modular IRC client
brew "irssi"
@@ -167,22 +163,26 @@ brew "irssi"
brew "jpeg"
# JSON parser for C
brew "json-c"
# Crawling and spidering framework
brew "katana"
# Style and grammar checker
brew "languagetool"
# Tool to detect/remediate misconfig and security risks of GitHub/GitLab assets
brew "legitify"
# Code coverage tester for compiled programs, Python, and shell scripts
brew "kcov"
# Network authentication protocol
brew "krb5"
# BSD-style licensed readline alternative
brew "libedit"
# Conversion library
brew "libiconv"
# Postgres C API library
brew "libpq"
# Version of the SSL/TLS protocol forked from OpenSSL
brew "libressl"
# Multi-platform support library with a focus on asynchronous I/O
brew "libuv"
# Linguistic software and Finnish dictionary
brew "libvoikko"
# GNOME XML library
brew "libxml2"
# YAML Parser
brew "libyaml"
# C library for reading, creating, and modifying zip archives
brew "libzip"
# Package manager for the Lua programming language
brew "luarocks"
# LZMA-based compression program similar to gzip or bzip2
@@ -210,27 +210,33 @@ brew "ossp-uuid"
# General-purpose scripting language
brew "php", link: false
# General-purpose scripting language
brew "php@8.1"
# General-purpose scripting language
brew "php@8.2", link: true
# General-purpose scripting language
brew "php@8.3"
# Execute binaries from Python packages in isolated environments
brew "pipx"
# Easily download, build, install, upgrade, and uninstall Python packages
brew "python-setuptools"
# Interpreted, interactive, object-oriented programming language
brew "python@3.11"
# Interpreted, interactive, object-oriented programming language
brew "python@3.13"
# Generate C-based recognizers from regular expressions
brew "re2c"
# User interface to the TELNET protocol
brew "telnet"
# Send macOS User Notifications from the command-line
brew "terminal-notifier"
# Tool which checks for the support of TLS/SSL ciphers and flaws
brew "testssl"
# Terminal multiplexer
brew "tmux"
# Display directories as trees (with optional color/HTML output)
brew "tree"
# Executes a program periodically, showing output fullscreen
brew "watch"
# Internet file retriever
brew "wget"
# Check your $HOME for unwanted files and directories
brew "xdg-ninja", args: ["HEAD"]
# General-purpose lossless data-compression library
brew "zlib"
# Watcher for macOS 10.14+ light/dark mode changes
@@ -241,32 +247,50 @@ brew "doron-cohen/tap/antidot"
brew "gesquive/tap/git-user"
# Simple hotkey-daemon for macOS.
brew "koekeishiya/formulae/skhd"
# Automated code review tool integrated with any code analysis tools regardless of programming language.
brew "reviewdog/tap/reviewdog"
# Igbinary PHP extension
brew "shivammathur/extensions/igbinary@8.3"
# Imagick PHP extension
brew "shivammathur/extensions/imagick@8.1"
# Imagick PHP extension
brew "shivammathur/extensions/imagick@8.2"
# Imagick PHP extension
brew "shivammathur/extensions/imagick@8.3"
# Imagick PHP extension
brew "shivammathur/extensions/imagick@8.4"
# Mcrypt PHP extension
brew "shivammathur/extensions/mcrypt@8.3"
# Msgpack PHP extension
brew "shivammathur/extensions/msgpack@8.3"
# PCOV PHP extension
brew "shivammathur/extensions/pcov@8.1"
# PCOV PHP extension
brew "shivammathur/extensions/pcov@8.2"
# PCOV PHP extension
brew "shivammathur/extensions/pcov@8.3"
# Redis PHP extension
brew "shivammathur/extensions/redis@8.3"
brew "shivammathur/extensions/phpredis@8.3"
# Uuid PHP extension
brew "shivammathur/extensions/uuid@8.3"
# Xdebug PHP extension
brew "shivammathur/extensions/xdebug@8.1"
# Xdebug PHP extension
brew "shivammathur/extensions/xdebug@8.2"
# Xdebug PHP extension
brew "shivammathur/extensions/xdebug@8.4"
# Xdebug PHP extension
brew "shivammathur/extensions/xdebug@8.5"
# Yaml PHP extension
brew "shivammathur/extensions/yaml@8.3"
# General-purpose scripting language
brew "shivammathur/php/php-debug"
brew "shivammathur/php/php-debug", link: false
# General-purpose scripting language
brew "shivammathur/php/php@8.1-debug"
# General-purpose scripting language
brew "shivammathur/php/php@8.2-debug"
# Tabby: AI Coding Assistant
brew "tabbyml/tabby/tabby"
# General-purpose scripting language
brew "shivammathur/php/php@8.4"
# Command-line interface for 1Password
cask "1password-cli"
# Semantic code analysis engine
cask "codeql"
# Universal database tool and SQL client
cask "dbeaver-community"
# Database version management tool
@@ -332,6 +356,8 @@ cask "thonny"
cask "todoist-app"
# Configuration application for the Ultimate Hacking Keyboard
cask "uhk-agent"
# Google Chromium, sans integration with Google
cask "ungoogled-chromium"
# Open-source code editor
cask "visual-studio-code"
# Multimedia player
@@ -340,7 +366,7 @@ cask "vlc"
cask "voikkospellservice"
# GPU-accelerated cross-platform terminal emulator and multiplexer
cask "wezterm"
# Application for generating TOTP and HOTP codes
# Full-featured companion app to the YubiKey
cask "yubico-authenticator"
# Multiplayer code editor
cask "zed"

View File

@@ -5,45 +5,50 @@ python = "3"
go = "latest"
rust = "stable"
# Pre-built binaries via ubi (fast — no compilation)
"ubi:sharkdp/fd" = "latest"
"ubi:BurntSushi/ripgrep" = "latest"
"ubi:eza-community/eza" = "latest"
"ubi:ClementTsang/bottom" = "latest"
"ubi:ajeetdsouza/zoxide" = "latest"
"ubi:tree-sitter/tree-sitter" = "latest"
"ubi:neovim/neovim" = "latest" # Neovim editor binary
"ubi:dandavison/delta" = "latest"
# Pre-built binaries via aqua registry
fd = "latest"
ripgrep = "latest"
eza = "latest"
bottom = "latest"
zoxide = "latest"
tree-sitter = "latest"
neovim = "latest" # Neovim editor binary
delta = "latest"
difftastic = "latest"
# Cargo-based tools (no pre-built binary available)
"cargo:bkt" = "latest"
"cargo:difftastic" = "latest"
"cargo:tmux-sessionizer" = "latest"
# GitHub releases (no aqua entry)
"github:dimo414/bkt" = "latest"
"github:jrmoulton/tmux-sessionizer" = "latest"
# Go-based tools
"go:github.com/google/yamlfmt/cmd/yamlfmt" = "latest"
"go:github.com/cheat/cheat/cmd/cheat" = "latest"
"go:github.com/charmbracelet/glow" = "latest"
"go:github.com/junegunn/fzf" = "latest"
"go:github.com/charmbracelet/gum" = "latest"
# Go-compiled tools (no registry binary available)
"go:github.com/joshmedeski/sesh/v2" = "latest"
"go:github.com/dotzero/git-profile" = "latest"
# Registry shorthands (aqua binaries)
yamlfmt = "latest"
cheat = "latest"
glow = "latest"
fzf = "latest"
gum = "latest"
# npm-based tools
"npm:editorconfig-checker" = "latest"
editorconfig-checker = "latest"
"npm:github-release-notes" = "latest"
"npm:neovim" = "latest" # Node.js client for Neovim's RPC API (required by plugins)
"npm:corepack" = "latest"
# Python tools (via pipx backend)
"pipx:ansible" = "latest"
"pipx:detect-secrets" = "latest"
"pipx:git-filter-repo" = "latest"
yamllint = "latest"
ansible = "latest"
"pipx:ansible-lint" = "latest"
"pipx:ruff" = "latest"
ruff = "latest"
"pipx:openapi-python-client" = "latest"
"pipx:python-lsp-server[websockets]" = "latest"
# .NET tools (via dotnet backend)
"dotnet:coverlet.console" = "latest"
"dotnet:csharp-ls" = "latest"
"dotnet:csharpier" = "latest"
"dotnet:ilspycmd" = "latest"
"dotnet:dotnet-ef" = "latest"
@@ -56,8 +61,12 @@ checkov = "latest"
grype = "latest"
pinact = "latest"
snyk = "latest"
cosign = "latest"
gitleaks = "latest"
syft = "latest"
# Dev tools (pre-built binaries)
gitui = "latest"
lazygit = "latest"
bat = "latest"
bats = "latest"
@@ -66,14 +75,21 @@ cmake = "latest"
gdu = "latest"
github-cli = "latest"
jq = "latest"
hadolint = "latest"
hugo = "latest"
just = "latest"
yq = "latest"
"github:exercism/cli" = "latest"
"github:projectdiscovery/katana" = "latest"
"github:Legit-Labs/legitify" = "latest"
shellcheck = "latest"
shfmt = "latest"
stylua = "latest"
actionlint = "latest"
"aqua:mpalmer/action-validator" = "latest"
oh-my-posh = "latest"
"ubi:o2sh/onefetch" = "latest"
"ubi:wakatime/wakatime-cli" = "latest"
"github:o2sh/onefetch" = "latest"
"github:wakatime/wakatime-cli" = "latest"
# Terraform (replaces tfenv)
terraform = "latest"
@@ -103,3 +119,4 @@ lockfile = true
# Save disk space — don't keep downloaded archives or failed installs
always_keep_download = false
always_keep_install = false
experimental = true

View File

@@ -22,8 +22,8 @@
[credential "https://github.com"]
helper =
helper = !/opt/homebrew/bin/gh auth git-credential
helper = !gh auth git-credential
[credential "https://gist.github.com"]
helper =
helper = !/opt/homebrew/bin/gh auth git-credential
helper = !gh auth git-credential

32
local/bin/x-gitprofile Executable file
View File

@@ -0,0 +1,32 @@
#!/usr/bin/env bash
# @description Set up mise enter hooks for git-profile auto-switching
set -euo pipefail
DEFAULTS=(
"home:$HOME/Code/ivuorinen"
"masf:$HOME/Code/masf"
)
write_hook()
{
local profile="$1" dir="$2"
mkdir -p "$dir"
cat > "$dir/.mise.toml" << EOF
[hooks]
enter = "git profile use $profile"
EOF
echo "Set git profile '$profile' for $dir"
}
if [[ $# -eq 0 ]]; then
for entry in "${DEFAULTS[@]}"; do
write_hook "${entry%%:*}" "${entry#*:}"
done
elif [[ $# -eq 2 ]]; then
write_hook "$1" "$2"
else
echo "Usage: x-gitprofile [<profile> <dir>]"
echo " No args: set up defaults (home, masf)"
echo " With args: create .mise.toml in <dir>"
exit 1
fi

View File

@@ -133,6 +133,15 @@ if command -v brew &> /dev/null; then
fi
fi
done
# Clean up orphaned dependencies left after the removals above
if [[ "$DRY_RUN" = "--dry-run" ]]; then
msgr warn "[DRY RUN] Would run: brew autoremove"
else
msgr run "Removing orphaned brew dependencies..."
brew autoremove
msgr run_done "Orphaned dependencies removed"
fi
fi
msgr yay "Cleanup complete! Run 'mise install' to set up tools via mise."

View File

@@ -1,12 +0,0 @@
# install-git-crypt
Installs `git-crypt` for transparent encryption of files in Git repositories.
## Usage
```bash
scripts/install-git-crypt.sh
```
After installation you can run `git-crypt init` inside a repository to begin
encrypting files.

View File

@@ -1,33 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
# @description Install git-crypt
#
# NOTE: Experimental, wip
#
# shellcheck source=shared.sh
source "${DOTFILES}/config/shared.sh"
msgr run "Installing git-crypt"
if ! command -v git-crypt &> /dev/null; then
REPO_URL="https://github.com/AGWA/git-crypt.git"
CHECK_PATH="${XDG_BIN_HOME}/git-crypt"
BUILD_PATH="$(mktemp -d)"
trap 'rm -rf "$BUILD_PATH"' EXIT
if [[ ! -f "$CHECK_PATH" ]]; then
git clone --depth 1 "$REPO_URL" "$BUILD_PATH" || {
msgr err "Failed to clone $REPO_URL"
exit 1
}
cd "$BUILD_PATH" || {
msgr err "$BUILD_PATH not found"
exit 1
}
make && make install PREFIX="$HOME/.local"
else
msgr run_done "git-crypt ($CHECK_PATH) already installed"
fi
fi
msgr run_done "Done installing git-crypt"