Turn the hardcoded straight-line sweep into a strategy system behind three
seams so new patterns are easy to add and, for the first time, testable
without nut.js or a real screen:
- src/device.ts: injectable Device seam over nut.js (autoDelayMs lives
here now); the only module that touches the native lib.
- src/strategies.ts: pure per-pattern path generators + registry + lenient
name resolution. Ships line, diagonal, jitter, walk,
arc, figureEight.
- src/executor.ts: single executePath driver owning bounds policy
(abort/clamp/reflect), pacing, interrupt detection, and
restore-on-clean.
keeper.ts's simulateActivity now selects a strategy and delegates to the
executor; the default `line` pattern is byte-for-byte the previous behavior.
New config surface, layered CLI > file > default with strict validation:
- -p/--pattern <name> movement strategy (names matched case/-/_-insensitive)
- -s/--step-size <px> pixels per step; stepCount is now a step *count*
Robustness for the new edge-seeking patterns: interrupt detection compares
against the last commanded (rounded) point with a 2px tolerance, and
clamp/reflect stay a couple pixels off the screen edge, so sub-pixel cursor
placement on scaled/multi-monitor displays isn't misread as user activity.
jitter's radius scales with sweep length so it moves at the default stepSize.
Tests: new suites for strategies, the executor (all bounds policies,
rounding, interrupt, tolerance, pacing), and the keeper loop; config and
configFile suites extended for pattern/stepSize. editor.test.ts moved to
tests/ for consistency. 64 pass.
5.1 KiB
5.1 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.
1.3.0 - 2026-08-06
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. -s, --step-size <pixels>decouples pixels-per-step fromstepCount(which is now a step count, not a pixel distance). Default1.- 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.jitter's radius now scales with the sweep length (like the other patterns) instead ofstepSizealone, so it produces real cursor motion at the defaultstepSizeof 1 rather than hovering within a 2px radius.- 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.
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.