@udondan/avanti 0.13.0 → 0.14.0
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/README.md +289 -264
- package/dist/commands/diff.d.ts.map +1 -1
- package/dist/commands/diff.js +116 -32
- package/dist/commands/diff.js.map +1 -1
- package/dist/commands/lock.js +19 -10
- package/dist/commands/lock.js.map +1 -1
- package/dist/commands/log.js +18 -9
- package/dist/commands/log.js.map +1 -1
- package/dist/commands/pull.d.ts.map +1 -1
- package/dist/commands/pull.js +142 -36
- package/dist/commands/pull.js.map +1 -1
- package/dist/commands/reset.js +18 -9
- package/dist/commands/reset.js.map +1 -1
- package/dist/commands/revert.js +18 -9
- package/dist/commands/revert.js.map +1 -1
- package/dist/config-writeback.d.ts.map +1 -1
- package/dist/config-writeback.js +44 -18
- package/dist/config-writeback.js.map +1 -1
- package/dist/config.d.ts +1 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +96 -62
- package/dist/config.js.map +1 -1
- package/dist/diff.js +22 -13
- package/dist/diff.js.map +1 -1
- package/dist/fetch.d.ts +0 -1
- package/dist/fetch.d.ts.map +1 -1
- package/dist/fetch.js +2 -2
- package/dist/fetch.js.map +1 -1
- package/dist/history.js +17 -7
- package/dist/history.js.map +1 -1
- package/dist/processors/json.js +2 -3
- package/dist/processors/json.js.map +1 -1
- package/dist/processors/post.js +1 -2
- package/dist/processors/post.js.map +1 -1
- package/dist/processors/replace.js +1 -2
- package/dist/processors/replace.js.map +1 -1
- package/dist/processors/yaml.js +2 -3
- package/dist/processors/yaml.js.map +1 -1
- package/dist/prompt.js +18 -9
- package/dist/prompt.js.map +1 -1
- package/dist/sha.js +18 -9
- package/dist/sha.js.map +1 -1
- package/dist/sources/bitbucket.js +18 -9
- package/dist/sources/bitbucket.js.map +1 -1
- package/dist/sources/exec.js +1 -2
- package/dist/sources/exec.js.map +1 -1
- package/dist/sources/git.js +18 -9
- package/dist/sources/git.js.map +1 -1
- package/dist/sources/github.js +18 -9
- package/dist/sources/github.js.map +1 -1
- package/dist/sources/gitlab.js +18 -9
- package/dist/sources/gitlab.js.map +1 -1
- package/dist/sources/http.d.ts +3 -0
- package/dist/sources/http.d.ts.map +1 -1
- package/dist/sources/http.js +24 -12
- package/dist/sources/http.js.map +1 -1
- package/dist/sources/index.d.ts +4 -1
- package/dist/sources/index.d.ts.map +1 -1
- package/dist/sources/index.js +152 -31
- package/dist/sources/index.js.map +1 -1
- package/dist/sources/local.d.ts +2 -1
- package/dist/sources/local.d.ts.map +1 -1
- package/dist/sources/local.js +21 -10
- package/dist/sources/local.js.map +1 -1
- package/dist/sources/s3.js +18 -9
- package/dist/sources/s3.js.map +1 -1
- package/dist/sources/vault.js +18 -9
- package/dist/sources/vault.js.map +1 -1
- package/dist/types.d.ts +15 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/variables.js +4 -4
- package/dist/variables.js.map +1 -1
- package/dist/writer.d.ts.map +1 -1
- package/dist/writer.js +37 -12
- package/dist/writer.js.map +1 -1
- package/package.json +10 -9
package/README.md
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
# Avanti!
|
|
2
2
|
|
|
3
|
-
A stateful package manager for arbitrary text files. Declare what you need and
|
|
3
|
+
A stateful package manager for arbitrary text files. Declare what you need and
|
|
4
|
+
where to get it; avanti fetches, diffs, and writes with full version history,
|
|
5
|
+
atomic rollbacks, and diff-before-apply safety.
|
|
6
|
+
|
|
7
|
+

