Skip to content

Commit ef50f15

Browse files
jdxclaude
andcommitted
feat(dotfiles): adaptive autosave and doctor health for the watcher
Each tracked file is scheduled on its own: an ordinary edit is saved after the base quiet period, while a file that never settles has its own interval doubled on every churn save, up to `history.watch.max_interval` (24h). A throttled file is still saved periodically, captured promptly once it settles, reset after sustained quiet, and never delays another file. The schedule is persisted so a service restart does not reset it, and captures another path triggers carry a held file's last saved version so whole-set reconciliation cannot defeat the throttling. Nothing is excluded or switched to manual saving automatically. The watcher persists its health; `mise doctor` reports a declared but not running watcher, capture failures, an unusable store, and heavily throttled files without starting anything, and `mise bootstrap dotfiles status` and `paths --noisy` show the detail. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
1 parent ece8e3f commit ef50f15

27 files changed

Lines changed: 1460 additions & 296 deletions

File tree

‎.github/workflows/test-impl.yml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ jobs:
162162
- run: mise run test:e2e e2e/cli/test_dotfiles_rollback_types
163163
- run: mise run test:e2e e2e/cli/test_bootstrap_user_services
164164
- run: mise run test:e2e e2e/cli/test_dotfiles_watch
165+
- run: mise run test:e2e e2e/cli/test_dotfiles_watch_throttle
165166

166167
lint:
167168
runs-on: ${{ !inputs.trusted && 'ubuntu-latest' || 'namespace-profile-endev-linux-amd64-large;overrides.cache-tag=cache' }}

