Introduce a continuous "loop" setting so a triggered sweep keeps the
cursor moving until the user moves the mouse (or Ctrl+C), instead of
firing a single sweep.
- strategies.ts: add optional `loopPath` to MovementStrategy; give `line`
and `diagonal` infinite loop generators that pick a direction once and
ramp forever (4px/step). Their finite `path` and declared `bounds` are
unchanged, so single-sweep behavior is identical.
- executor.ts: add ExecuteOptions { restore?, bounds?, loop? }. Omitting
options reproduces the original single-sweep contract exactly.
- keeper.ts: in loop mode, run an infinite loopPath once (stopped only by
interruption) or chain a finite path cycle after cycle; force `reflect`
bounds for every pattern and suppress the between-cycle restore, so
line/diagonal bounce edge-to-edge instead of stopping at the first edge.
- config plumbing: new boolean `loop` through config.default.json,
config.ts, configFile.ts, cli.ts (-l/--loop), and move.ts, mirroring
the existing `verbose` precedence.
- docs: README loop-mode section + usage/validation updates; CHANGELOG
Unreleased entry.
- tests: loopPath generators, executor options (bounds override, loop
selection, restore suppression), config/configFile loop plumbing, and
keeper-level loop behavior (ramps far vs. bounded single-sweep, chained
cycles). 79 pass.
8.6 KiB
8.6 KiB
Changelog
All notable changes to move are documented here.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[Unreleased]
Added
- Loop mode:
-l/--loop(and theloopconfig key) keep the mouse moving after a sweep is triggered until real user activity is detected, instead of firing a single sweep. In loop mode the cursor is never restored between iterations and every pattern's bounds policy is forced toreflect, solineanddiagonalbounce edge-to-edge across the screen (a roaming-DVD effect) rather than stopping at the first edge. Patterns with a finite path (jitter,walk,arc,figureEight) chain that path cycle after cycle. Interruption remains mouse-movement only.
1.3.3 - 2026-08-17
Changed
install.shnow installs the newest published tag by default instead of tracking themasterbranch, so the plaincurl ... | shone-liner installs a real release and reports its version (e.g.v1.3.2). The tag is resolved from the Gitea tags API; if that lookup fails (offline, API unreachable, or no tags yet) it falls back tomaster, preserving the old behavior. SetMOVE_VERSIONto pin an explicit branch or tag as before.
1.3.2 - 2026-08-17
Added
install.shis now interactive. When it finds an existing install and a controlling terminal is available, it reports what's there and asks before replacing it, instead of leavingMOVE_FORCEas the only control. If a config file already exists it asks separately whether to reseed it from the shipped defaults. Both questions are asked before anything is downloaded or deleted, so declining changes nothing.MOVE_RESEED_CONFIG=1overwrites the user config with the shipped defaults without prompting, for unattended use. The previous file is kept asconfig.json.bak; the same backup is written when reseeding is confirmed at the prompt.
Changed
MOVE_FORCE=1now means "skip every prompt and reinstall unconditionally". It deliberately does not touch the user config, so automation that reinstalls the CLI can't take customizations down with it.- Existing-install detection looks for the install tree and the wrapper, not
just the
.installed-versionmarker, so a half-finished or hand-moved install is caught rather than silently overwritten.
Fixed
- Installing a different version over an existing one used to wipe and replace it with no warning; only an exact version match was ever reported. That case now prompts. With no terminal (CI, cron, container builds) the previous non-interactive behavior is preserved exactly: an identical version is a no-op, a different version is replaced.
1.3.1 - 2026-08-14
Added
docs/execution-happy-path.md: a sequence diagram (plus invariants) tracing a clean idle-triggered sweep end to end, linked from the README.
Fixed
- Stale comments corrected to match the current code: the
install.sh/uninstall.shheader curl URLs pointed at a nonexistent repo-root path (they live underscripts/), so the documented command 404'd;move.ts's module list omittededitor.tsand the--editstep; andconfig.tsstill described a removed pixel unit.
1.3.0 - 2026-08-14
Added
- Pluggable movement strategies. New
-p, --pattern <name>flag andpatternconfig key select how the cursor moves:line(default, unchanged behavior),diagonal,jitter,walk,arc,figureEight. Each pattern owns its own size and step count as constants; there is no user knob for sweep magnitude. - Pattern names are matched leniently: case and separators are ignored, so
figureEight,figure-eight,figure_eight, andFIGUREEIGHTare all accepted (on the CLI and in the config file) and resolve to the canonical name. src/device.ts: injectableDeviceseam over nut.js, enabling unit tests for movement without the native binary or a real screen.src/strategies.ts: pure, per-pattern path generators plus the registry and name validation.src/executor.ts: singleexecutePathdriver owning bounds policy (abort/clamp/reflect), pacing, interrupt detection, and restore.- Test suites for strategies, the executor (all bounds policies, rounding, interrupt), and the keeper loop.
Changed
simulateActivityno longer hardcodes a straight-line sweep; it selects a strategy from the registry and delegates execution toexecutePath. The defaultlinepattern is byte-for-byte the previous behavior.- Interrupt detection now compares against the last commanded (rounded) point rather than an ideal target, so fractional/curved paths don't self-trip.
mouse.config.autoDelayMs = 0moved fromrunKeeperintocreateNutDevice— the single place nut.js is wired up.runKeeper(config, device?)accepts an injected device for testing.- Interrupt detection tolerates a small (2px) gap between the commanded and
read-back cursor position, and the
clamp/reflectpatterns stay a few pixels off the screen edge. Together these avoid false "user activity" aborts from sub-pixel cursor placement on scaled or multi-monitor setups, which the new edge-seeking patterns would otherwise hit.line(policyabort) is unaffected.
Removed
-n, --step-countflag and thestepCount/stepSizeconfig keys. Sweep size and step count are now intrinsic to each movement pattern, not user knobs. Config files that still contain these keys keep working: the loader ignores them with a one-line notice instead of rejecting them, so existing installs (all seeded withstepCount) don't break on upgrade. The removed CLI flag, however, is a hard error like any other unknown option.
1.2.0 - 2026-06-17
Added
-e, --editflag opens the resolved config file in$EDITOR.
Changed
keeper.ts(and@nut-tree-fork/nut-js) is lazy-imported, so--helpand--versionskip the nut.js load and start ~10x faster.
1.1.1 - 2026-06-17
Changed
- Tests moved from
src/to a top-leveltests/directory. tsconfig.jsonsets"types": ["bun"]so VS Code resolvesbun:test.
Fixed
package.jsonversion now matches the published tag.
1.1.0 - 2026-06-17
Added
- JSON config file support at
${XDG_CONFIG_HOME:-~/.config}/move/config.json. Precedence: CLI flags > config file > defaults. Strict validation. -C, --config <path>to override the default config path.- Installer seeds
config.jsonwith project defaults on fresh install only. - Bun test suite for
resolveConfigandloadConfigFile.
Changed
- Installer scripts now live in
scripts/. verboseis now a first-classConfigfield;resolveVerboseremoved.CliErrorextracted intosrc/errors.ts.defaultConfigPath()throws when both$XDG_CONFIG_HOMEand$HOMEare unset.mouse.config.autoDelayMs = 0moved intorunKeeper(no module-load side effect).- Runtime errors go through a
failRuntimehelper that mirrorsfailUser. keeper.tsdeclares a namedLoggerinterface.dev-setup.shis now POSIXsh.tsconfig.json: enablednoUncheckedIndexedAccessandresolveJsonModule.
1.0.1 - 2026-06-17
Added
- End-user
install.shrunnable viacurl ... | sh. XDG-respecting, idempotent. uninstall.shremoves the wrapper and install tree; leaves Bun and user config alone.dev-setup.shfor contributors.
Removed
DISTRIBUTION-PLAN.md(design notes, superseded by the implementation).
1.0.0 - 2026-06-15
Initial release.
Added
moveCLI for keeping presence-tracking apps marked Available by nudging the cursor after a configurable idle period.- Flags:
-h/--help,-v/--version,-m/--move-interval,-c/--check-interval,-d/--step-delay,-n/--step-count,-V/--verbose. - Quiet-by-default logging.
- Source split into
src/{move,cli,config,keeper}.ts. binentry + shebang sobun linkregistersmoveglobally.