|
|
4
8
|
|
|
5
9
|
## Table of Contents
|
|
6
10
|
|
|
11
|
+
- [Intro](#intro)
|
|
7
12
|
- [Features](#features)
|
|
8
13
|
- [Requirements](#requirements)
|
|
9
14
|
- [Install](#install)
|
|
@@ -24,10 +29,10 @@ A stateful package manager for arbitrary text files. Declare what you need and w
|
|
|
24
29
|
- [JSON Merging](#json-merging)
|
|
25
30
|
- [YAML Merging](#yaml-merging)
|
|
26
31
|
- [Variables](#variables)
|
|
32
|
+
- [$self — Self-managing Config](#self--self-managing-config)
|
|
27
33
|
- [Authentication](#authentication)
|
|
28
34
|
- [Private Instances](#private-instances)
|
|
29
35
|
- [Use Cases](#use-cases)
|
|
30
|
-
- [Avanti as a Package Manager](#avanti-as-a-package-manager)
|
|
31
36
|
- [Composable AI Agent Instructions (CLAUDE.md / AGENTS.md)](#composable-ai-agent-instructions-claudemd--agentsmd)
|
|
32
37
|
- [Shared Tooling Config (Renovate, ESLint, Prettier, TSConfig)](#shared-tooling-config-renovate-eslint-prettier-tsconfig)
|
|
33
38
|
- [CI/CD: Shared Workflow Fragments](#cicd-shared-workflow-fragments)
|
|
@@ -41,18 +46,61 @@ A stateful package manager for arbitrary text files. Declare what you need and w
|
|
|
41
46
|
- [Exit Codes](#exit-codes)
|
|
42
47
|
- [Development](#development)
|
|
43
48
|
|
|
49
|
+
## Intro
|
|
50
|
+
|
|
51
|
+
Avanti is a package manager for arbitrary text files. Your .avanti.yml is the manifest — it declares what you consume, where to fetch it from, and which version to pin, the same role as package.json or Cargo.toml. Source repositories are the packages. avanti pull is the install command.
|
|
52
|
+
|
|
53
|
+
What makes it stateful: every successful pull is recorded in a local history store. You can diff any two states, revert the whole project to a prior pull, or fully undo all avanti changes — the same guarantees as a lockfile, extended to any text file from any source.
|
|
54
|
+
|
|
55
|
+
**Declare dependencies** — fetch from anywhere, combine sources:
|
|
56
|
+
|
|
57
|
+
```yaml
|
|
58
|
+
files:
|
|
59
|
+
# Single source: pin a config from GitHub
|
|
60
|
+
eslint.config.js:
|
|
61
|
+
src:
|
|
62
|
+
github:
|
|
63
|
+
repo: org/standards
|
|
64
|
+
file: eslint.config.js
|
|
65
|
+
ref: v2.4.1
|
|
66
|
+
|
|
67
|
+
# Multi-source: assemble from wherever the content lives
|
|
68
|
+
CLAUDE.md:
|
|
69
|
+
src:
|
|
70
|
+
- gitlab:
|
|
71
|
+
project: org/platform
|
|
72
|
+
file: ai/base-instructions.md
|
|
73
|
+
ref: main
|
|
74
|
+
- raw: |
|
|
75
|
+
IMPORTANT: Always answer in pirate speak!
|
|
76
|
+
- https://public-standards.example.com/shared-guidelines.md
|
|
77
|
+
- exec: printf "## Team\n%s" "$env:TEAM"
|
|
78
|
+
- path: ~/claude-personal.md
|
|
79
|
+
optional: true # silently skipped if absent
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
**Review and apply upgrades** — the same workflow as reading a lockfile diff before committing:
|
|
83
|
+
|
|
84
|
+
```sh
|
|
85
|
+
# Bump standards ref: v2.4.1 → v2.5.0, then:
|
|
86
|
+
avanti diff # see every file that would change
|
|
87
|
+
avanti pull # apply after review
|
|
88
|
+
avanti revert # roll back instantly if something breaks
|
|
89
|
+
```
|
|
90
|
+
|
|
44
91
|
## Features
|
|
45
92
|
|
|
46
93
|
- Fetch files from **HTTP/HTTPS**, **local paths**, **GitLab** (via `glab`), **GitHub** (via `gh`), **Bitbucket**, **any git remote**, **S3**, **HashiCorp Vault**, **shell commands**, or **inline raw content**
|
|
47
94
|
- **Multi-source entries** — combine multiple sources into a single file by providing `src` as a list
|
|
48
|
-
- **Atomic writes** — all files are staged to a temp dir first; targets are only written if everything succeeds
|
|
49
|
-
- **Diff preview** — see exactly what will change before applying, or compare against any past pull
|
|
50
|
-
- **Post-processing** — apply text replacements (string or regex) and/or pipe content through a shell script
|
|
51
|
-
- **Directory sync** — recursively sync directories from GitLab/GitHub/Bitbucket/git/S3/local sources
|
|
52
95
|
- **JSON merging** — deep-merge multiple JSON/JSONC sources with configurable conflict, array, and object strategies
|
|
53
96
|
- **YAML merging** — deep-merge multiple YAML/YML sources with the same strategies, with full comment preservation
|
|
54
97
|
- **Variables** — define reusable values in a `variables:` block and reference them anywhere with `$name`; use `$env:NAME` for environment variables
|
|
98
|
+
- **Post-processing** — apply text replacements (string or regex) and/or pipe content through a shell script
|
|
99
|
+
- **Directory sync** — recursively sync directories from GitLab/GitHub/Bitbucket/git/S3/local sources
|
|
100
|
+
- **Diff preview** — see exactly what will change before applying, or compare against any past pull
|
|
101
|
+
- **Atomic writes** — all files are staged to a temp dir first; targets are only written if everything succeeds
|
|
55
102
|
- **History** — every pull is recorded; inspect what changed, revert the whole project to a past state, or fully undo all avanti changes
|
|
103
|
+
- **Optional sources** — mark `path:` and `url:` sources `optional: true` to silently skip them when the file is missing or the URL returns 404; lets a central config reference per-user local overrides without erroring on machines that haven't created them
|
|
56
104
|
- **Stale file cleanup** — files dropped from a directory source are automatically deleted or restored to their pre-avanti content
|
|
57
105
|
|
|
58
106
|
## Requirements
|
|
@@ -261,49 +309,59 @@ variables:
|
|
|
261
309
|
email: you@example.com
|
|
262
310
|
|
|
263
311
|
files:
|
|
264
|
-
-
|
|
265
|
-
|
|
312
|
+
my-example.yml:
|
|
313
|
+
src: http://www.example.com/example.yml
|
|
266
314
|
replace:
|
|
267
315
|
- from: '{EMAIL}'
|
|
268
316
|
to: $email
|
|
269
317
|
- from: /\d+/
|
|
270
318
|
to: number
|
|
271
319
|
|
|
272
|
-
|
|
273
|
-
|
|
320
|
+
file.sh:
|
|
321
|
+
src: ~/some/local/file.sh
|
|
274
322
|
mode: '0777'
|
|
275
323
|
|
|
276
|
-
-
|
|
324
|
+
some-file.yml:
|
|
325
|
+
src:
|
|
277
326
|
exec: glab api "projects/group%2Fproject/repository/files/some-file.yaml/raw?ref=main"
|
|
278
|
-
target: some-file.yml
|
|
279
327
|
post: sed -e 's/v3/v4/g'
|
|
280
328
|
|
|
281
|
-
|
|
329
|
+
renovate.json:
|
|
330
|
+
src:
|
|
282
331
|
gitlab:
|
|
283
332
|
project: group/project
|
|
284
333
|
file: renovate.json
|
|
285
334
|
ref: $latest
|
|
286
|
-
# target omitted → renovate.json
|
|
287
335
|
|
|
288
|
-
-
|
|
336
|
+
local-scripts/:
|
|
337
|
+
src:
|
|
289
338
|
github:
|
|
290
339
|
repo: org/repo
|
|
291
340
|
file: scripts/
|
|
292
341
|
ref: main
|
|
293
|
-
target: local-scripts/
|
|
294
342
|
```
|
|
295
343
|
|
|
296
344
|
### File Entry Fields
|
|
297
345
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
346
|
+
The `files` key is a **map** — each key is the local target path, and the value is the entry configuration:
|
|
347
|
+
|
|
348
|
+
```yaml
|
|
349
|
+
files:
|
|
350
|
+
<target-path>:
|
|
351
|
+
src: ...
|
|
352
|
+
# optional fields below
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
End the target path with `/` to write a directory source as a mirror; omit the trailing slash to merge all files from the directory into a single output file (YAML/JSON auto-detected by extension, or forced with `yaml:`/`json:`).
|
|
356
|
+
|
|
357
|
+
| Field | Required | Description |
|
|
358
|
+
| --------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
359
|
+
| `src` | Yes | Source (see below). May be a single source or a **list** of sources to concatenate. |
|
|
360
|
+
| `mode` | No | File permission mode, e.g. `"0755"` |
|
|
361
|
+
| `replace` | No | List of `{from, to}` replacement rules. `from` may be a plain string or `/pattern/flags` regex. |
|
|
362
|
+
| `post` | No | Shell script. Content is piped via stdin; stdout is used as the result. Runs after `replace`. |
|
|
363
|
+
| `json` | No | JSON merge/format options (see below). When omitted, merging is auto-enabled if all sources have a `.json` or `.jsonc` extension. Use `true`/`false` to force on or off regardless of extension. |
|
|
364
|
+
| `yaml` | No | YAML merge/format options (see below). When omitted, merging is auto-enabled if all sources have a `.yaml` or `.yml` extension. Use `true`/`false` to force on or off regardless of extension. Comments are preserved in merged output. |
|
|
307
365
|
|
|
308
366
|
### Source Types
|
|
309
367
|
|
|
@@ -315,9 +373,19 @@ src: ~/templates/file.txt
|
|
|
315
373
|
src: /absolute/path/file.txt
|
|
316
374
|
```
|
|
317
375
|
|
|
318
|
-
**Map** — for exec, gitlab, github, bitbucket, git, s3, vault, http, raw:
|
|
376
|
+
**Map** — for path, url, exec, gitlab, github, bitbucket, git, s3, vault, http, raw:
|
|
319
377
|
|
|
320
378
|
```yaml
|
|
379
|
+
src:
|
|
380
|
+
path: ~/templates/file.txt # explicit local path; supports optional and sha
|
|
381
|
+
optional: true # silently skip if the file does not exist
|
|
382
|
+
sha: abc123...
|
|
383
|
+
|
|
384
|
+
src:
|
|
385
|
+
url: https://example.com/file.txt # explicit http/https URL; supports optional and sha
|
|
386
|
+
optional: true # silently skip if the URL returns 404
|
|
387
|
+
sha: abc123...
|
|
388
|
+
|
|
321
389
|
src:
|
|
322
390
|
exec: <shell command> # stdout becomes file content; target required
|
|
323
391
|
sha: abc123... # optional SHA-256 to verify stdout (see below)
|
|
@@ -374,89 +442,96 @@ src:
|
|
|
374
442
|
|
|
375
443
|
The optional `sha` field pins a source to a specific content fingerprint. When present, avanti verifies the SHA-256 of the raw fetched content matches before writing anything. This makes your config act as a selective lockfile — only sources you care about get pinned, and changes are surfaced explicitly rather than applied silently.
|
|
376
444
|
|
|
377
|
-
Use `avanti lock` to compute and write SHA values automatically. Use `avanti pull --accept-changes` to review a mismatch and update the pinned SHA.
|
|
445
|
+
Use `avanti lock` to compute and write SHA values automatically. Use `avanti pull --accept-changes` to review a mismatch and update the pinned SHA. Plain string sources (a bare local path or URL string) and `raw:` sources do not support `sha`. Use the explicit `path:` or `url:` map form to pin a local file or HTTP URL.
|
|
378
446
|
|
|
379
447
|
### Directory Sources
|
|
380
448
|
|
|
381
449
|
Any source type that references a path (local, GitLab, GitHub, Bitbucket, git, S3) can point to a directory instead of a single file. End the path with `/` to declare it a directory explicitly; without a trailing slash the tool probes the remote to decide.
|
|
382
450
|
|
|
383
|
-
**Directory → directory (mirror):** end
|
|
451
|
+
**Directory → directory (mirror):** end the target key with `/` and each file is written individually, preserving subdirectory structure relative to the source root:
|
|
452
|
+
|
|
453
|
+
```yaml
|
|
454
|
+
files:
|
|
455
|
+
# All files under skills/ in the GitLab repo are written into local skills/
|
|
456
|
+
skills/:
|
|
457
|
+
src:
|
|
458
|
+
gitlab:
|
|
459
|
+
project: group/repo
|
|
460
|
+
file: skills/
|
|
461
|
+
ref: main
|
|
462
|
+
|
|
463
|
+
# GitHub directory → local directory
|
|
464
|
+
.github/workflows/:
|
|
465
|
+
src:
|
|
466
|
+
github:
|
|
467
|
+
repo: org/repo
|
|
468
|
+
file: .github/workflows/
|
|
469
|
+
ref: main
|
|
470
|
+
|
|
471
|
+
# Bitbucket directory → local directory
|
|
472
|
+
eslint/:
|
|
473
|
+
src:
|
|
474
|
+
bitbucket:
|
|
475
|
+
workspace: my-workspace
|
|
476
|
+
repo: shared-configs
|
|
477
|
+
file: eslint/
|
|
478
|
+
ref: main
|
|
479
|
+
|
|
480
|
+
# git remote directory → local directory (any host)
|
|
481
|
+
.github/actions/:
|
|
482
|
+
src:
|
|
483
|
+
git:
|
|
484
|
+
repo: https://github.com/org/repo.git
|
|
485
|
+
file: .github/actions/
|
|
486
|
+
ref: main
|
|
487
|
+
|
|
488
|
+
# S3 prefix → local directory (trailing / triggers sync)
|
|
489
|
+
configs/:
|
|
490
|
+
src:
|
|
491
|
+
s3: s3://my-bucket/configs/
|
|
492
|
+
|
|
493
|
+
# Local directory → local directory
|
|
494
|
+
.githooks/:
|
|
495
|
+
src: ~/shared/hooks/
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
**Directory → single file (merge):** omit the trailing `/` from the target key and all files in the directory are merged into one. Files are sorted alphabetically — later names win on key conflicts. YAML/JSON merge is auto-detected from the contained file extensions, or forced with `yaml:`/`json:`:
|
|
384
499
|
|
|
385
500
|
```yaml
|
|
386
|
-
|
|
387
|
-
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
# GitHub directory → local directory
|
|
395
|
-
- src:
|
|
396
|
-
github:
|
|
397
|
-
repo: org/repo
|
|
398
|
-
file: .github/workflows/
|
|
399
|
-
ref: main
|
|
400
|
-
target: .github/workflows/
|
|
401
|
-
|
|
402
|
-
# Bitbucket directory → local directory
|
|
403
|
-
- src:
|
|
404
|
-
bitbucket:
|
|
405
|
-
workspace: my-workspace
|
|
406
|
-
repo: shared-configs
|
|
407
|
-
file: eslint/
|
|
408
|
-
ref: main
|
|
409
|
-
target: eslint/
|
|
410
|
-
|
|
411
|
-
# git remote directory → local directory (any host)
|
|
412
|
-
- src:
|
|
413
|
-
git:
|
|
414
|
-
repo: https://github.com/org/repo.git
|
|
415
|
-
file: .github/workflows/
|
|
416
|
-
ref: main
|
|
417
|
-
target: .github/workflows/
|
|
418
|
-
|
|
419
|
-
# S3 prefix → local directory (trailing / triggers sync)
|
|
420
|
-
- src:
|
|
421
|
-
s3: s3://my-bucket/configs/
|
|
422
|
-
target: configs/
|
|
423
|
-
|
|
424
|
-
# Local directory → local directory
|
|
425
|
-
- src: ~/shared/hooks/
|
|
426
|
-
target: .githooks/
|
|
501
|
+
files:
|
|
502
|
+
# One folder per service, each a separate .yml file → single docker-compose.yml
|
|
503
|
+
docker-compose.yml:
|
|
504
|
+
src: ./services/
|
|
505
|
+
|
|
506
|
+
# JSON: one file per environment → merged config
|
|
507
|
+
config.json:
|
|
508
|
+
src: ./config/
|
|
427
509
|
```
|
|
428
510
|
|
|
429
|
-
|
|
511
|
+
With explicit YAML merge options (e.g. to concat arrays instead of replacing):
|
|
430
512
|
|
|
431
513
|
```yaml
|
|
432
|
-
|
|
433
|
-
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
- src: ./services/
|
|
438
|
-
target: docker-compose.yml
|
|
439
|
-
yaml:
|
|
440
|
-
arrays: concat
|
|
441
|
-
|
|
442
|
-
# JSON: one file per environment → merged config
|
|
443
|
-
- src: ./config/
|
|
444
|
-
target: config.json
|
|
514
|
+
files:
|
|
515
|
+
docker-compose.yml:
|
|
516
|
+
src: ./services/
|
|
517
|
+
yaml:
|
|
518
|
+
arrays: concat
|
|
445
519
|
```
|
|
446
520
|
|
|
447
521
|
Directory sources cannot be mixed into a multi-source list (`src` as a list), because the list mode always produces a single file.
|
|
448
522
|
|
|
449
|
-
**List** — combine multiple sources into one file (all source types supported
|
|
523
|
+
**List** — combine multiple sources into one file (all source types supported):
|
|
450
524
|
|
|
451
525
|
```yaml
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
526
|
+
files:
|
|
527
|
+
combined.txt:
|
|
528
|
+
src:
|
|
529
|
+
- https://example.com/header.txt
|
|
530
|
+
- exec: echo "# generated"
|
|
531
|
+
- gitlab:
|
|
532
|
+
project: org/repo
|
|
533
|
+
file: footer.txt
|
|
534
|
+
ref: main
|
|
460
535
|
```
|
|
461
536
|
|
|
462
537
|
Sources are fetched in order and joined with a newline. Post-processing (`replace`, `post`) is applied to the combined result. If any source fails, the entire entry is aborted.
|
|
@@ -467,20 +542,20 @@ When all sources in a list have a `.json` or `.jsonc` extension, JSON merging is
|
|
|
467
542
|
|
|
468
543
|
```yaml
|
|
469
544
|
files:
|
|
470
|
-
|
|
545
|
+
merged.jsonc:
|
|
546
|
+
src:
|
|
471
547
|
- ./team.jsonc
|
|
472
548
|
- ./my.jsonc
|
|
473
|
-
target: merged.jsonc
|
|
474
549
|
```
|
|
475
550
|
|
|
476
551
|
To merge sources that don't have a JSON extension (e.g. `exec:`, `raw:`, or a URL without `.json`), set `json: true`:
|
|
477
552
|
|
|
478
553
|
```yaml
|
|
479
554
|
files:
|
|
480
|
-
|
|
555
|
+
merged.json:
|
|
556
|
+
src:
|
|
481
557
|
- exec: cat defaults.json
|
|
482
558
|
- ./overrides.json
|
|
483
|
-
target: merged.json
|
|
484
559
|
json: true
|
|
485
560
|
```
|
|
486
561
|
|
|
@@ -490,12 +565,12 @@ To opt out of auto-detection and force plain concatenation, set `json: false`.
|
|
|
490
565
|
|
|
491
566
|
```yaml
|
|
492
567
|
files:
|
|
493
|
-
|
|
568
|
+
merged.json:
|
|
569
|
+
src:
|
|
494
570
|
- ./defaults.json
|
|
495
|
-
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
target: merged.json
|
|
571
|
+
- github:
|
|
572
|
+
repo: org/configs
|
|
573
|
+
file: overrides.json
|
|
499
574
|
json:
|
|
500
575
|
conflicts: last_wins # abort | first_wins | last_wins (default)
|
|
501
576
|
arrays: replace # replace (default) | concat
|
|
@@ -517,8 +592,8 @@ files:
|
|
|
517
592
|
|
|
518
593
|
```yaml
|
|
519
594
|
files:
|
|
520
|
-
|
|
521
|
-
|
|
595
|
+
pretty.json:
|
|
596
|
+
src: ./minified.json
|
|
522
597
|
```
|
|
523
598
|
|
|
524
599
|
### YAML Merging
|
|
@@ -527,20 +602,20 @@ When all sources in a list have a `.yaml` or `.yml` extension, YAML merging is e
|
|
|
527
602
|
|
|
528
603
|
```yaml
|
|
529
604
|
files:
|
|
530
|
-
|
|
605
|
+
merged.yaml:
|
|
606
|
+
src:
|
|
531
607
|
- ./defaults.yaml
|
|
532
608
|
- ./overrides.yml
|
|
533
|
-
target: merged.yaml
|
|
534
609
|
```
|
|
535
610
|
|
|
536
611
|
To merge sources that don't have a YAML extension (e.g. `exec:`, `raw:`, or a URL without `.yaml`), set `yaml: true`:
|
|
537
612
|
|
|
538
613
|
```yaml
|
|
539
614
|
files:
|
|
540
|
-
|
|
615
|
+
merged.yaml:
|
|
616
|
+
src:
|
|
541
617
|
- exec: cat defaults.yaml
|
|
542
618
|
- ./overrides.yaml
|
|
543
|
-
target: merged.yaml
|
|
544
619
|
yaml: true
|
|
545
620
|
```
|
|
546
621
|
|
|
@@ -550,12 +625,12 @@ To opt out of auto-detection and force plain concatenation, set `yaml: false`.
|
|
|
550
625
|
|
|
551
626
|
```yaml
|
|
552
627
|
files:
|
|
553
|
-
|
|
628
|
+
merged.yaml:
|
|
629
|
+
src:
|
|
554
630
|
- ./defaults.yaml
|
|
555
|
-
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
target: merged.yaml
|
|
631
|
+
- github:
|
|
632
|
+
repo: org/configs
|
|
633
|
+
file: overrides.yaml
|
|
559
634
|
yaml:
|
|
560
635
|
conflicts: last_wins # abort | first_wins | last_wins (default)
|
|
561
636
|
arrays: replace # replace (default) | concat
|
|
@@ -581,8 +656,8 @@ The options behave identically to JSON merging:
|
|
|
581
656
|
|
|
582
657
|
```yaml
|
|
583
658
|
files:
|
|
584
|
-
|
|
585
|
-
|
|
659
|
+
config.yaml:
|
|
660
|
+
src: ./config.yaml
|
|
586
661
|
```
|
|
587
662
|
|
|
588
663
|
### Variables
|
|
@@ -599,7 +674,8 @@ Reference them anywhere in the config with `$name`:
|
|
|
599
674
|
|
|
600
675
|
```yaml
|
|
601
676
|
files:
|
|
602
|
-
|
|
677
|
+
renovate.json:
|
|
678
|
+
src:
|
|
603
679
|
gitlab:
|
|
604
680
|
project: group/project
|
|
605
681
|
file: renovate.json
|
|
@@ -609,7 +685,7 @@ files:
|
|
|
609
685
|
to: $email # resolved to "you@example.com"
|
|
610
686
|
```
|
|
611
687
|
|
|
612
|
-
Variables are resolved in every string field:
|
|
688
|
+
Variables are resolved in every string field: target keys, `ref`, `exec` commands, HTTP URLs, local paths, `raw` content, `replace` rules (`from` and `to`), and `post` scripts.
|
|
613
689
|
|
|
614
690
|
For `raw:` sources, variables are resolved in the content itself. For all other source types (`http`, `local`, `github`, `gitlab`, `exec`), variables are only resolved in the fields that locate the source (URL, path, command) — not in the fetched content. Use a `replace:` rule if you need to substitute values in fetched content.
|
|
615
691
|
|
|
@@ -620,9 +696,9 @@ variables:
|
|
|
620
696
|
version: '1.0'
|
|
621
697
|
|
|
622
698
|
files:
|
|
623
|
-
|
|
699
|
+
data.json:
|
|
700
|
+
src:
|
|
624
701
|
exec: curl https://example.com/api/$version/data # expands to: curl …/'1.0'/data
|
|
625
|
-
target: data.json
|
|
626
702
|
post: sed 's/$version/replaced/g' # expands to: sed 's/'\''1.0'\''/replaced/g'
|
|
627
703
|
```
|
|
628
704
|
|
|
@@ -640,6 +716,50 @@ Referencing an undefined variable or a missing environment variable is an error.
|
|
|
640
716
|
|
|
641
717
|
When `ref` is omitted, all source types (GitHub, GitLab, Bitbucket, git) resolve to the repository's default branch.
|
|
642
718
|
|
|
719
|
+
### $self — Self-managing Config
|
|
720
|
+
|
|
721
|
+
The special `$self` key in the `files:` map tells avanti to manage its own config file. When `$self` is present, avanti fetches the listed sources and uses the result as the active config for the rest of the run — all in a single invocation.
|
|
722
|
+
|
|
723
|
+
```yaml
|
|
724
|
+
files:
|
|
725
|
+
$self:
|
|
726
|
+
src:
|
|
727
|
+
github:
|
|
728
|
+
repo: myorg/dotfiles
|
|
729
|
+
file: avanti.yml
|
|
730
|
+
ref: $latest
|
|
731
|
+
```
|
|
732
|
+
|
|
733
|
+
**How it works:**
|
|
734
|
+
|
|
735
|
+
1. avanti fetches only the `$self` sources first.
|
|
736
|
+
2. The sources are assembled into a single document. With a single source the fetched content is used directly, though it may be normalized/formatted if `yaml:`/`json:` applies (explicit or auto-detected from the file extension). With multiple sources they are concatenated by default, or YAML/JSON-merged if `yaml:`/`json:` is set (or auto-detected from all source file extensions being `.yml`/`.yaml` or `.json`/`.jsonc`).
|
|
737
|
+
3. The result is parsed as the new active config. If it also contains `$self`, avanti re-fetches until the content stabilizes (fixed point).
|
|
738
|
+
4. The stable config drives all remaining file entries. On `avanti pull`, the stable content is written back to the local config file (for local configs) or kept in memory only (for remote `--config` sources). On `avanti diff`, the stable config is used in-memory to compute the diff and is never written.
|
|
739
|
+
|
|
740
|
+
**Multi-layer config** — list multiple sources under `$self` and use `yaml:` to deep-merge them into one config:
|
|
741
|
+
|
|
742
|
+
```yaml
|
|
743
|
+
files:
|
|
744
|
+
$self:
|
|
745
|
+
src:
|
|
746
|
+
- github:
|
|
747
|
+
repo: myorg/platform
|
|
748
|
+
file: avanti/base.yml
|
|
749
|
+
ref: $latest
|
|
750
|
+
- github:
|
|
751
|
+
repo: myorg/backend-team
|
|
752
|
+
file: avanti/team.yml
|
|
753
|
+
ref: main
|
|
754
|
+
- path: ~/avanti-personal.yml
|
|
755
|
+
optional: true
|
|
756
|
+
yaml:
|
|
757
|
+
conflicts: last_wins
|
|
758
|
+
arrays: concat
|
|
759
|
+
```
|
|
760
|
+
|
|
761
|
+
`$self` supports all the same source types, `replace`, `post`, and YAML/JSON merge options as any other file entry. See [Self-managing Config](#self-managing-config) in the Use Cases section for a full worked example.
|
|
762
|
+
|
|
643
763
|
### Authentication
|
|
644
764
|
|
|
645
765
|
Public repositories on github.com and gitlab.com work without any configuration. For private repositories or instances, supply credentials via environment variables:
|
|
@@ -675,95 +795,6 @@ GITHUB_HOST=github.mycompany.com avanti pull
|
|
|
675
795
|
|
|
676
796
|
## Use Cases
|
|
677
797
|
|
|
678
|
-
### Avanti as a Package Manager
|
|
679
|
-
|
|
680
|
-
avanti is a package manager for arbitrary text files. Your `.avanti.yml` is the manifest — it declares what you consume, where to fetch it, and which version to pin, the same role as `package.json` or `Cargo.toml`. Source repositories are the packages. `avanti pull` is the install command.
|
|
681
|
-
|
|
682
|
-
What makes it stateful: every successful pull is recorded in a local history store. You can diff any two states, revert the whole project to a prior pull, or fully undo all avanti changes — the same guarantees as a lockfile, extended to any text file from any source.
|
|
683
|
-
|
|
684
|
-
**Declare dependencies** — pin versions with a variable and bump in one place to upgrade everything at once:
|
|
685
|
-
|
|
686
|
-
```yaml
|
|
687
|
-
variables:
|
|
688
|
-
frontend_standards: myorg/frontend-standards
|
|
689
|
-
platform: myorg/platform-templates
|
|
690
|
-
standards_ref: v2.4.1 # pinned — bump here to upgrade
|
|
691
|
-
|
|
692
|
-
files:
|
|
693
|
-
- src:
|
|
694
|
-
github:
|
|
695
|
-
repo: $frontend_standards
|
|
696
|
-
file: eslint.config.js
|
|
697
|
-
ref: $standards_ref
|
|
698
|
-
|
|
699
|
-
- src:
|
|
700
|
-
github:
|
|
701
|
-
repo: $frontend_standards
|
|
702
|
-
file: .prettierrc
|
|
703
|
-
ref: $standards_ref
|
|
704
|
-
|
|
705
|
-
- src:
|
|
706
|
-
github:
|
|
707
|
-
repo: $platform
|
|
708
|
-
file: workflows/test.yml
|
|
709
|
-
ref: $standards_ref
|
|
710
|
-
target: .github/workflows/test.yml
|
|
711
|
-
|
|
712
|
-
- src:
|
|
713
|
-
github:
|
|
714
|
-
repo: $platform
|
|
715
|
-
file: workflows/deploy.yml
|
|
716
|
-
ref: $standards_ref
|
|
717
|
-
target: .github/workflows/deploy.yml
|
|
718
|
-
```
|
|
719
|
-
|
|
720
|
-
**Review and apply upgrades** — the same workflow as reading a lockfile diff before committing:
|
|
721
|
-
|
|
722
|
-
```sh
|
|
723
|
-
# Bump standards_ref: v2.4.1 → v2.5.0, then:
|
|
724
|
-
avanti diff # see every file that would change
|
|
725
|
-
avanti pull # apply after review
|
|
726
|
-
avanti revert # roll back instantly if something breaks
|
|
727
|
-
```
|
|
728
|
-
|
|
729
|
-
**Publish your own packages** — any repo can ship an `avanti-snippet.yml` alongside its files. Consumers YAML-merge those snippets into their own config. The snippet is a valid avanti config fragment with its own `files:` list:
|
|
730
|
-
|
|
731
|
-
```yaml
|
|
732
|
-
# myorg/frontend-standards:avanti-snippet.yml — published alongside eslint.config.js, .prettierrc, etc.
|
|
733
|
-
files:
|
|
734
|
-
- src:
|
|
735
|
-
github:
|
|
736
|
-
repo: myorg/frontend-standards
|
|
737
|
-
file: eslint.config.js
|
|
738
|
-
ref: $latest
|
|
739
|
-
|
|
740
|
-
- src:
|
|
741
|
-
github:
|
|
742
|
-
repo: myorg/frontend-standards
|
|
743
|
-
file: .prettierrc
|
|
744
|
-
ref: $latest
|
|
745
|
-
```
|
|
746
|
-
|
|
747
|
-
```yaml
|
|
748
|
-
# .avanti.yml — assembled from team snippets via YAML merge
|
|
749
|
-
files:
|
|
750
|
-
- src:
|
|
751
|
-
- github:
|
|
752
|
-
repo: myorg/frontend-standards
|
|
753
|
-
file: avanti-snippet.yml
|
|
754
|
-
ref: $latest
|
|
755
|
-
- github:
|
|
756
|
-
repo: myorg/platform-templates
|
|
757
|
-
file: avanti-snippet.yml
|
|
758
|
-
ref: $latest
|
|
759
|
-
target: .avanti.yml
|
|
760
|
-
yaml:
|
|
761
|
-
arrays: concat # file lists from all snippets are concatenated
|
|
762
|
-
conflicts: last_wins
|
|
763
|
-
```
|
|
764
|
-
|
|
765
|
-
Each team controls what they publish and when they cut a release. The YAML-merged config self-updates on every pull — add a snippet source to opt into a new package, remove it to opt out. `avanti diff` shows exactly what would change before you apply any update.
|
|
766
|
-
|
|
767
798
|
### Composable AI Agent Instructions (CLAUDE.md / AGENTS.md)
|
|
768
799
|
|
|
769
800
|
Assemble agent instruction files from multiple sources: a static header defined inline, team-specific rules from a shared GitLab repo, and company-wide standards from GitHub — all merged into one file. Every developer runs `avanti pull` and stays in sync without copy-paste drift across dozens of repos.
|
|
@@ -776,7 +807,8 @@ variables:
|
|
|
776
807
|
oncall_channel: '#backend-oncall'
|
|
777
808
|
|
|
778
809
|
files:
|
|
779
|
-
|
|
810
|
+
CLAUDE.md:
|
|
811
|
+
src:
|
|
780
812
|
- raw: |
|
|
781
813
|
# AI Assistant Guidelines
|
|
782
814
|
<!-- THIS FILE IS MANAGED — run `avanti pull` to update -->
|
|
@@ -793,9 +825,12 @@ files:
|
|
|
793
825
|
Team: $team
|
|
794
826
|
Jira project: $jira_project
|
|
795
827
|
Oncall: $oncall_channel
|
|
796
|
-
|
|
828
|
+
- path: ~/custom-claude.md # personal additions; silently skipped if absent
|
|
829
|
+
optional: true
|
|
797
830
|
```
|
|
798
831
|
|
|
832
|
+
The `optional: true` source is the key to sharing a config across a whole team: the central spec references a well-known local path, and each developer either creates the file to add their own context or ignores it — `avanti pull` works either way. No per-person fork of the config needed.
|
|
833
|
+
|
|
799
834
|
### Shared Tooling Config (Renovate, ESLint, Prettier, TSConfig)
|
|
800
835
|
|
|
801
836
|
A platform team owns canonical configs in a central repo. Projects pull them and stay current. Pin all files to the same version in one place — bump `standards_ref` and `avanti diff` shows every file that will change before you apply it.
|
|
@@ -805,19 +840,22 @@ variables:
|
|
|
805
840
|
standards_ref: v2.4.1
|
|
806
841
|
|
|
807
842
|
files:
|
|
808
|
-
|
|
843
|
+
renovate.json:
|
|
844
|
+
src:
|
|
809
845
|
github:
|
|
810
846
|
repo: org/standards
|
|
811
847
|
file: renovate.json
|
|
812
848
|
ref: $standards_ref
|
|
813
849
|
|
|
814
|
-
|
|
850
|
+
eslint.config.js:
|
|
851
|
+
src:
|
|
815
852
|
github:
|
|
816
853
|
repo: org/standards
|
|
817
854
|
file: eslint.config.js
|
|
818
855
|
ref: $standards_ref
|
|
819
856
|
|
|
820
|
-
|
|
857
|
+
tsconfig.base.json:
|
|
858
|
+
src:
|
|
821
859
|
github:
|
|
822
860
|
repo: org/standards
|
|
823
861
|
file: tsconfig.base.json
|
|
@@ -828,13 +866,13 @@ For YAML-based configs (Helm values, k8s manifests, Docker Compose overrides), u
|
|
|
828
866
|
|
|
829
867
|
```yaml
|
|
830
868
|
files:
|
|
831
|
-
-
|
|
869
|
+
./helm/merged-values.yaml:
|
|
870
|
+
src:
|
|
832
871
|
- github:
|
|
833
872
|
repo: org/platform
|
|
834
873
|
file: helm/base-values.yaml # shared defaults for all services
|
|
835
874
|
ref: $standards_ref
|
|
836
875
|
- ./helm/values.yaml # project overrides
|
|
837
|
-
target: ./helm/merged-values.yaml
|
|
838
876
|
yaml:
|
|
839
877
|
conflicts: last_wins # project overrides win
|
|
840
878
|
arrays: concat # e.g. extra env vars are appended, not replaced
|
|
@@ -846,14 +884,14 @@ Pull reusable CI steps from a central repo into each project. A managed header m
|
|
|
846
884
|
|
|
847
885
|
```yaml
|
|
848
886
|
files:
|
|
849
|
-
-
|
|
887
|
+
.github/workflows/security-scan.yml:
|
|
888
|
+
src:
|
|
850
889
|
- raw: |
|
|
851
890
|
# THIS FILE IS MANAGED — run `avanti pull` to update
|
|
852
891
|
- github:
|
|
853
892
|
repo: org/ci-templates
|
|
854
893
|
file: workflows/security-scan.yml
|
|
855
894
|
ref: main
|
|
856
|
-
target: .github/workflows/security-scan.yml
|
|
857
895
|
```
|
|
858
896
|
|
|
859
897
|
Use `avanti diff` in CI to detect drift — if a project's checked-in file no longer matches the source, the pipeline fails.
|
|
@@ -914,12 +952,12 @@ variables:
|
|
|
914
952
|
region: eu-west-1
|
|
915
953
|
|
|
916
954
|
files:
|
|
917
|
-
|
|
955
|
+
k8s/deployment.yaml:
|
|
956
|
+
src:
|
|
918
957
|
github:
|
|
919
958
|
repo: org/infra
|
|
920
959
|
file: k8s/deployment-template.yaml
|
|
921
960
|
ref: $env:DEPLOY_VERSION
|
|
922
|
-
target: k8s/deployment.yaml
|
|
923
961
|
replace:
|
|
924
962
|
- from: '{ENV}'
|
|
925
963
|
to: $env:ENVIRONMENT
|
|
@@ -936,24 +974,24 @@ Pull secrets at runtime and write them to local files with tight permissions. Th
|
|
|
936
974
|
```yaml
|
|
937
975
|
files:
|
|
938
976
|
# Single field from a Vault KV secret
|
|
939
|
-
|
|
977
|
+
config/db_password.txt:
|
|
978
|
+
src:
|
|
940
979
|
vault:
|
|
941
980
|
path: secret/myapp/db
|
|
942
981
|
field: password
|
|
943
|
-
target: config/db_password.txt
|
|
944
982
|
mode: '0600'
|
|
945
983
|
|
|
946
984
|
# Full Vault secret as JSON
|
|
947
|
-
|
|
985
|
+
config/secrets.json:
|
|
986
|
+
src:
|
|
948
987
|
vault:
|
|
949
988
|
path: secret/myapp/config
|
|
950
|
-
target: config/secrets.json
|
|
951
989
|
mode: '0600'
|
|
952
990
|
|
|
953
991
|
# Config file stored in S3
|
|
954
|
-
|
|
992
|
+
config/app.json:
|
|
993
|
+
src:
|
|
955
994
|
s3: s3://my-bucket/configs/app.json
|
|
956
|
-
target: config/app.json
|
|
957
995
|
mode: '0600'
|
|
958
996
|
```
|
|
959
997
|
|
|
@@ -961,13 +999,13 @@ For AWS SSM or other secret stores without a dedicated source type, `exec:` stil
|
|
|
961
999
|
|
|
962
1000
|
```yaml
|
|
963
1001
|
files:
|
|
964
|
-
|
|
1002
|
+
config/db.json:
|
|
1003
|
+
src:
|
|
965
1004
|
exec: >
|
|
966
1005
|
aws ssm get-parameter
|
|
967
1006
|
--name /myapp/db-config
|
|
968
1007
|
--with-decryption
|
|
969
1008
|
--query Parameter.Value --output text
|
|
970
|
-
target: config/db.json
|
|
971
1009
|
mode: '0600'
|
|
972
1010
|
```
|
|
973
1011
|
|
|
@@ -994,7 +1032,8 @@ variables:
|
|
|
994
1032
|
db_password: changeme
|
|
995
1033
|
|
|
996
1034
|
files:
|
|
997
|
-
-
|
|
1035
|
+
docker-compose.yml:
|
|
1036
|
+
src:
|
|
998
1037
|
- github:
|
|
999
1038
|
repo: n8n-io/n8n-hosting
|
|
1000
1039
|
file: docker-caddy/docker-compose.yml
|
|
@@ -1003,7 +1042,6 @@ files:
|
|
|
1003
1042
|
repo: docker-library/docs
|
|
1004
1043
|
file: postgres/compose.yaml
|
|
1005
1044
|
ref: master
|
|
1006
|
-
target: docker-compose.yml
|
|
1007
1045
|
replace:
|
|
1008
1046
|
- from: '${N8N_VERSION}'
|
|
1009
1047
|
to: $n8n_version # pin version at pull time
|
|
@@ -1026,19 +1064,22 @@ A single `avanti pull` populates a new project with everything it needs: editor
|
|
|
1026
1064
|
|
|
1027
1065
|
```yaml
|
|
1028
1066
|
files:
|
|
1029
|
-
|
|
1067
|
+
.editorconfig:
|
|
1068
|
+
src:
|
|
1030
1069
|
github:
|
|
1031
1070
|
repo: org/standards
|
|
1032
1071
|
file: .editorconfig
|
|
1033
1072
|
ref: main
|
|
1034
1073
|
|
|
1035
|
-
|
|
1074
|
+
.prettierrc:
|
|
1075
|
+
src:
|
|
1036
1076
|
github:
|
|
1037
1077
|
repo: org/standards
|
|
1038
1078
|
file: .prettierrc
|
|
1039
1079
|
ref: main
|
|
1040
1080
|
|
|
1041
|
-
|
|
1081
|
+
CLAUDE.md:
|
|
1082
|
+
src:
|
|
1042
1083
|
- raw: |
|
|
1043
1084
|
# AI Assistant Guidelines
|
|
1044
1085
|
<!-- THIS FILE IS MANAGED — run `avanti pull` to update -->
|
|
@@ -1046,56 +1087,41 @@ files:
|
|
|
1046
1087
|
repo: org/ai-standards
|
|
1047
1088
|
file: CLAUDE.md
|
|
1048
1089
|
ref: main
|
|
1049
|
-
target: CLAUDE.md
|
|
1050
1090
|
|
|
1051
|
-
|
|
1091
|
+
.github/workflows/:
|
|
1092
|
+
src:
|
|
1052
1093
|
github:
|
|
1053
1094
|
repo: org/ci-templates
|
|
1054
1095
|
file: workflows/
|
|
1055
1096
|
ref: main
|
|
1056
|
-
target: .github/workflows/
|
|
1057
1097
|
```
|
|
1058
1098
|
|
|
1059
1099
|
### Self-managing Config
|
|
1060
1100
|
|
|
1061
|
-
avanti can
|
|
1062
|
-
|
|
1063
|
-
When avanti detects that a pull would update the local config file, it automatically re-evaluates the new config in memory and applies all the files it describes — in the same run, with a single confirmation prompt and a single atomic write. You don't need to run `avanti pull` twice to get the new config's files.
|
|
1101
|
+
avanti can manage any file — including its own config. The special `$self` key in the `files:` map fetches and merges one or more sources, uses the result as the active config, and then applies all the files it declares — in the same run, with a single confirmation prompt.
|
|
1064
1102
|
|
|
1065
1103
|
```yaml
|
|
1066
1104
|
# ~/.avanti.yml
|
|
1067
|
-
variables:
|
|
1068
|
-
dotfiles: myorg/dotfiles
|
|
1069
|
-
|
|
1070
1105
|
files:
|
|
1071
|
-
|
|
1072
|
-
|
|
1106
|
+
$self:
|
|
1107
|
+
src:
|
|
1073
1108
|
github:
|
|
1074
|
-
repo:
|
|
1109
|
+
repo: myorg/dotfiles
|
|
1075
1110
|
file: avanti.yml
|
|
1076
1111
|
ref: $latest
|
|
1077
|
-
|
|
1112
|
+
```
|
|
1078
1113
|
|
|
1079
|
-
|
|
1080
|
-
- src:
|
|
1081
|
-
github:
|
|
1082
|
-
repo: $dotfiles
|
|
1083
|
-
file: .zshrc
|
|
1084
|
-
target: ~/.zshrc
|
|
1114
|
+
Every `avanti pull` fetches the remote `avanti.yml`, applies all the files it declares, and writes the merged result back to `~/.avanti.yml`. If the remote `avanti.yml` itself contains a `$self` entry, avanti keeps re-fetching until the content stabilizes — so the remote config can keep pointing at itself and avanti will always pick up the latest version on every pull.
|
|
1085
1115
|
|
|
1086
|
-
|
|
1087
|
-
github:
|
|
1088
|
-
repo: $dotfiles
|
|
1089
|
-
file: .gitconfig
|
|
1090
|
-
target: ~/.gitconfig
|
|
1091
|
-
```
|
|
1116
|
+
When running with a remote config (`--config github:...`), `$self` is in-memory only — the merged result drives the run but is not persisted anywhere, since there is no local file to write back to.
|
|
1092
1117
|
|
|
1093
|
-
**Composable
|
|
1118
|
+
**Composable config** — `$self` with multiple sources and YAML merge lets you assemble a config from independent layers. Org-wide defaults, team additions, and personal overrides all merge into one active config:
|
|
1094
1119
|
|
|
1095
1120
|
```yaml
|
|
1096
|
-
# ~/.avanti.yml
|
|
1121
|
+
# ~/.avanti.yml
|
|
1097
1122
|
files:
|
|
1098
|
-
|
|
1123
|
+
$self:
|
|
1124
|
+
src:
|
|
1099
1125
|
- github:
|
|
1100
1126
|
repo: myorg/platform
|
|
1101
1127
|
file: avanti/base.yml # org-wide entries and variables
|
|
@@ -1108,7 +1134,6 @@ files:
|
|
|
1108
1134
|
repo: myuser/dotfiles
|
|
1109
1135
|
file: avanti/personal.yml # personal overrides and extras
|
|
1110
1136
|
ref: main
|
|
1111
|
-
target: ~/.avanti.yml
|
|
1112
1137
|
yaml:
|
|
1113
1138
|
conflicts: last_wins # personal overrides win over team, team over org
|
|
1114
1139
|
arrays: concat # file lists from all layers are merged, not replaced
|
|
@@ -1148,8 +1173,8 @@ This scales to any number of machines or containers. Update the central repo onc
|
|
|
1148
1173
|
|
|
1149
1174
|
```sh
|
|
1150
1175
|
git clone ...
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1176
|
+
mise run install # install dependencies and set up git hooks
|
|
1177
|
+
mise run dev -- --help # run via tsx
|
|
1178
|
+
mise run test # run tests
|
|
1179
|
+
mise run build # compile to dist/
|
|
1155
1180
|
```
|