‎docs/.vitepress/cli_commands.ts‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,9 @@ export const commands: { [key: string]: Command } = {
8686
edit: {
8787
hide: false,
8888
},
89+
exclude: {
90+
hide: false,
91+
},
8992
history: {
9093
hide: false,
9194
subcommands: {
@@ -103,6 +106,9 @@ export const commands: { [key: string]: Command } = {
103106
},
104107
},
105108
},
109+
include: {
110+
hide: false,
111+
},
106112
paths: {
107113
hide: false,
108114
},
@@ -127,6 +133,9 @@ export const commands: { [key: string]: Command } = {
127133
untrack: {
128134
hide: false,
129135
},
136+
watch: {
137+
hide: false,
138+
},
130139
},
131140
},
132141
files: {

‎docs/cli/bootstrap/dotfiles.md‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,15 @@ Manage dotfiles from `[dotfiles]`
1616
- [`mise bootstrap dotfiles apply [FLAGS] [TARGET]…`](/cli/bootstrap/dotfiles/apply.md)
1717
- [`mise bootstrap dotfiles diff [TARGET]…`](/cli/bootstrap/dotfiles/diff.md)
1818
- [`mise bootstrap dotfiles edit [FLAGS] <TARGET>`](/cli/bootstrap/dotfiles/edit.md)
19-
- [`mise bootstrap dotfiles history [FLAGS] [SUBCOMMAND]`](/cli/bootstrap/dotfiles/history.md)
20-
- [`mise bootstrap dotfiles paths [-J --json] [--preview <PATH>]`](/cli/bootstrap/dotfiles/paths.md)
19+
- [`mise bootstrap dotfiles exclude <GLOB>`](/cli/bootstrap/dotfiles/exclude.md)
20+
- [`mise bootstrap dotfiles history [FLAGS] <SUBCOMMAND>`](/cli/bootstrap/dotfiles/history.md)
21+
- [`mise bootstrap dotfiles include <GLOB>`](/cli/bootstrap/dotfiles/include.md)
22+
- [`mise bootstrap dotfiles paths [FLAGS]`](/cli/bootstrap/dotfiles/paths.md)
2123
- [`mise bootstrap dotfiles rollback [FLAGS] [PATH]…`](/cli/bootstrap/dotfiles/rollback.md)
2224
- [`mise bootstrap dotfiles save [FLAGS] [PATH]…`](/cli/bootstrap/dotfiles/save.md)
2325
- [`mise bootstrap dotfiles status [-J --json] [--missing] [TARGET]…`](/cli/bootstrap/dotfiles/status.md)
2426
- [`mise bootstrap dotfiles track [FLAGS] <PATH>…`](/cli/bootstrap/dotfiles/track.md)
2527
- [`mise bootstrap dotfiles unapply [FLAGS] [TARGET]…`](/cli/bootstrap/dotfiles/unapply.md)
2628
- [`mise bootstrap dotfiles undo [-n --dry-run] [-y --yes] [REF]`](/cli/bootstrap/dotfiles/undo.md)
2729
- [`mise bootstrap dotfiles untrack <PATH>…`](/cli/bootstrap/dotfiles/untrack.md)
30+
- [`mise bootstrap dotfiles watch [--once] [-J --json]`](/cli/bootstrap/dotfiles/watch.md)
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<!-- @generated by usage-cli from usage spec -->
2+
# `mise bootstrap dotfiles exclude`
3+
4+
- **Usage:** `mise bootstrap dotfiles exclude <GLOB>`
5+
- **Effect:** modifies state
6+
- **Source code:** [`src/cli/bootstrap.rs`](https://github.com/jdx/mise/blob/main/src/cli/bootstrap.rs)
7+
8+
Never capture paths matching a glob
9+
10+
Adds the glob to `[history] exclude` in the global config. Use it for
11+
logs, caches, databases, and constantly rewritten application state; a
12+
file that genuinely holds configuration but changes constantly is
13+
better tracked with `--no-autosave` and saved explicitly.
14+
15+
## Arguments
16+
- **`<GLOB>`** — A glob such as `~/.config/hypr/plugins/**`
17+
18+
## Flags
19+
- **`-h --help`** — Print help
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<!-- @generated by usage-cli from usage spec -->
2+
# `mise bootstrap dotfiles include`
3+
4+
- **Usage:** `mise bootstrap dotfiles include <GLOB>`
5+
- **Effect:** modifies state
6+
- **Source code:** [`src/cli/bootstrap.rs`](https://github.com/jdx/mise/blob/main/src/cli/bootstrap.rs)
7+
8+
Capture paths matching a glob again
9+
10+
Removes the glob from `[history] exclude` in the global config.
11+
12+
## Arguments
13+
- **`<GLOB>`** — The glob as written by `exclude`
14+
15+
## Flags
16+
- **`-h --help`** — Print help

‎docs/cli/bootstrap/dotfiles/paths.md‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<!-- @generated by usage-cli from usage spec -->
22
# `mise bootstrap dotfiles paths`
33

4-
- **Usage:** `mise bootstrap dotfiles paths [-J --json] [--preview <PATH>]`
4+
- **Usage:** `mise bootstrap dotfiles paths [FLAGS]`
55
- **Effect:** read-only
66
- **Source code:** [`src/cli/bootstrap.rs`](https://github.com/jdx/mise/blob/main/src/cli/bootstrap.rs)
77

@@ -15,4 +15,5 @@ enrollment is never mistaken for protection.
1515
## Flags
1616
- **`-J --json`** — Output in JSON format
1717
- **`--preview <PATH>`** — Show what tracking this path would capture
18+
- **`--noisy`** — List the paths the watcher found changing constantly
1819
- **`-h --help`** — Print help
Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
<!-- @generated by usage-cli from usage spec -->
2-
# `mise history watch`
2+
# `mise bootstrap dotfiles watch`
33

4-
- **Usage:** `mise history watch [--once] [-J --json]`
4+
- **Usage:** `mise bootstrap dotfiles watch [--once] [-J --json]`
55
- **Effect:** modifies state
6-
- **Source code:** [`src/cli/history/watch.rs`](https://github.com/jdx/mise/blob/main/src/cli/history/watch.rs)
6+
- **Source code:** [`src/cli/bootstrap.rs`](https://github.com/jdx/mise/blob/main/src/cli/bootstrap.rs)
77

88
Save tracked files as they change
99

@@ -36,7 +36,7 @@ is deferred.
3636
Examples:
3737

3838
```
39-
mise history watch
40-
mise history watch --once # one reconcile, for a timer
41-
mise history watch --json
39+
mise bootstrap dotfiles watch
40+
mise bootstrap dotfiles watch --once # one reconcile, for a timer
41+
mise bootstrap dotfiles watch --json
4242
```

‎docs/cli/history/paths/exclude.md‎

Lines changed: 0 additions & 14 deletions
This file was deleted.

‎docs/cli/history/paths/include.md‎

Lines changed: 0 additions & 14 deletions
This file was deleted.

‎docs/cli/index.md‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,19 +67,22 @@
6767
- [`mise bootstrap dotfiles apply [FLAGS] [TARGET]…`](/cli/bootstrap/dotfiles/apply.md)
6868
- [`mise bootstrap dotfiles diff [TARGET]…`](/cli/bootstrap/dotfiles/diff.md)
6969
- [`mise bootstrap dotfiles edit [FLAGS] <TARGET>`](/cli/bootstrap/dotfiles/edit.md)
70+
- [`mise bootstrap dotfiles exclude <GLOB>`](/cli/bootstrap/dotfiles/exclude.md)
7071
- [`mise bootstrap dotfiles history [FLAGS] [SUBCOMMAND]`](/cli/bootstrap/dotfiles/history.md)
7172
- [`mise bootstrap dotfiles history describe <REF> <TEXT>`](/cli/bootstrap/dotfiles/history/describe.md)
7273
- [`mise bootstrap dotfiles history diff [FLAGS] [A] [B]`](/cli/bootstrap/dotfiles/history/diff.md)
7374
- [`mise bootstrap dotfiles history ls [FLAGS]`](/cli/bootstrap/dotfiles/history/ls.md)
7475
- [`mise bootstrap dotfiles history show [FLAGS] [REF]`](/cli/bootstrap/dotfiles/history/show.md)
75-
- [`mise bootstrap dotfiles paths [-J --json] [--preview <PATH>]`](/cli/bootstrap/dotfiles/paths.md)
76+
- [`mise bootstrap dotfiles include <GLOB>`](/cli/bootstrap/dotfiles/include.md)
77+
- [`mise bootstrap dotfiles paths [FLAGS]`](/cli/bootstrap/dotfiles/paths.md)
7678
- [`mise bootstrap dotfiles rollback [FLAGS] [PATH]…`](/cli/bootstrap/dotfiles/rollback.md)
7779
- [`mise bootstrap dotfiles save [FLAGS] [PATH]…`](/cli/bootstrap/dotfiles/save.md)
7880
- [`mise bootstrap dotfiles status [-J --json] [--missing] [TARGET]…`](/cli/bootstrap/dotfiles/status.md)
7981
- [`mise bootstrap dotfiles track [FLAGS] <PATH>…`](/cli/bootstrap/dotfiles/track.md)
8082
- [`mise bootstrap dotfiles unapply [FLAGS] [TARGET]…`](/cli/bootstrap/dotfiles/unapply.md)
8183
- [`mise bootstrap dotfiles undo [-n --dry-run] [-y --yes] [REF]`](/cli/bootstrap/dotfiles/undo.md)
8284
- [`mise bootstrap dotfiles untrack <PATH>…`](/cli/bootstrap/dotfiles/untrack.md)
85+
- [`mise bootstrap dotfiles watch [--once] [-J --json]`](/cli/bootstrap/dotfiles/watch.md)
8386
- [`mise bootstrap files <SUBCOMMAND>`](/cli/bootstrap/files.md)
8487
- [`mise bootstrap files apply [FLAGS]`](/cli/bootstrap/files/apply.md)
8588
- [`mise bootstrap files status [FLAGS]`](/cli/bootstrap/files/status.md)

0 commit comments

Comments
 (0)