@alexgorbatchev/dotfiles 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +397 -0
- package/cli-fj2hdbnx.js +5 -0
- package/cli-fj2hdbnx.js.map +9 -0
- package/cli-w822cqdk.js +4 -0
- package/cli-w822cqdk.js.map +10 -0
- package/cli.js +449 -0
- package/cli.js.map +283 -0
- package/dashboard-0ebz5sqb.js +159 -0
- package/dashboard-0ebz5sqb.js.map +102 -0
- package/dashboard-3axqywva.css +1 -0
- package/dashboard.js +13 -0
- package/package.json +63 -0
- package/prerender-kpxyx916.js +3 -0
- package/prerender-kpxyx916.js.map +11 -0
- package/schemas.d.ts +2730 -0
- package/skill/SKILL.md +74 -0
- package/skill/references/api-reference.md +614 -0
- package/skill/references/configuration.md +1154 -0
- package/skill/references/installation-methods/brew.md +62 -0
- package/skill/references/installation-methods/cargo.md +86 -0
- package/skill/references/installation-methods/curl-binary.md +73 -0
- package/skill/references/installation-methods/curl-script.md +132 -0
- package/skill/references/installation-methods/curl-tar.md +58 -0
- package/skill/references/installation-methods/dmg.md +113 -0
- package/skill/references/installation-methods/gitea-release.md +106 -0
- package/skill/references/installation-methods/github-release.md +97 -0
- package/skill/references/installation-methods/manual.md +74 -0
- package/skill/references/installation-methods/npm.md +75 -0
- package/skill/references/installation-methods/overview.md +293 -0
- package/skill/references/installation-methods/zsh-plugin.md +156 -0
- package/skill/references/make-tool.md +866 -0
- package/skill/references/shell-and-hooks.md +833 -0
- package/tool-types.d.ts +14 -0
- package/wasm-n3cagcre.js +3 -0
- package/wasm-n3cagcre.js.map +10 -0
|
@@ -0,0 +1,1154 @@
|
|
|
1
|
+
# Configuration
|
|
2
|
+
|
|
3
|
+
## Table of Contents
|
|
4
|
+
|
|
5
|
+
- [Getting Started](#getting-started)
|
|
6
|
+
- [File Structure](#file-structure)
|
|
7
|
+
- [Minimal Configuration](#minimal-configuration)
|
|
8
|
+
- [Complete Example](#complete-example)
|
|
9
|
+
- [Available Methods](#available-methods)
|
|
10
|
+
- [TypeScript Setup](#typescript-setup)
|
|
11
|
+
- [Project Configuration](#project-configuration)
|
|
12
|
+
- [Basic Configuration](#basic-configuration)
|
|
13
|
+
- [defineConfig Options](#defineconfig-options)
|
|
14
|
+
- [Configuration Reference](#configuration-reference)
|
|
15
|
+
- [Platform Overrides](#platform-overrides)
|
|
16
|
+
- [CLI Usage](#cli-usage)
|
|
17
|
+
- [Directory Structure](#directory-structure)
|
|
18
|
+
- [Platform-Specific Configuration](#platform-specific-configuration)
|
|
19
|
+
- [Platform and Architecture Enums](#platform-and-architecture-enums)
|
|
20
|
+
- [Basic Usage](#basic-usage-1)
|
|
21
|
+
- [With Architecture](#with-architecture)
|
|
22
|
+
- [Platform Groups](#platform-groups)
|
|
23
|
+
- [Platform-Specific Shell Config](#platform-specific-shell-config)
|
|
24
|
+
- [Platform Detection in Hooks](#platform-detection-in-hooks)
|
|
25
|
+
- [Common Asset Patterns](#common-asset-patterns)
|
|
26
|
+
- [Virtual Environments](#virtual-environments)
|
|
27
|
+
- [Overview](#overview)
|
|
28
|
+
- [Creating an Environment](#creating-an-environment)
|
|
29
|
+
- [Activating an Environment](#activating-an-environment)
|
|
30
|
+
- [Using an Activated Environment](#using-an-activated-environment)
|
|
31
|
+
- [Adding Tools](#adding-tools)
|
|
32
|
+
- [Deactivating](#deactivating)
|
|
33
|
+
- [Deleting an Environment](#deleting-an-environment)
|
|
34
|
+
- [Use Cases](#use-cases)
|
|
35
|
+
- [XDG Configuration Isolation](#xdg-configuration-isolation)
|
|
36
|
+
- [Generated Files](#generated-files)
|
|
37
|
+
- [Common Patterns](#common-patterns)
|
|
38
|
+
- [GitHub Tool with Shell Integration](#github-tool-with-shell-integration)
|
|
39
|
+
- [Tool Dependencies](#tool-dependencies)
|
|
40
|
+
- [Complex Shell Integration](#complex-shell-integration)
|
|
41
|
+
- [Cross-Shell Configuration](#cross-shell-configuration)
|
|
42
|
+
- [With Hooks](#with-hooks)
|
|
43
|
+
- [Platform-Specific Installation](#platform-specific-installation)
|
|
44
|
+
- [Cargo (Rust) Tool](#cargo-rust-tool)
|
|
45
|
+
- [Manual Script](#manual-script)
|
|
46
|
+
- [Configuration-Only (No Binary)](#configuration-only-no-binary)
|
|
47
|
+
- [Custom Asset Selection](#custom-asset-selection)
|
|
48
|
+
- [Installation Method Quick Reference](#installation-method-quick-reference)
|
|
49
|
+
- [Advanced Topics](#advanced-topics)
|
|
50
|
+
- [Custom Asset Selection](#custom-asset-selection-1)
|
|
51
|
+
- [Dynamic Configuration](#dynamic-configuration)
|
|
52
|
+
- [Conditional Installation](#conditional-installation)
|
|
53
|
+
- [Build from Source](#build-from-source)
|
|
54
|
+
- [Dependency Verification](#dependency-verification)
|
|
55
|
+
- [Lazy Loading](#lazy-loading)
|
|
56
|
+
- [Dynamic Completions](#dynamic-completions)
|
|
57
|
+
- [Parallel Setup Tasks](#parallel-setup-tasks)
|
|
58
|
+
- [Troubleshooting](#troubleshooting)
|
|
59
|
+
- [Enable Debug Logging](#enable-debug-logging)
|
|
60
|
+
- [Common Issues](#common-issues)
|
|
61
|
+
- [Testing and Verification](#testing-and-verification)
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
# Getting Started
|
|
66
|
+
|
|
67
|
+
This guide covers how to create `.tool.ts` configuration files for your CLI tools.
|
|
68
|
+
|
|
69
|
+
## Prerequisites
|
|
70
|
+
|
|
71
|
+
Set up your project configuration first. See Project Configuration for instructions.
|
|
72
|
+
|
|
73
|
+
## File Structure
|
|
74
|
+
|
|
75
|
+
Tool configurations are placed in your `toolConfigsDir` (default: `~/.dotfiles/tools`):
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
tools/
|
|
79
|
+
├── fzf.tool.ts
|
|
80
|
+
├── ripgrep.tool.ts
|
|
81
|
+
└── dev/
|
|
82
|
+
├── node.tool.ts
|
|
83
|
+
└── rust.tool.ts
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Files must be named `{tool-name}.tool.ts` and export a default using `defineTool`.
|
|
87
|
+
|
|
88
|
+
## Minimal Configuration
|
|
89
|
+
|
|
90
|
+
```typescript
|
|
91
|
+
import { defineTool } from '@alexgorbatchev/dotfiles';
|
|
92
|
+
|
|
93
|
+
export default defineTool((install, ctx) =>
|
|
94
|
+
install('github-release', {
|
|
95
|
+
repo: 'junegunn/fzf',
|
|
96
|
+
}).bin('fzf')
|
|
97
|
+
);
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Complete Example
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
import { defineTool } from '@alexgorbatchev/dotfiles';
|
|
104
|
+
|
|
105
|
+
export default defineTool((install, ctx) =>
|
|
106
|
+
install('github-release', {
|
|
107
|
+
repo: 'BurntSushi/ripgrep',
|
|
108
|
+
})
|
|
109
|
+
.bin('rg')
|
|
110
|
+
.dependsOn('pcre2')
|
|
111
|
+
.symlink('./ripgreprc', '~/.ripgreprc')
|
|
112
|
+
.zsh((shell) => shell.env({ RIPGREP_CONFIG_PATH: '~/.ripgreprc' }).aliases({ rgi: 'rg -i' }))
|
|
113
|
+
);
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Available Methods
|
|
117
|
+
|
|
118
|
+
After calling `install()`, these methods are available:
|
|
119
|
+
|
|
120
|
+
| Method | Purpose |
|
|
121
|
+
| ------------------------ | ------------------------------------- |
|
|
122
|
+
| `.bin(name)` | Define binary name(s) to expose |
|
|
123
|
+
| `.version(v)` | Set version (`'latest'` or specific) |
|
|
124
|
+
| `.dependsOn(bin)` | Declare binary dependencies |
|
|
125
|
+
| `.symlink(src, dest)` | Create config file symlinks |
|
|
126
|
+
| `.hook(event, fn)` | Lifecycle hooks |
|
|
127
|
+
| `.zsh(fn)` / `.bash(fn)` | Shell-specific configuration |
|
|
128
|
+
| `.platform(p, fn)` | Platform-specific overrides |
|
|
129
|
+
| `.disable()` | Skip tool during generation |
|
|
130
|
+
| `.hostname(pattern)` | Restrict tool to specific hostname(s) |
|
|
131
|
+
|
|
132
|
+
## TypeScript Setup
|
|
133
|
+
|
|
134
|
+
### Imports
|
|
135
|
+
|
|
136
|
+
```typescript
|
|
137
|
+
import { Architecture, defineTool, Platform } from '@alexgorbatchev/dotfiles';
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
| Export | Description |
|
|
141
|
+
| -------------- | ---------------------------------------------- |
|
|
142
|
+
| `defineTool` | Factory function to create tool configurations |
|
|
143
|
+
| `Platform` | Enum: `Darwin`, `Linux`, `Windows`, `MacOS` |
|
|
144
|
+
| `Architecture` | Enum: `X86_64`, `Arm64` |
|
|
145
|
+
|
|
146
|
+
### Configuration-Only Tools
|
|
147
|
+
|
|
148
|
+
Tools that only contribute shell configuration (no binary installation):
|
|
149
|
+
|
|
150
|
+
```typescript
|
|
151
|
+
export default defineTool((install) => install().zsh((shell) => shell.env({ FOO: 'bar' })));
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Orphaned Artifact Cleanup
|
|
155
|
+
|
|
156
|
+
When a `.tool.ts` configuration file is removed, `dotfiles generate` automatically cleans up the corresponding generated shims and completions on the next run. No manual cleanup is needed.
|
|
157
|
+
|
|
158
|
+
### Auto-Generated Types
|
|
159
|
+
|
|
160
|
+
Running `dotfiles generate` creates `.generated/tool-types.d.ts` with type-safe `dependsOn()` autocomplete for all your tool binaries.
|
|
161
|
+
|
|
162
|
+
Add to your `tsconfig.json`:
|
|
163
|
+
|
|
164
|
+
```json
|
|
165
|
+
{
|
|
166
|
+
"include": ["tools/**/*.tool.ts", ".generated/tool-types.d.ts"]
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Common Type Errors
|
|
171
|
+
|
|
172
|
+
```typescript
|
|
173
|
+
// ❌ Missing required parameter
|
|
174
|
+
install('github-release', {}) // Error: 'repo' is required
|
|
175
|
+
|
|
176
|
+
// ❌ Invalid parameter for method
|
|
177
|
+
install('brew', { repo: 'owner/tool' }) // Error: 'repo' not valid for brew
|
|
178
|
+
|
|
179
|
+
// ❌ String instead of enum
|
|
180
|
+
.platform('macos', ...) // Error: use Platform.MacOS
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
# Project Configuration
|
|
186
|
+
|
|
187
|
+
The project configuration file defines paths, features, and API settings for your dotfiles system.
|
|
188
|
+
|
|
189
|
+
## Basic Configuration
|
|
190
|
+
|
|
191
|
+
```typescript
|
|
192
|
+
import { defineConfig } from '@alexgorbatchev/dotfiles';
|
|
193
|
+
|
|
194
|
+
export default defineConfig(() => ({
|
|
195
|
+
paths: {
|
|
196
|
+
dotfilesDir: '~/.dotfiles',
|
|
197
|
+
toolConfigsDir: '~/.dotfiles/tools',
|
|
198
|
+
generatedDir: '~/.dotfiles/.generated',
|
|
199
|
+
targetDir: '~/.local/bin',
|
|
200
|
+
},
|
|
201
|
+
}));
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## defineConfig Options
|
|
205
|
+
|
|
206
|
+
### Async Configuration
|
|
207
|
+
|
|
208
|
+
```typescript
|
|
209
|
+
export default defineConfig(async () => {
|
|
210
|
+
const token = await loadTokenFromVault();
|
|
211
|
+
return {
|
|
212
|
+
paths: { dotfilesDir: '~/.dotfiles' },
|
|
213
|
+
github: { token },
|
|
214
|
+
};
|
|
215
|
+
});
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### Context-Aware Configuration
|
|
219
|
+
|
|
220
|
+
```typescript
|
|
221
|
+
export default defineConfig(({ configFileDir, systemInfo }) => ({
|
|
222
|
+
paths: {
|
|
223
|
+
generatedDir: `${configFileDir}/.generated`,
|
|
224
|
+
},
|
|
225
|
+
}));
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
## Configuration Reference
|
|
229
|
+
|
|
230
|
+
### paths
|
|
231
|
+
|
|
232
|
+
```typescript
|
|
233
|
+
paths: {
|
|
234
|
+
homeDir: '~', // User's home directory
|
|
235
|
+
dotfilesDir: '~/.dotfiles', // Root dotfiles directory
|
|
236
|
+
toolConfigsDir: '~/.dotfiles/tools', // Directory with *.tool.ts files
|
|
237
|
+
generatedDir: '~/.dotfiles/.generated', // Generated files directory
|
|
238
|
+
targetDir: '/usr/local/bin', // Shim directory (must be in PATH)
|
|
239
|
+
shellScriptsDir: '~/.dotfiles/.generated/shell-scripts',
|
|
240
|
+
binariesDir: '~/.dotfiles/.generated/binaries',
|
|
241
|
+
}
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### features
|
|
245
|
+
|
|
246
|
+
#### Catalog
|
|
247
|
+
|
|
248
|
+
Auto-generates a markdown file listing all managed tools:
|
|
249
|
+
|
|
250
|
+
```typescript
|
|
251
|
+
features: {
|
|
252
|
+
catalog: {
|
|
253
|
+
generate: true, // Enable catalog generation
|
|
254
|
+
filePath: '~/.dotfiles/CATALOG.md', // Output location
|
|
255
|
+
},
|
|
256
|
+
}
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
The generated catalog includes tool names, installation methods, and available binaries.
|
|
260
|
+
|
|
261
|
+
#### Shell Installation
|
|
262
|
+
|
|
263
|
+
Automatically adds sourcing to your shell configuration:
|
|
264
|
+
|
|
265
|
+
```typescript
|
|
266
|
+
features: {
|
|
267
|
+
shellInstall: {
|
|
268
|
+
zsh: '~/.zshrc', // Path to zsh config
|
|
269
|
+
bash: '~/.bashrc', // Path to bash config
|
|
270
|
+
powershell: '~/.config/powershell/profile.ps1', // Path to PowerShell config
|
|
271
|
+
},
|
|
272
|
+
}
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
If a shell path is not provided, initialization for that shell is skipped.
|
|
276
|
+
|
|
277
|
+
### github
|
|
278
|
+
|
|
279
|
+
```typescript
|
|
280
|
+
github: {
|
|
281
|
+
host: 'https://api.github.com',
|
|
282
|
+
token: process.env.GITHUB_TOKEN, // Recommended for rate limits
|
|
283
|
+
userAgent: 'dotfiles-generator',
|
|
284
|
+
cache: {
|
|
285
|
+
enabled: true,
|
|
286
|
+
ttl: 86400000, // 24 hours in ms
|
|
287
|
+
},
|
|
288
|
+
}
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
### proxy
|
|
292
|
+
|
|
293
|
+
HTTP caching proxy to prevent API rate limiting during development:
|
|
294
|
+
|
|
295
|
+
```typescript
|
|
296
|
+
proxy: {
|
|
297
|
+
enabled: false, // Enable proxy server
|
|
298
|
+
port: 3128, // Proxy server port
|
|
299
|
+
cacheDir: '{paths.generatedDir}/.http-proxy-cache', // Cache directory
|
|
300
|
+
ttl: 86400000, // Cache TTL (24 hours)
|
|
301
|
+
}
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
When enabled, the proxy ignores server cache headers, ensuring responses are always cached for the configured TTL. Use the proxy to avoid rate limits when frequently testing tool installations.
|
|
305
|
+
|
|
306
|
+
#### Endpoints
|
|
307
|
+
|
|
308
|
+
- `POST /cache/clear` - Clear cache entries by glob pattern (use `*` to clear all)
|
|
309
|
+
- `POST /cache/populate` - Pre-populate cache entries
|
|
310
|
+
- `GET /cache/stats` - Get cache statistics
|
|
311
|
+
|
|
312
|
+
#### Standalone Usage
|
|
313
|
+
|
|
314
|
+
The proxy can also be run standalone without enabling it in the config:
|
|
315
|
+
|
|
316
|
+
```bash
|
|
317
|
+
bun run packages/http-proxy/src/server.ts --port=3128 --cache-dir=.tmp/cache
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
### system
|
|
321
|
+
|
|
322
|
+
```typescript
|
|
323
|
+
system: {
|
|
324
|
+
sudoPrompt: 'Please enter your password to continue:',
|
|
325
|
+
}
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
### updates
|
|
329
|
+
|
|
330
|
+
```typescript
|
|
331
|
+
updates: {
|
|
332
|
+
checkOnRun: true, // Check for updates on each run
|
|
333
|
+
checkInterval: 86400, // Seconds between checks (24 hours)
|
|
334
|
+
}
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
## Platform Overrides
|
|
338
|
+
|
|
339
|
+
```typescript
|
|
340
|
+
export default defineConfig(() => ({
|
|
341
|
+
paths: {
|
|
342
|
+
targetDir: '~/.local/bin',
|
|
343
|
+
},
|
|
344
|
+
platform: [
|
|
345
|
+
{
|
|
346
|
+
match: [{ platform: 'darwin', arch: 'arm64' }],
|
|
347
|
+
config: {
|
|
348
|
+
paths: { targetDir: '/opt/homebrew/bin' },
|
|
349
|
+
},
|
|
350
|
+
},
|
|
351
|
+
],
|
|
352
|
+
}));
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
## CLI Usage
|
|
356
|
+
|
|
357
|
+
```bash
|
|
358
|
+
dotfiles --config ~/.dotfiles/config.ts install
|
|
359
|
+
dotfiles install # Uses config.ts in current directory
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
## Directory Structure
|
|
363
|
+
|
|
364
|
+
```
|
|
365
|
+
~/.dotfiles/
|
|
366
|
+
├── config.ts # Project configuration
|
|
367
|
+
├── tools/ # Tool definitions (*.tool.ts)
|
|
368
|
+
├── CATALOG.md # Auto-generated
|
|
369
|
+
└── .generated/ # Not version controlled
|
|
370
|
+
├── bin/ # Shims
|
|
371
|
+
├── shell-scripts/ # Shell init scripts
|
|
372
|
+
└── binaries/ # Downloaded binaries
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
---
|
|
376
|
+
|
|
377
|
+
# Platform-Specific Configuration
|
|
378
|
+
|
|
379
|
+
Use `.platform()` for cross-platform tool configurations.
|
|
380
|
+
|
|
381
|
+
## Platform and Architecture Enums
|
|
382
|
+
|
|
383
|
+
```typescript
|
|
384
|
+
import { Architecture, Platform } from '@alexgorbatchev/dotfiles';
|
|
385
|
+
|
|
386
|
+
// Platforms (bitwise flags)
|
|
387
|
+
Platform.Linux; // 1
|
|
388
|
+
Platform.MacOS; // 2
|
|
389
|
+
Platform.Windows; // 4
|
|
390
|
+
Platform.Unix; // Linux | MacOS (3)
|
|
391
|
+
Platform.All; // All platforms (7)
|
|
392
|
+
|
|
393
|
+
// Architectures (bitwise flags)
|
|
394
|
+
Architecture.X86_64; // 1
|
|
395
|
+
Architecture.Arm64; // 2
|
|
396
|
+
Architecture.All; // Both (3)
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
## Basic Usage
|
|
400
|
+
|
|
401
|
+
```typescript
|
|
402
|
+
import { defineTool, Platform } from '@alexgorbatchev/dotfiles';
|
|
403
|
+
|
|
404
|
+
export default defineTool((install) =>
|
|
405
|
+
install()
|
|
406
|
+
.bin('tool')
|
|
407
|
+
.platform(Platform.MacOS, (install) => install('brew', { formula: 'tool' }))
|
|
408
|
+
.platform(Platform.Linux, (install) =>
|
|
409
|
+
install('github-release', {
|
|
410
|
+
repo: 'owner/tool',
|
|
411
|
+
assetPattern: '*linux*.tar.gz',
|
|
412
|
+
}))
|
|
413
|
+
.platform(Platform.Windows, (install) =>
|
|
414
|
+
install('github-release', {
|
|
415
|
+
repo: 'owner/tool',
|
|
416
|
+
assetPattern: '*windows*.zip',
|
|
417
|
+
}))
|
|
418
|
+
);
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
## With Architecture
|
|
422
|
+
|
|
423
|
+
```typescript
|
|
424
|
+
import { Architecture, defineTool, Platform } from '@alexgorbatchev/dotfiles';
|
|
425
|
+
|
|
426
|
+
export default defineTool((install) =>
|
|
427
|
+
install()
|
|
428
|
+
.bin('tool')
|
|
429
|
+
.platform(Platform.Linux, Architecture.X86_64, (install) =>
|
|
430
|
+
install('github-release', {
|
|
431
|
+
repo: 'owner/tool',
|
|
432
|
+
assetPattern: '*linux-amd64*.tar.gz',
|
|
433
|
+
}))
|
|
434
|
+
.platform(Platform.Linux, Architecture.Arm64, (install) =>
|
|
435
|
+
install('github-release', {
|
|
436
|
+
repo: 'owner/tool',
|
|
437
|
+
assetPattern: '*linux-arm64*.tar.gz',
|
|
438
|
+
}))
|
|
439
|
+
.platform(Platform.MacOS, Architecture.All, (install) => install('brew', { formula: 'tool' }))
|
|
440
|
+
);
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
## Platform Groups
|
|
444
|
+
|
|
445
|
+
Use `Platform.Unix` for shared Linux/macOS configuration:
|
|
446
|
+
|
|
447
|
+
```typescript
|
|
448
|
+
export default defineTool((install) =>
|
|
449
|
+
install()
|
|
450
|
+
.bin('tool')
|
|
451
|
+
.platform(Platform.Unix, (install) =>
|
|
452
|
+
install('github-release', {
|
|
453
|
+
repo: 'owner/tool',
|
|
454
|
+
assetPattern: '*unix*.tar.gz',
|
|
455
|
+
}))
|
|
456
|
+
.platform(Platform.Windows, (install) =>
|
|
457
|
+
install('github-release', {
|
|
458
|
+
repo: 'owner/tool',
|
|
459
|
+
assetPattern: '*windows*.zip',
|
|
460
|
+
}))
|
|
461
|
+
);
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
## Platform-Specific Shell Config
|
|
465
|
+
|
|
466
|
+
```typescript
|
|
467
|
+
export default defineTool((install) =>
|
|
468
|
+
install('github-release', { repo: 'owner/tool' })
|
|
469
|
+
.bin('tool')
|
|
470
|
+
.platform(Platform.Unix, (install) =>
|
|
471
|
+
install().zsh((shell) =>
|
|
472
|
+
shell.env({
|
|
473
|
+
TOOL_CONFIG: '~/.config/tool',
|
|
474
|
+
})
|
|
475
|
+
))
|
|
476
|
+
.platform(Platform.Windows, (install) =>
|
|
477
|
+
install().powershell((shell) =>
|
|
478
|
+
shell.env({
|
|
479
|
+
TOOL_CONFIG: '~\\.config\\tool',
|
|
480
|
+
})
|
|
481
|
+
))
|
|
482
|
+
);
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
## Platform Detection in Hooks
|
|
486
|
+
|
|
487
|
+
```typescript
|
|
488
|
+
export default defineTool((install) =>
|
|
489
|
+
install('github-release', { repo: 'owner/tool' })
|
|
490
|
+
.bin('tool')
|
|
491
|
+
.hook('after-install', async ({ systemInfo, $ }) => {
|
|
492
|
+
if (systemInfo.platform === 'darwin') {
|
|
493
|
+
await $`./setup-macos.sh`;
|
|
494
|
+
} else if (systemInfo.platform === 'linux') {
|
|
495
|
+
await $`./setup-linux.sh`;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
if (systemInfo.arch === 'arm64') {
|
|
499
|
+
await $`./configure-arm64.sh`;
|
|
500
|
+
}
|
|
501
|
+
})
|
|
502
|
+
);
|
|
503
|
+
```
|
|
504
|
+
|
|
505
|
+
## Common Asset Patterns
|
|
506
|
+
|
|
507
|
+
| Platform | Pattern Examples |
|
|
508
|
+
| -------- | ---------------------------------------------- |
|
|
509
|
+
| macOS | `*darwin*.tar.gz`, `*macos*.zip` |
|
|
510
|
+
| Linux | `*linux*.tar.gz`, `*x86_64-unknown-linux-gnu*` |
|
|
511
|
+
| Windows | `*windows*.zip`, `*pc-windows-msvc*` |
|
|
512
|
+
| x86_64 | `*amd64*`, `*x86_64*` |
|
|
513
|
+
| ARM64 | `*arm64*`, `*aarch64*` |
|
|
514
|
+
|
|
515
|
+
---
|
|
516
|
+
|
|
517
|
+
# Virtual Environments
|
|
518
|
+
|
|
519
|
+
Virtual environments allow you to create isolated dotfiles configurations for different projects, similar to Python's `venv`, `pyenv`, or Hermit.
|
|
520
|
+
|
|
521
|
+
## Overview
|
|
522
|
+
|
|
523
|
+
Instead of a single global dotfiles configuration, you can create project-specific environments with their own:
|
|
524
|
+
|
|
525
|
+
- Tool configurations
|
|
526
|
+
- Generated shell scripts
|
|
527
|
+
- Installed binaries
|
|
528
|
+
- XDG configuration files
|
|
529
|
+
|
|
530
|
+
## Creating an Environment
|
|
531
|
+
|
|
532
|
+
```bash
|
|
533
|
+
# Create with default name 'env' in current directory
|
|
534
|
+
dotfiles env create
|
|
535
|
+
|
|
536
|
+
# Create with custom name
|
|
537
|
+
dotfiles env create my-env
|
|
538
|
+
|
|
539
|
+
# Create at absolute path
|
|
540
|
+
dotfiles env create /path/to/project/.devenv
|
|
541
|
+
```
|
|
542
|
+
|
|
543
|
+
This creates:
|
|
544
|
+
|
|
545
|
+
```
|
|
546
|
+
env/
|
|
547
|
+
├── source # POSIX shell activation script
|
|
548
|
+
├── source.ps1 # PowerShell activation script
|
|
549
|
+
├── config.ts # Dotfiles configuration
|
|
550
|
+
├── .config/ # XDG_CONFIG_HOME for tool configs
|
|
551
|
+
└── tools/ # Tool configuration directory
|
|
552
|
+
```
|
|
553
|
+
|
|
554
|
+
## Activating an Environment
|
|
555
|
+
|
|
556
|
+
**Bash/Zsh:**
|
|
557
|
+
|
|
558
|
+
```bash
|
|
559
|
+
source env/source
|
|
560
|
+
```
|
|
561
|
+
|
|
562
|
+
**PowerShell:**
|
|
563
|
+
|
|
564
|
+
```powershell
|
|
565
|
+
. .\env\source.ps1
|
|
566
|
+
```
|
|
567
|
+
|
|
568
|
+
When activated, the following environment variables are set:
|
|
569
|
+
|
|
570
|
+
| Variable | Value |
|
|
571
|
+
| ------------------- | ------------------------------------ |
|
|
572
|
+
| `DOTFILES_ENV_DIR` | Absolute path to environment |
|
|
573
|
+
| `DOTFILES_ENV_NAME` | Environment directory name |
|
|
574
|
+
| `XDG_CONFIG_HOME` | `$DOTFILES_ENV_DIR/.config` |
|
|
575
|
+
| `PATH` | Prepended with environment's bin dir |
|
|
576
|
+
|
|
577
|
+
## Using an Activated Environment
|
|
578
|
+
|
|
579
|
+
Once activated, all dotfiles commands use the environment's configuration automatically:
|
|
580
|
+
|
|
581
|
+
```bash
|
|
582
|
+
source env/source
|
|
583
|
+
|
|
584
|
+
# These all use env/config.ts automatically
|
|
585
|
+
dotfiles generate
|
|
586
|
+
dotfiles install
|
|
587
|
+
dotfiles update fd
|
|
588
|
+
```
|
|
589
|
+
|
|
590
|
+
No need to pass `--config` - the CLI detects `DOTFILES_ENV_DIR` and uses its `config.ts`.
|
|
591
|
+
|
|
592
|
+
## Adding Tools
|
|
593
|
+
|
|
594
|
+
Create tool configuration files in the `tools/` directory:
|
|
595
|
+
|
|
596
|
+
```bash
|
|
597
|
+
source env/source
|
|
598
|
+
|
|
599
|
+
cat > env/tools/fd.tool.ts << 'EOF'
|
|
600
|
+
import { defineTool } from '@alexgorbatchev/dotfiles';
|
|
601
|
+
|
|
602
|
+
export default defineTool((install) =>
|
|
603
|
+
install('github-release', { repo: 'sharkdp/fd' })
|
|
604
|
+
.bin('fd')
|
|
605
|
+
);
|
|
606
|
+
EOF
|
|
607
|
+
|
|
608
|
+
dotfiles generate
|
|
609
|
+
dotfiles install fd
|
|
610
|
+
```
|
|
611
|
+
|
|
612
|
+
## Deactivating
|
|
613
|
+
|
|
614
|
+
```bash
|
|
615
|
+
dotfiles-deactivate
|
|
616
|
+
```
|
|
617
|
+
|
|
618
|
+
This restores the previous `PATH` and `XDG_CONFIG_HOME` values.
|
|
619
|
+
|
|
620
|
+
## Deleting an Environment
|
|
621
|
+
|
|
622
|
+
```bash
|
|
623
|
+
# Delete default 'env' directory
|
|
624
|
+
dotfiles env delete
|
|
625
|
+
|
|
626
|
+
# Delete specific environment
|
|
627
|
+
dotfiles env delete my-env
|
|
628
|
+
|
|
629
|
+
# Force delete without confirmation
|
|
630
|
+
dotfiles env delete --force
|
|
631
|
+
```
|
|
632
|
+
|
|
633
|
+
## Use Cases
|
|
634
|
+
|
|
635
|
+
### Project-Specific Tools
|
|
636
|
+
|
|
637
|
+
Keep project tools isolated from your global configuration:
|
|
638
|
+
|
|
639
|
+
```bash
|
|
640
|
+
cd ~/projects/data-science
|
|
641
|
+
dotfiles env create
|
|
642
|
+
source env/source
|
|
643
|
+
|
|
644
|
+
# Add project-specific tools
|
|
645
|
+
cat > env/tools/jupyter.tool.ts << 'EOF'
|
|
646
|
+
import { defineTool } from '@alexgorbatchev/dotfiles';
|
|
647
|
+
export default defineTool((install) =>
|
|
648
|
+
install('manual').bin('jupyter')
|
|
649
|
+
.zsh((shell) => shell.aliases({
|
|
650
|
+
jn: 'jupyter notebook',
|
|
651
|
+
jl: 'jupyter lab'
|
|
652
|
+
}))
|
|
653
|
+
);
|
|
654
|
+
EOF
|
|
655
|
+
|
|
656
|
+
dotfiles generate
|
|
657
|
+
```
|
|
658
|
+
|
|
659
|
+
### Team Environments
|
|
660
|
+
|
|
661
|
+
Share tool configurations with your team:
|
|
662
|
+
|
|
663
|
+
```bash
|
|
664
|
+
cd ~/work/team-project
|
|
665
|
+
dotfiles env create .devenv
|
|
666
|
+
|
|
667
|
+
# Configure shared tools
|
|
668
|
+
# ...
|
|
669
|
+
|
|
670
|
+
# Add to version control
|
|
671
|
+
echo ".devenv/.generated" >> .gitignore
|
|
672
|
+
git add .devenv/config.ts .devenv/tools/ .devenv/source .devenv/source.ps1
|
|
673
|
+
git commit -m "Add development environment"
|
|
674
|
+
```
|
|
675
|
+
|
|
676
|
+
Team members then run:
|
|
677
|
+
|
|
678
|
+
```bash
|
|
679
|
+
git clone <repo>
|
|
680
|
+
cd team-project
|
|
681
|
+
source .devenv/source
|
|
682
|
+
dotfiles install
|
|
683
|
+
```
|
|
684
|
+
|
|
685
|
+
### Multiple Environments
|
|
686
|
+
|
|
687
|
+
Different projects can have different tool versions:
|
|
688
|
+
|
|
689
|
+
```bash
|
|
690
|
+
# Project A uses older tools
|
|
691
|
+
cd ~/projects/legacy
|
|
692
|
+
dotfiles env create
|
|
693
|
+
source env/source
|
|
694
|
+
# Configure tools...
|
|
695
|
+
|
|
696
|
+
# Project B uses latest
|
|
697
|
+
cd ~/projects/modern
|
|
698
|
+
dotfiles env create
|
|
699
|
+
source env/source
|
|
700
|
+
# Configure different versions...
|
|
701
|
+
```
|
|
702
|
+
|
|
703
|
+
## XDG Configuration Isolation
|
|
704
|
+
|
|
705
|
+
The environment sets `XDG_CONFIG_HOME` to isolate tool configuration files:
|
|
706
|
+
|
|
707
|
+
```bash
|
|
708
|
+
source env/source
|
|
709
|
+
echo $XDG_CONFIG_HOME
|
|
710
|
+
# /path/to/env/.config
|
|
711
|
+
|
|
712
|
+
# Tools that respect XDG will store config here
|
|
713
|
+
# e.g., ~/.config/nvim becomes env/.config/nvim
|
|
714
|
+
```
|
|
715
|
+
|
|
716
|
+
This prevents activated environments from affecting global tool configurations.
|
|
717
|
+
|
|
718
|
+
## Generated Files
|
|
719
|
+
|
|
720
|
+
After running `dotfiles generate`, the environment contains:
|
|
721
|
+
|
|
722
|
+
```
|
|
723
|
+
env/
|
|
724
|
+
├── .generated/
|
|
725
|
+
│ ├── shell-scripts/
|
|
726
|
+
│ │ ├── main.zsh
|
|
727
|
+
│ │ ├── main.bash
|
|
728
|
+
│ │ └── main.ps1
|
|
729
|
+
│ ├── user-bin/
|
|
730
|
+
│ │ └── <tool shims>
|
|
731
|
+
│ └── binaries/
|
|
732
|
+
│ └── <installed tools>
|
|
733
|
+
├── source
|
|
734
|
+
├── source.ps1
|
|
735
|
+
├── config.ts
|
|
736
|
+
├── .config/
|
|
737
|
+
└── tools/
|
|
738
|
+
```
|
|
739
|
+
|
|
740
|
+
The activation script sources the generated shell scripts and adds `user-bin` to PATH.
|
|
741
|
+
|
|
742
|
+
---
|
|
743
|
+
|
|
744
|
+
# Common Patterns
|
|
745
|
+
|
|
746
|
+
Real-world examples for common tool configuration scenarios.
|
|
747
|
+
|
|
748
|
+
## GitHub Tool with Shell Integration
|
|
749
|
+
|
|
750
|
+
```typescript
|
|
751
|
+
import { defineTool } from '@alexgorbatchev/dotfiles';
|
|
752
|
+
|
|
753
|
+
export default defineTool((install, ctx) =>
|
|
754
|
+
install('github-release', { repo: 'BurntSushi/ripgrep' })
|
|
755
|
+
.bin('rg')
|
|
756
|
+
.zsh((shell) => shell.completions('complete/_rg').aliases({ rg: 'ripgrep' }))
|
|
757
|
+
.bash((shell) => shell.completions('complete/rg.bash'))
|
|
758
|
+
);
|
|
759
|
+
```
|
|
760
|
+
|
|
761
|
+
## Tool Dependencies
|
|
762
|
+
|
|
763
|
+
Use `.dependsOn()` when a tool needs other binaries to exist first:
|
|
764
|
+
|
|
765
|
+
```typescript
|
|
766
|
+
// provider.tool.ts
|
|
767
|
+
export default defineTool((install) => install('manual', { binaryPath: './bin/provider' }).bin('provider'));
|
|
768
|
+
|
|
769
|
+
// consumer.tool.ts
|
|
770
|
+
export default defineTool((install) =>
|
|
771
|
+
install('github-release', { repo: 'owner/consumer' }).bin('consumer').dependsOn('provider')
|
|
772
|
+
);
|
|
773
|
+
```
|
|
774
|
+
|
|
775
|
+
## Complex Shell Integration
|
|
776
|
+
|
|
777
|
+
```typescript
|
|
778
|
+
import { defineTool } from '@alexgorbatchev/dotfiles';
|
|
779
|
+
|
|
780
|
+
export default defineTool((install, ctx) =>
|
|
781
|
+
install('github-release', { repo: 'junegunn/fzf' })
|
|
782
|
+
.bin('fzf')
|
|
783
|
+
.zsh((shell) =>
|
|
784
|
+
shell.env({ FZF_DEFAULT_OPTS: '--color=fg+:cyan' }).completions('shell/completion.zsh').always(/* zsh */ `
|
|
785
|
+
if [[ -f "${ctx.currentDir}/shell/key-bindings.zsh" ]]; then
|
|
786
|
+
source "${ctx.currentDir}/shell/key-bindings.zsh"
|
|
787
|
+
fi
|
|
788
|
+
`)
|
|
789
|
+
)
|
|
790
|
+
);
|
|
791
|
+
```
|
|
792
|
+
|
|
793
|
+
## Cross-Shell Configuration
|
|
794
|
+
|
|
795
|
+
```typescript
|
|
796
|
+
export default defineTool((install) =>
|
|
797
|
+
install('github-release', { repo: 'owner/tool' })
|
|
798
|
+
.bin('tool')
|
|
799
|
+
.zsh((shell) =>
|
|
800
|
+
shell.completions('completions/_tool').env({ TOOL_CONFIG: '~/.config/tool' }).aliases({ t: 'tool' })
|
|
801
|
+
)
|
|
802
|
+
.bash((shell) =>
|
|
803
|
+
shell.completions('completions/tool.bash').env({ TOOL_CONFIG: '~/.config/tool' }).aliases({ t: 'tool' })
|
|
804
|
+
)
|
|
805
|
+
);
|
|
806
|
+
```
|
|
807
|
+
|
|
808
|
+
## With Hooks
|
|
809
|
+
|
|
810
|
+
```typescript
|
|
811
|
+
import { defineTool } from '@alexgorbatchev/dotfiles';
|
|
812
|
+
|
|
813
|
+
export default defineTool((install) =>
|
|
814
|
+
install('github-release', { repo: 'owner/tool' })
|
|
815
|
+
.bin('tool')
|
|
816
|
+
.symlink('./config.yml', '~/.config/tool/config.yml')
|
|
817
|
+
.hook('after-install', async ({ installedDir, fileSystem, $ }) => {
|
|
818
|
+
await $`${installedDir}/tool init`;
|
|
819
|
+
})
|
|
820
|
+
);
|
|
821
|
+
```
|
|
822
|
+
|
|
823
|
+
## Platform-Specific Installation
|
|
824
|
+
|
|
825
|
+
```typescript
|
|
826
|
+
import { Architecture, defineTool, Platform } from '@alexgorbatchev/dotfiles';
|
|
827
|
+
|
|
828
|
+
export default defineTool((install, ctx) =>
|
|
829
|
+
install('github-release', { repo: 'owner/tool' })
|
|
830
|
+
.bin('tool')
|
|
831
|
+
.platform(Platform.MacOS, (installMac) => installMac('brew', { formula: 'tool' }))
|
|
832
|
+
.platform(Platform.Linux, (installLinux) =>
|
|
833
|
+
installLinux('github-release', {
|
|
834
|
+
repo: 'owner/tool',
|
|
835
|
+
assetPattern: '*linux*.tar.gz',
|
|
836
|
+
}))
|
|
837
|
+
.platform(Platform.Windows, Architecture.Arm64, (installWin) =>
|
|
838
|
+
installWin('github-release', {
|
|
839
|
+
repo: 'owner/tool',
|
|
840
|
+
assetPattern: '*windows-arm64.zip',
|
|
841
|
+
}))
|
|
842
|
+
);
|
|
843
|
+
```
|
|
844
|
+
|
|
845
|
+
## Cargo (Rust) Tool
|
|
846
|
+
|
|
847
|
+
```typescript
|
|
848
|
+
export default defineTool((install) =>
|
|
849
|
+
install('cargo', {
|
|
850
|
+
crateName: 'eza',
|
|
851
|
+
githubRepo: 'eza-community/eza',
|
|
852
|
+
})
|
|
853
|
+
.bin('eza')
|
|
854
|
+
.zsh((shell) => shell.completions('completions/eza.zsh').aliases({ ls: 'eza', ll: 'eza -l', la: 'eza -la' }))
|
|
855
|
+
);
|
|
856
|
+
```
|
|
857
|
+
|
|
858
|
+
## Manual Script
|
|
859
|
+
|
|
860
|
+
```typescript
|
|
861
|
+
export default defineTool((install) =>
|
|
862
|
+
install('manual', { binaryPath: './scripts/deploy.sh' })
|
|
863
|
+
.bin('deploy')
|
|
864
|
+
.symlink('./deploy.config.yaml', '~/.config/deploy/config.yaml')
|
|
865
|
+
.zsh((shell) =>
|
|
866
|
+
shell.aliases({
|
|
867
|
+
dp: 'deploy',
|
|
868
|
+
'deploy-prod': 'deploy --env production',
|
|
869
|
+
})
|
|
870
|
+
)
|
|
871
|
+
);
|
|
872
|
+
```
|
|
873
|
+
|
|
874
|
+
## Configuration-Only (No Binary)
|
|
875
|
+
|
|
876
|
+
```typescript
|
|
877
|
+
export default defineTool((install) =>
|
|
878
|
+
install()
|
|
879
|
+
.symlink('./gitconfig', '~/.gitconfig')
|
|
880
|
+
.zsh((shell) => shell.aliases({ g: 'git', gs: 'git status', ga: 'git add' }).env({ GIT_EDITOR: 'nvim' }))
|
|
881
|
+
);
|
|
882
|
+
```
|
|
883
|
+
|
|
884
|
+
## Custom Asset Selection
|
|
885
|
+
|
|
886
|
+
```typescript
|
|
887
|
+
export default defineTool((install) =>
|
|
888
|
+
install('github-release', {
|
|
889
|
+
repo: 'owner/tool',
|
|
890
|
+
assetSelector: ({ assets, systemInfo }) => {
|
|
891
|
+
const platformMap: Record<string, string> = { darwin: 'macos', linux: 'linux' };
|
|
892
|
+
const archMap: Record<string, string> = { x64: 'amd64', arm64: 'arm64' };
|
|
893
|
+
const platform = platformMap[systemInfo.platform];
|
|
894
|
+
const arch = archMap[systemInfo.arch];
|
|
895
|
+
return assets.find((a) => a.name.includes(platform) && a.name.includes(arch) && a.name.endsWith('.tar.gz'));
|
|
896
|
+
},
|
|
897
|
+
}).bin('tool')
|
|
898
|
+
);
|
|
899
|
+
```
|
|
900
|
+
|
|
901
|
+
## Installation Method Quick Reference
|
|
902
|
+
|
|
903
|
+
| Use Case | Method | Example Tools |
|
|
904
|
+
| ----------------- | ---------------- | ------------------ |
|
|
905
|
+
| GitHub releases | `github-release` | fzf, ripgrep, bat |
|
|
906
|
+
| Gitea/Forgejo | `gitea-release` | Codeberg tools |
|
|
907
|
+
| Homebrew | `brew` | git, jq |
|
|
908
|
+
| Rust crates | `cargo` | eza, fd, ripgrep |
|
|
909
|
+
| npm packages | `npm` | prettier, eslint |
|
|
910
|
+
| Custom scripts | `manual` | deployment scripts |
|
|
911
|
+
| Shell config only | `install()` | aliases, env vars |
|
|
912
|
+
| Installer scripts | `curl-script` | rustup, nvm |
|
|
913
|
+
| Direct binaries | `curl-binary` | single-file tools |
|
|
914
|
+
|
|
915
|
+
---
|
|
916
|
+
|
|
917
|
+
# Advanced Topics
|
|
918
|
+
|
|
919
|
+
Advanced configuration patterns for complex setups.
|
|
920
|
+
|
|
921
|
+
## Custom Asset Selection
|
|
922
|
+
|
|
923
|
+
For non-standard release naming, use `assetSelector`:
|
|
924
|
+
|
|
925
|
+
```typescript
|
|
926
|
+
export default defineTool((install) =>
|
|
927
|
+
install('github-release', {
|
|
928
|
+
repo: 'owner/tool',
|
|
929
|
+
assetSelector: ({ assets, systemInfo, release, log }) => {
|
|
930
|
+
const osMap: Record<string, string> = { darwin: 'macos', linux: 'linux' };
|
|
931
|
+
const archMap: Record<string, string> = { x64: 'amd64', arm64: 'arm64' };
|
|
932
|
+
|
|
933
|
+
return assets.find(
|
|
934
|
+
(a) =>
|
|
935
|
+
a.name.includes(osMap[systemInfo.platform]) &&
|
|
936
|
+
a.name.includes(archMap[systemInfo.arch]) &&
|
|
937
|
+
a.name.endsWith('.tar.gz'),
|
|
938
|
+
);
|
|
939
|
+
},
|
|
940
|
+
}).bin('tool')
|
|
941
|
+
);
|
|
942
|
+
```
|
|
943
|
+
|
|
944
|
+
## Dynamic Configuration
|
|
945
|
+
|
|
946
|
+
Use environment variables for runtime configuration:
|
|
947
|
+
|
|
948
|
+
```typescript
|
|
949
|
+
const isDev = process.env.NODE_ENV === 'development';
|
|
950
|
+
|
|
951
|
+
export default defineTool((install) =>
|
|
952
|
+
install('github-release', { repo: 'owner/tool' })
|
|
953
|
+
.bin('tool')
|
|
954
|
+
.version(isDev ? 'latest' : 'v1.2.3')
|
|
955
|
+
.zsh((shell) => shell.env({ TOOL_LOG_LEVEL: isDev ? 'debug' : 'info' }))
|
|
956
|
+
);
|
|
957
|
+
```
|
|
958
|
+
|
|
959
|
+
## Conditional Installation
|
|
960
|
+
|
|
961
|
+
Choose methods based on system capabilities:
|
|
962
|
+
|
|
963
|
+
```typescript
|
|
964
|
+
export default defineTool((install) => {
|
|
965
|
+
if (process.platform === 'darwin' && process.env.HOMEBREW_PREFIX) {
|
|
966
|
+
return install('brew', { formula: 'tool' }).bin('tool');
|
|
967
|
+
}
|
|
968
|
+
return install('github-release', { repo: 'owner/tool' }).bin('tool');
|
|
969
|
+
});
|
|
970
|
+
```
|
|
971
|
+
|
|
972
|
+
## Build from Source
|
|
973
|
+
|
|
974
|
+
```typescript
|
|
975
|
+
export default defineTool((install) =>
|
|
976
|
+
install('github-release', { repo: 'owner/tool' })
|
|
977
|
+
.bin('tool')
|
|
978
|
+
.hook('after-extract', async ({ extractDir, stagingDir, $ }) => {
|
|
979
|
+
if (extractDir && stagingDir) {
|
|
980
|
+
await $`cd ${extractDir} && ./configure --prefix=${stagingDir}`;
|
|
981
|
+
await $`cd ${extractDir} && make -j$(nproc)`;
|
|
982
|
+
await $`cd ${extractDir} && make install`;
|
|
983
|
+
}
|
|
984
|
+
})
|
|
985
|
+
);
|
|
986
|
+
```
|
|
987
|
+
|
|
988
|
+
## Dependency Verification
|
|
989
|
+
|
|
990
|
+
Combine `.dependsOn()` with hooks for version checks:
|
|
991
|
+
|
|
992
|
+
```typescript
|
|
993
|
+
export default defineTool((install) =>
|
|
994
|
+
install('github-release', { repo: 'owner/tool' })
|
|
995
|
+
.bin('tool')
|
|
996
|
+
.dependsOn('node')
|
|
997
|
+
.hook('before-install', async ({ log, $ }) => {
|
|
998
|
+
const result = await $`node --version`.nothrow();
|
|
999
|
+
if (result.exitCode !== 0) {
|
|
1000
|
+
throw new Error('Node is required but not available');
|
|
1001
|
+
}
|
|
1002
|
+
log.info(`Using Node ${result.stdout.toString().trim()}`);
|
|
1003
|
+
})
|
|
1004
|
+
);
|
|
1005
|
+
```
|
|
1006
|
+
|
|
1007
|
+
## Lazy Loading
|
|
1008
|
+
|
|
1009
|
+
```typescript
|
|
1010
|
+
export default defineTool((install, ctx) =>
|
|
1011
|
+
install('github-release', { repo: 'owner/tool' })
|
|
1012
|
+
.bin('tool')
|
|
1013
|
+
.zsh((shell) =>
|
|
1014
|
+
shell.always(`
|
|
1015
|
+
function expensive-fn() {
|
|
1016
|
+
unfunction expensive-fn
|
|
1017
|
+
source "${ctx.currentDir}/expensive.zsh"
|
|
1018
|
+
expensive-fn "$@"
|
|
1019
|
+
}
|
|
1020
|
+
`)
|
|
1021
|
+
)
|
|
1022
|
+
);
|
|
1023
|
+
```
|
|
1024
|
+
|
|
1025
|
+
## Dynamic Completions
|
|
1026
|
+
|
|
1027
|
+
```typescript
|
|
1028
|
+
export default defineTool((install, ctx) =>
|
|
1029
|
+
install('github-release', { repo: 'owner/tool' })
|
|
1030
|
+
.bin('tool')
|
|
1031
|
+
.zsh((shell) =>
|
|
1032
|
+
shell
|
|
1033
|
+
.once(
|
|
1034
|
+
`
|
|
1035
|
+
tool completion zsh > "${ctx.projectConfig.paths.generatedDir}/completions/_tool"
|
|
1036
|
+
`,
|
|
1037
|
+
)
|
|
1038
|
+
.completions(`${ctx.projectConfig.paths.generatedDir}/completions/_tool`)
|
|
1039
|
+
)
|
|
1040
|
+
);
|
|
1041
|
+
```
|
|
1042
|
+
|
|
1043
|
+
## Parallel Setup Tasks
|
|
1044
|
+
|
|
1045
|
+
```typescript
|
|
1046
|
+
export default defineTool((install) =>
|
|
1047
|
+
install('github-release', { repo: 'owner/tool' })
|
|
1048
|
+
.bin('tool')
|
|
1049
|
+
.hook('after-install', async ({ $, log }) => {
|
|
1050
|
+
await Promise.all([$`tool setup-task-1`, $`tool setup-task-2`, $`tool setup-task-3`]);
|
|
1051
|
+
log.info('All setup tasks completed');
|
|
1052
|
+
})
|
|
1053
|
+
);
|
|
1054
|
+
```
|
|
1055
|
+
|
|
1056
|
+
---
|
|
1057
|
+
|
|
1058
|
+
# Troubleshooting
|
|
1059
|
+
|
|
1060
|
+
## Enable Debug Logging
|
|
1061
|
+
|
|
1062
|
+
```bash
|
|
1063
|
+
dotfiles install tool-name --trace --log=verbose
|
|
1064
|
+
```
|
|
1065
|
+
|
|
1066
|
+
## Common Issues
|
|
1067
|
+
|
|
1068
|
+
### Tool Not Found After Installation
|
|
1069
|
+
|
|
1070
|
+
1. Verify `.bin()` is called with correct binary names
|
|
1071
|
+
2. Check shim exists: `ls -la ~/.generated/usr-local-bin/tool-name`
|
|
1072
|
+
3. Ensure PATH includes generated bin directory
|
|
1073
|
+
|
|
1074
|
+
### Installation Fails
|
|
1075
|
+
|
|
1076
|
+
1. Check asset patterns match actual GitHub release assets
|
|
1077
|
+
2. Verify repository name is correct
|
|
1078
|
+
3. Use `--trace --log=verbose` to see detailed error messages
|
|
1079
|
+
|
|
1080
|
+
### Infinite Recursion Error
|
|
1081
|
+
|
|
1082
|
+
**Message**: "Recursive installation detected for [TOOL]. Aborting..."
|
|
1083
|
+
|
|
1084
|
+
The installer has built-in recursion guards. If you see this, check that your installation scripts don't call the tool being installed via its shim.
|
|
1085
|
+
|
|
1086
|
+
### Disable Shim Usage Tracking
|
|
1087
|
+
|
|
1088
|
+
Shim usage tracking is enabled by default and runs in the background.
|
|
1089
|
+
|
|
1090
|
+
- Disable temporarily for a single command:
|
|
1091
|
+
`DOTFILES_USAGE_TRACKING=0 rg --version`
|
|
1092
|
+
- Disable for the current shell session:
|
|
1093
|
+
`export DOTFILES_USAGE_TRACKING=0`
|
|
1094
|
+
|
|
1095
|
+
### Dependency Errors
|
|
1096
|
+
|
|
1097
|
+
**Messages**: "Missing dependency", "Ambiguous dependency", "Circular dependency"
|
|
1098
|
+
|
|
1099
|
+
- Ensure every `.dependsOn()` references a binary from `.bin()` in exactly one tool
|
|
1100
|
+
- Verify providers include active platform/architecture for platform-specific configs
|
|
1101
|
+
|
|
1102
|
+
### Shell Integration Not Working
|
|
1103
|
+
|
|
1104
|
+
1. Source shell scripts: `source ~/.generated/shell-scripts/main.zsh`
|
|
1105
|
+
2. Check for syntax errors: `zsh -n ~/.generated/shell-scripts/main.zsh`
|
|
1106
|
+
3. Use declarative `.env()` instead of inline exports
|
|
1107
|
+
|
|
1108
|
+
### Completions Not Loading
|
|
1109
|
+
|
|
1110
|
+
1. Check completion file exists in extracted archive
|
|
1111
|
+
2. Reload completions: `autoload -U compinit && compinit`
|
|
1112
|
+
3. Verify shell completion path is correct
|
|
1113
|
+
|
|
1114
|
+
### Hook Not Executing
|
|
1115
|
+
|
|
1116
|
+
```typescript
|
|
1117
|
+
.hook('after-install', async ({ log, $ }) => {
|
|
1118
|
+
try {
|
|
1119
|
+
await $`./setup.sh`;
|
|
1120
|
+
} catch (error) {
|
|
1121
|
+
log.error('Setup failed');
|
|
1122
|
+
throw error;
|
|
1123
|
+
}
|
|
1124
|
+
})
|
|
1125
|
+
```
|
|
1126
|
+
|
|
1127
|
+
- `$` uses tool directory as cwd
|
|
1128
|
+
- Always await `$` commands
|
|
1129
|
+
- Handle errors with try/catch
|
|
1130
|
+
|
|
1131
|
+
## Testing and Verification
|
|
1132
|
+
|
|
1133
|
+
### Type Checking
|
|
1134
|
+
|
|
1135
|
+
```bash
|
|
1136
|
+
bun typecheck
|
|
1137
|
+
```
|
|
1138
|
+
|
|
1139
|
+
### Installation Commands
|
|
1140
|
+
|
|
1141
|
+
```bash
|
|
1142
|
+
dotfiles install tool-name # Install by tool name
|
|
1143
|
+
dotfiles install binary-name # Install by binary name
|
|
1144
|
+
dotfiles install tool-name --force # Force reinstall
|
|
1145
|
+
dotfiles install tool-name --trace --log=verbose # Debug logging
|
|
1146
|
+
dotfiles files tool-name # List generated files
|
|
1147
|
+
dotfiles check-updates # Check all for updates
|
|
1148
|
+
```
|
|
1149
|
+
|
|
1150
|
+
### Verification Steps
|
|
1151
|
+
|
|
1152
|
+
1. **Binary works**: `tool-name --version`
|
|
1153
|
+
2. **Shim created**: `ls -la ~/.generated/usr-local-bin/tool-name`
|
|
1154
|
+
3. **Shell integration**: Source shell scripts and test aliases/environment
|