원클릭으로
add-tool
Add a new tool to the dotfiles repository. Use when asked to add a new CLI tool, application, or package as a managed dotfiles tool.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Add a new tool to the dotfiles repository. Use when asked to add a new CLI tool, application, or package as a managed dotfiles tool.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Voice guide for writing PR descriptions. Use this skill for ALL PR creation and updates (via gh CLI or editing existing PRs). Contains your specific voice rules, anti-patterns, examples, and workflow. Never write PR descriptions without invoking this skill first.
Commit the changes in the working tree. Only invoke when the user explicitly signals to commit ("commit", "/commit", etc.). Never invoke this skill on your own initiative — implementation approval is not a commit signal.
Standalone code review for any scope — PR number, branch, file paths, or current changes. Synthesizes intent, runs 10 parallel specialized agents, and presents actionable findings with a verdict. For PR scope, optionally posts the review to GitHub with inline comments.
Survey observable paths, run the real system, capture evidence, and surface gaps. TRIGGER when asked to prove a change works or write a QA plan.
Tell the next agent everything they need to know to continue your work.
Voice guide for writing issue/ticket/task/epic descriptions. Use this skill for ALL issue creation — GitHub issues, Jira tasks, Monday tasks, Linear tasks, and epics. Contains section structure, voice rules, and anti-patterns. Never write ticket descriptions without invoking this skill first.
| name | add-tool |
| description | Add a new tool to the dotfiles repository. Use when asked to add a new CLI tool, application, or package as a managed dotfiles tool. |
ls "${DOTFILES}/tools" | grep -v ^@tools/@new/ — reference for file structure and patternsAdd a new tool to this dotfiles repository. Follow these steps:
Before writing any files:
brew install, npm install -g, bun install -g, uv tool install, cargo install, or a custom install script.{command} --version output? Run it (or check the docs) to know the exact format — you'll need this to write parse_version.eval "$(tool completion zsh)"), note it — you'll need shell.zsh.~/.config/{tool}/ or similar, you'll need link.bash and a config/ directory.Simple tool (no dotfiles config to symlink): needs only the 4 core files.
Examples: eza, sd, logcli
Tool with config (has config files to symlink): also needs link.bash and a config/ directory.
Examples: claude, neovim, git
tools/{tool}/utils.bash#!/usr/bin/env bash
set -euo pipefail
export TOOL_LOWER="{tool}"
export TOOL_UPPER="{Tool}"
export TOOL_COMMAND="{tool}"
export TOOL_PACKAGE="{package-name}"
export TOOL_EMOJI="🔧"
export TOOL_CONFIG_DIR="${HOME}/.config/${TOOL_LOWER}" # omit if no config
parse_version() {
local raw_version="${1}"
# Adapt to match the actual output of the version command (arg 6 in install/update):
printf "${raw_version}"
}
Key variables:
TOOL_LOWER: lowercase name used in paths and log messagesTOOL_UPPER: display name (often same as TOOL_LOWER, but e.g. "Claude Code")TOOL_COMMAND: the binary name (which resolves this)TOOL_PACKAGE: the package name passed to the installerTOOL_EMOJI: used in log outputTOOL_CONFIG_DIR: only needed for tools with config; omit the export if unusedparse_version by installer — receives the raw output of the version command (arg 6) and must return a clean semver string:
| Installer | Version command (arg 6) | Typical raw output | parse_version logic |
|---|---|---|---|
brew | brew list --version {pkg} | sd 1.0.0 | strip "sd " prefix |
npm / bun | {command} --version | 1.10.2 | print as-is |
npm (some) | {command} --version | 1.0.0 (Claude Code) | strip suffix |
uv tool | {pkg} --version | ty, version 0.0.1 | strip "ty, version " prefix |
cargo | {command} --version | sd 1.0.0 | strip "sd " prefix |
tools/{tool}/install.bashStructure is always the same — only the install command (arg 5) and version command (arg 6) change by installer:
brew:
#!/usr/bin/env bash
set -euo pipefail
source "${DOTFILES}/features/install/utils.bash"
source "${DOTFILES}/tools/{tool}/utils.bash" # source last to avoid env var overrides
install_and_symlink \
"${TOOL_LOWER}" \
"${TOOL_UPPER}" \
"${TOOL_COMMAND}" \
"${TOOL_EMOJI}" \
"brew install --formula ${TOOL_PACKAGE}" \
"brew list --version ${TOOL_PACKAGE}" \
"parse_version"
npm:
"npm install --global ${TOOL_PACKAGE}@latest" \
"${TOOL_COMMAND} --version" \
bun:
"bun install --global ${TOOL_PACKAGE}" \
"${TOOL_COMMAND} --version" \
uv:
"uv tool install ${TOOL_PACKAGE}" \
"${TOOL_PACKAGE} --version" \
cargo:
"cargo install ${TOOL_PACKAGE}" \
"${TOOL_COMMAND} --version" \
For tools with config, add the symlink script path as an 8th argument:
"parse_version" \
"${DOTFILES}/tools/${TOOL_LOWER}/link.bash"
tools/{tool}/update.bashSame pattern — update command varies by installer, 8th arg is always the install script fallback:
brew:
#!/usr/bin/env bash
set -euo pipefail
source "${DOTFILES}/features/update/utils.bash"
source "${DOTFILES}/tools/{tool}/utils.bash" # source last to avoid env var overrides
update_and_symlink \
"${TOOL_LOWER}" \
"${TOOL_UPPER}" \
"${TOOL_COMMAND}" \
"${TOOL_EMOJI}" \
"brew upgrade --formula ${TOOL_PACKAGE}" \
"brew list --version ${TOOL_PACKAGE}" \
"parse_version" \
"${DOTFILES}/tools/${TOOL_LOWER}/install.bash"
Update commands by installer: brew upgrade --formula {pkg} / npm install --global {pkg}@latest / bun install --global {pkg} / uv tool upgrade {pkg} / cargo install {pkg}
For tools with config, add the symlink script path as a 9th argument:
"${DOTFILES}/tools/${TOOL_LOWER}/install.bash" \
"${DOTFILES}/tools/${TOOL_LOWER}/link.bash"
tools/{tool}/uninstall.bash (non-brew tools only)Brew-managed tools: skip this file. Uninstall by moving the tool folder to
tools/@archive (or deleting it) and running u — the Brewfile entry drops
out of Brewfile.generated automatically.
Non-brew tools (npm/bun/uv/cargo): create a plain script with only the cleanup steps brew can't handle — no wrapper needed:
#!/usr/bin/env bash
set -euo pipefail
source "${DOTFILES}/tools/bash/utils.bash"
info "🔧 Uninstalling {tool}"
{uninstall command}
Uninstall commands: npm uninstall --global {pkg} / bun uninstall --global {pkg} / uv tool uninstall {pkg} / cargo uninstall {pkg}
tools/{tool}/shell.zsh (only if needed)Only create this file if the tool requires explicit shell setup: environment variables, aliases, or completions not auto-installed by the package manager.
Brew auto-installs completions to /opt/homebrew/share/zsh/site-functions — no shell.zsh needed for those. Only add completion setup if the tool's docs require something like eval "$(tool completion zsh)" or source <(tool completions zsh).
########################
# ENVIRONMENT VARIABLES #
########################
# export SOME_VAR="value"
###########
# ALIASES #
###########
# alias x="tool --flag"
###############
# COMPLETIONS #
###############
# eval "$(tool completion zsh)"
link.bashtools/{tool}/link.bash:
#!/usr/bin/env bash
set -euo pipefail
source "${DOTFILES}/tools/{tool}/utils.bash"
source "${DOTFILES}/tools/bash/utils.bash"
symlink "${DOTFILES}/tools/{tool}/config/settings.json" "${TOOL_CONFIG_DIR}/settings.json"
shellcheck tools/{tool}/*.bash
Run the install script to confirm it works end-to-end:
DOTFILES="$HOME/Repos/ooloth/dotfiles" bash tools/{tool}/install.bash
features/install/tools.bash and features/update/tools.bash use find to discover all install.bash / update.bash files under tools/ automatically. No manual registration is needed.shell.zsh is sourced automatically in every new shell via the generated manifest at $DOTFILES/.cache/shell-files-manifest.zsh. Regenerate it with the symlinks alias after adding a new tool.