manual
Installs files from your tool configuration directory (custom scripts, pre-built binaries) or registers configuration-only tools. The manual method can be called with or without params.
Basic Usage
Section titled “Basic Usage”import { defineTool } from "@alexgorbatchev/dotfiles";
// Install a custom scriptexport default defineTool((install, ctx) => install("manual", { binaryPath: "./scripts/my-tool.sh", }).bin("my-tool"),);// Without params (shell-only or dependency wrapper)export default defineTool((install) => install("manual") .bin("tokscale") .dependsOn("bun") .zsh((shell) => shell.functions({ tokscale: `bun x tokscale@latest`, }), ),);// Configuration-only tool (no binary)export default defineTool((install, ctx) => install().zsh((shell) => shell.aliases({ ll: "ls -la" })));When to Use
Section titled “When to Use”Use install("manual", { binaryPath }) for binaries that ship with your dotfiles:
- You have custom scripts or binaries to include with your dotfiles
- You want the system to manage and version your tool files
- You need shims generated for your custom tools
- You want to distribute pre-built binaries with your dotfiles
Use install() with no arguments for configuration-only tools:
- You only need shell configuration (aliases, environment, symlinks)
- Tools are managed entirely outside the dotfiles system
- You don’t want any binary installation or management
A tool installed by a script that picks its own location (such as
https://claude.ai/install.sh, which installs into ~/.local/bin) is not a manual tool
with the script run from a hook. Use curl-script with binaryPath, which downloads and
runs the script itself and links the binary to where the script put it; see
Scripts That Install Themselves.
Parameters
Section titled “Parameters”| Parameter | Type | Required | Description |
|---|---|---|---|
binaryPath | string | No | Path to the binary; see binaryPath Resolution |
symlink | boolean | No | If true, symlinks to binaryPath instead of copying files |
binaryPath Resolution
Section titled “binaryPath Resolution”binaryPath is resolved in this order:
- Placeholders such as
{paths.homeDir}are filled from the project configuration. A placeholder nothing can fill fails the installation, naming the tool and the value. - A leading
~is the project’spaths.homeDir. - A path that is still relative is taken relative to the
.tool.tsfile, or topaths.dotfilesDirfor a configuration that has no tool file.
Symlinks are not followed: the result is the path as written. The generated shim runs the same resolved path, so the installer and the shim cannot disagree about it.
binaryPath and Binary Patterns
Section titled “binaryPath and Binary Patterns”binaryPath names the one file that is installed under every declared .bin() name, so
nothing is searched for and a binary pattern
has nothing to select. A tool that sets binaryPath and gives any .bin() a pattern,
whether as .bin(name, pattern) or .bin(name, { pattern }), is rejected when the
configuration loads, with an error naming the tool file, the tool, the binary, the pattern
and binaryPath:
invalid tool configuration in "<tool file>": tool "<tool>": binary "<binary>" declares pattern "<pattern>", but manual binaryPath "<binaryPath>" already names the file to install, so the pattern would never be used; drop the pattern from .bin().bin(name, { shim: false }) declares no pattern and is accepted. The same rule applies to
curl-script’s binaryPath. Its error
says curl-script binaryPath and also offers the other fix, since a curl-script without
binaryPath does search stagingDir with the pattern:
...; drop the pattern from .bin(), or drop binaryPath and point the script at {stagingDir} through args or env.
Examples
Section titled “Examples”Pre-built Binary
Section titled “Pre-built Binary”export default defineTool((install, ctx) => install("manual", { binaryPath: "./binaries/linux/x64/custom-tool", }).bin("custom-tool"),);Configuration-Only Tool
Section titled “Configuration-Only Tool”export default defineTool((install, ctx) => install().zsh((shell) => shell.aliases({ ll: "ls -la", la: "ls -A" })));With Shell Configuration
Section titled “With Shell Configuration”export default defineTool((install, ctx) => install("manual", { binaryPath: "./bin/my-tool.sh", }) .bin("my-tool") .zsh((shell) => shell.aliases({ mt: "my-tool" }).completions("./completions/_my-tool")),);With Sudo Prompt
Section titled “With Sudo Prompt”export default defineTool((install) => install("manual", { binaryPath: "/usr/bin/whoami", }) .bin("sudo-prompt-test") .sudo(),);Notes:
- Binary paths are relative to the tool configuration file location
- Files are copied to the managed installation directory with executable permissions
.sudo()acquires sudo credentials interactively before Dotfiles registers the manual binary- A
before-installhook can stage files intostagingDirin place ofbinaryPath; if it leaves the staging directory empty the installation fails rather than producing an empty payload (see lifecycle-hooks.md) - Configuration-only tools use
install()with no arguments and must not define.bin()