Skip to content

feat(managed): session-start hooks and a timer keep managed skills up to date [skip release] - #419

Merged
aroff merged 4 commits into
mainfrom
feat/managed-hooks
Oct 10, 2026
Merged

aroff merged 4 commits into
mainfrom
feat/managed-hooks

Conversation

@aroff

@aroff aroff commented Oct 10, 2026

Copy link
Copy Markdown
Contributor

Implements ADR-0016 decisions 16 and 17: managed skills stay up to date without anyone running fastskill managed apply.

What changes

  • Session-start hooks (core::managed::hooks)
    • Every apply registers a user-level hook running fastskill managed apply --hook fastskill-managed-<agent> for each covered agent that supports one (Claude Code, Gemini CLI, through aikit-sdk session_hooks).
    • Hooks are removed from agents that are no longer covered.
    • An agent whose administrator-level settings already hold the hook gets no user-level one.
    • When a new hook needs the user's approval, the apply says so.
  • Hook mode (managed apply --hook <id>)
    • Starts an apply detached in the background, then returns at once.
    • Prints nothing unless the user must act (sign in, expired state, nothing applied yet); then it prints one notice in the agent's systemMessage form.
    • Always exits 0.
  • Timer (core::managed::timer)
    • Enrolling, including enrolling by first apply, installs a user timer: a systemd user timer on Linux, a launchd agent on macOS (apply --timer waits up to 10 minutes at random first), or a scheduled task on Windows (UTF-16 XML).
    • It runs shortly after login, then hourly, with up to 10 minutes of random delay.
    • No user timer is installed when a machine-wide one is present.
    • FASTSKILL_MANAGED_TIMER=off installs none.
    • A failure is a warning in the apply's report, not an error.
  • unenroll removes the hooks and the timer.
  • managed hooks [--system] [--json] (read-only)
    • Without --system: this user's hook state per agent, plus the timer.
    • With --system: the administrator-level entries to merge and the machine-wide timer plan.
  • Status and report:
    • status shows the hooked agents.
    • The report's agents[].hook is now filled in.
  • Dependencies:
    • aikit-sdk is bumped to b894e4f (session_hooks).
    • cli-framework is bumped to the release that pins the same aikit rev.
  • Docs: webdocs/cli-reference/managed-command.mdx gains a new "Keeping up to date" section.

Test plan

  • cargo fmt --all
  • cargo clippy --workspace --all-targets --all-features -- -D warnings
  • cargo llvm-cov nextest --all-features -E 'not test(install_e2e_tests)': 2234 passed
  • scripts/check-modified-rust-coverage.py origin/main coverage-summary.json 90: every modified file passes (hooks.rs 100%, timer.rs 97.7%, managed_hooks.rs 100%, managed.rs 94.8%, apply.rs 92.8%, enrollment.rs 99.4%)
  • Unit tests:
    • hook sync, admin replacement, and invalid settings as a warning
    • timer plans for all three OSes, with injected command runners
    • enroll by first apply registering the hooks and timer, and unenroll removing them
    • hook-mode notices
  • Integration tests (with FASTSKILL_MANAGED_TIMER=off):
    • managed apply --hook without settings prints nothing and exits 0
    • managed hooks and managed hooks --system --json

aroff added 4 commits October 10, 2026 12:08
… to date

Every apply registers a session-start hook for each covered agent that supports one and removes
hooks from agents no longer covered. Enrolling, including enrolling by first apply, installs a
user timer (systemd, launchd or a scheduled task); unenroll removes both. managed hooks shows
them, and managed hooks --system prints what an administrator installs for every user.
@aroff
aroff marked this pull request as ready for review October 10, 2026 12:41
@aroff
aroff enabled auto-merge (squash) October 10, 2026 12:41
@aroff
aroff merged commit 70dcaaf into main Oct 10, 2026
15 checks passed
@aroff
aroff deleted the feat/managed-hooks branch October 10, 2026 12:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant