Liking cljdoc? Tell your friends :D

hive-hot.core

Hot-reload registry built on clj-reload.

Extends tonsky/clj-reload with:

  • Named component registry
  • Event-driven listeners (for hive-events integration)
  • Status tracking and introspection
  • Cascade control
  • Watcher integration with coordinated debouncing
  • Scoped reload: load the changes under a set of source roots, drag in their dependents, DECLINE every other change — with a per-file baseline so a declined change stays pending for the reload that owns it (clj-reload keeps one scalar :since for the whole image)

Design: Composition over reimplementation.

Hot-reload registry built on clj-reload.

Extends tonsky/clj-reload with:
- Named component registry
- Event-driven listeners (for hive-events integration)
- Status tracking and introspection
- Cascade control
- Watcher integration with coordinated debouncing
- Scoped reload: load the changes under a set of source roots, drag in
  their dependents, DECLINE every other change — with a per-file baseline
  so a declined change stays pending for the reload that owns it
  (clj-reload keeps one scalar :since for the whole image)

Design: Composition over reimplementation.
raw docstring

add-listener!clj

(add-listener! listener-id listener-fn)

Add a reload event listener.

Events:

  • {:type :reload-start}
  • {:type :reload-success :unloaded [...] :loaded [...] :ms elapsed}
  • {:type :reload-error :failed ns :error ex}
  • {:type :component-callback :component id :callback :on-reload|:on-error}
Add a reload event listener.

Events:
- {:type :reload-start}
- {:type :reload-success :unloaded [...] :loaded [...] :ms elapsed}
- {:type :reload-error :failed ns :error ex}
- {:type :component-callback :component id :callback :on-reload|:on-error}
sourceraw docstring

changed-rootsclj

(changed-roots dirs files)

The watched dirs that contain at least one of the changed files, as sorted canonical paths, each once.

The watcher's debounced reload passes these to reload-scoped!, so a save under one repo reloads that repo (plus the namespaces that depend on it) and leaves a co-tenant's half-saved file under another watched dir pending for the reload that owns it. A file under no watched dir contributes no root.

The watched `dirs` that contain at least one of the changed `files`, as
sorted canonical paths, each once.

The watcher's debounced reload passes these to `reload-scoped!`, so a save
under one repo reloads that repo (plus the namespaces that depend on it)
and leaves a co-tenant's half-saved file under another watched dir pending
for the reload that owns it. A file under no watched dir contributes no
root.
sourceraw docstring

ensure-init!clj

(ensure-init! opts)

init! when not yet initialized, else extend-init! — the idempotent way for a host to declare the dirs it needs without resetting a baseline another caller established. Returns {:initialized? true :fresh? bool :dirs :added}.

`init!` when not yet initialized, else `extend-init!` — the idempotent way
for a host to declare the dirs it needs without resetting a baseline another
caller established. Returns {:initialized? true :fresh? bool :dirs :added}.
sourceraw docstring

extend-init!clj

(extend-init! {:keys [dirs no-reload no-unload owner]})

Extend an initialized registry: union dirs, no-reload and no-unload into clj-reload's config WITHOUT resetting the change baseline, the per-file view, or the work a pass left pending — a change declined before this call is still pending after it, a namespace an earlier pass unloaded but never loaded is still queued, and a keep entry still stands. No-op when nothing is new. Restarts the file watcher, when one is running, over the union. The inverse is remove-dirs!.

:owner (any value, e.g. an addon id) records who claims dirs; a dir stays tracked while an owner other than the one releasing it still claims it. Callers that pass none share one anonymous claim.

Dirs are compared by canonical path: a root already tracked under another spelling is not added twice.

Returns hive-hot.schema/ExtendInitReport {:dirs [...] :added [...]}.

Extend an initialized registry: union `dirs`, `no-reload` and `no-unload`
into clj-reload's config WITHOUT resetting the change baseline, the
per-file view, or the work a pass left pending — a change declined before
this call is still pending after it, a namespace an earlier pass unloaded
but never loaded is still queued, and a keep entry still stands. No-op when
nothing is new. Restarts the file watcher, when one is running, over the
union. The inverse is `remove-dirs!`.

`:owner` (any value, e.g. an addon id) records who claims `dirs`; a dir
stays tracked while an owner other than the one releasing it still claims
it. Callers that pass none share one anonymous claim.

Dirs are compared by canonical path: a root already tracked under another
spelling is not added twice.

Returns hive-hot.schema/ExtendInitReport {:dirs [...] :added [...]}.
sourceraw docstring

find-namespacesclj

(find-namespaces pattern)

Find namespaces matching a pattern. Delegates to clj-reload/find-namespaces.

Find namespaces matching a pattern.
Delegates to clj-reload/find-namespaces.
sourceraw docstring

get-componentclj

(get-component component-id)

Get component registration by ID.

Get component registration by ID.
sourceraw docstring

init!clj

(init!)
(init! opts)

Initialize hive-hot with source directories.

Options (passed to clj-reload/init):

  • :dirs - Source directories (default: ["src"])
  • :no-reload - Namespaces to never reload
  • :no-unload - Namespaces to reload but not unload
  • :since - Epoch ms the change baseline starts from (default: now). A file modified after it counts as changed on the first reload; pass the JVM start time so edits made before this init are not silently taken as the baseline.

Resets the per-file baseline. The dirs this call declares are the CORE dirs: remove-dirs! never releases them. Use ensure-init! to extend an initialized registry without resetting it.

Example:

(init! {:dirs ["src" "dev"]
        :no-reload '#{user}})
Initialize hive-hot with source directories.

Options (passed to clj-reload/init):
- :dirs      - Source directories (default: ["src"])
- :no-reload - Namespaces to never reload
- :no-unload - Namespaces to reload but not unload
- :since     - Epoch ms the change baseline starts from (default: now). A
               file modified after it counts as changed on the first reload;
               pass the JVM start time so edits made before this init are
               not silently taken as the baseline.

Resets the per-file baseline. The dirs this call declares are the CORE dirs:
`remove-dirs!` never releases them. Use `ensure-init!` to extend an
initialized registry without resetting it.

Example:
```clojure
(init! {:dirs ["src" "dev"]
        :no-reload '#{user}})
```
sourceraw docstring

init-with-watcher!clj

(init-with-watcher!)
(init-with-watcher! {:keys [dirs claim-checker debounce-ms no-reload no-unload
                            watch-local-roots?]
                     :or {dirs ["src"]
                          claim-checker (constantly #{})
                          debounce-ms 100
                          watch-local-roots? true}
                     :as opts})

Initialize hive-hot with file watcher and coordinating debouncer.

This wires together:

  • FileWatcher (from hive-hot.watcher)
  • CoordinatingDebouncer (from hive-hot.debounce)
  • reload! for actual reloading

Options:

  • :dirs - Source directories to watch (default: ["src"])
  • :claim-checker - Function returning set of claimed files (default: (constantly #{}))
  • :debounce-ms - Debounce window in ms (default: 100)
  • :no-reload - Namespaces to never reload
  • :no-unload - Namespaces to reload but not unload
  • :watch-local-roots? - Include existing source dirs of tools.deps :local/root libraries (default: true)

clj-reload is initialized through ensure-init!: an already-initialized registry is EXTENDED with the dirs, never reset, so a change made between init and watch is not silently taken as the baseline.

The claim-checker is typically created via:

(events/make-claim-checker logic/get-all-claims)

When a file changes:

  1. FileWatcher detects change
  2. Debouncer checks claim-checker
    • If file is claimed: buffer until released
    • If unclaimed: apply debounce-ms window
  3. After debounce: emit :file/changed, call reload!

Example:

;; Basic usage (no coordination)
(init-with-watcher! {:dirs ["src" "dev"]})

;; With claim-aware coordination
(init-with-watcher!
  {:dirs ["src"]
   :claim-checker (events/make-claim-checker logic/get-all-claims)})

Returns :watching on success.

Initialize hive-hot with file watcher and coordinating debouncer.

This wires together:
- FileWatcher (from hive-hot.watcher)
- CoordinatingDebouncer (from hive-hot.debounce)
- reload! for actual reloading

Options:
- :dirs          - Source directories to watch (default: ["src"])
- :claim-checker - Function returning set of claimed files
                   (default: (constantly #{}))
- :debounce-ms   - Debounce window in ms (default: 100)
- :no-reload     - Namespaces to never reload
- :no-unload     - Namespaces to reload but not unload
- :watch-local-roots? - Include existing source dirs of tools.deps
                       :local/root libraries (default: true)

clj-reload is initialized through `ensure-init!`: an already-initialized
registry is EXTENDED with the dirs, never reset, so a change made between
init and watch is not silently taken as the baseline.

The claim-checker is typically created via:
```clojure
(events/make-claim-checker logic/get-all-claims)
```

When a file changes:
1. FileWatcher detects change
2. Debouncer checks claim-checker
   - If file is claimed: buffer until released
   - If unclaimed: apply debounce-ms window
3. After debounce: emit :file/changed, call reload!

Example:
```clojure
;; Basic usage (no coordination)
(init-with-watcher! {:dirs ["src" "dev"]})

;; With claim-aware coordination
(init-with-watcher!
  {:dirs ["src"]
   :claim-checker (events/make-claim-checker logic/get-all-claims)})
```

Returns :watching on success.
sourceraw docstring

list-componentsclj

(list-components)

List all registered component IDs.

List all registered component IDs.
sourceraw docstring

local-root-source-dirsclj

(local-root-source-dirs basis)

Existing source directories of :local/root libraries in a tools.deps basis. Library :paths are relative to their own root, never to the host cwd. The classpath roots in a basis may also contain jars and unrelated host paths, so only explicit local-root library entries are selected.

Existing source directories of :local/root libraries in a tools.deps basis.
Library :paths are relative to their own root, never to the host cwd.
The classpath roots in a basis may also contain jars and unrelated host
paths, so only explicit local-root library entries are selected.
sourceraw docstring

reg-hotclj

(reg-hot component-id {:keys [ns on-reload on-error] :as opts})

Register a component for hot-reload callbacks.

Options:

  • :ns - Namespace symbol (required)
  • :on-reload - Callback after successful reload (fn [])
  • :on-error - Callback on reload failure (fn [exception])

Note: clj-reload handles dependency tracking automatically. Use this for application-level callbacks (restart server, etc).

Example:

(reg-hot :http-server
  {:ns 'my.server
   :on-reload #(println "Server code reloaded!")})
Register a component for hot-reload callbacks.

Options:
- :ns        - Namespace symbol (required)
- :on-reload - Callback after successful reload (fn [])
- :on-error  - Callback on reload failure (fn [exception])

Note: clj-reload handles dependency tracking automatically.
Use this for application-level callbacks (restart server, etc).

Example:
```clojure
(reg-hot :http-server
  {:ns 'my.server
   :on-reload #(println "Server code reloaded!")})
```
sourceraw docstring

reload!clj

(reload!)
(reload! opts)

Reload changed namespaces and their dependents.

Without :only this is (reload-scoped! nil opts): every change the registry's per-file baseline has not seen, under every tracked dir -- which includes the changes an earlier SCOPED reload declined.

Options:

  • :only - :loaded | :all | #"pattern" -- clj-reload's explicit selection, passed straight through (bypasses the baseline)
  • :throw - Throw on error (default: false, returns result map)

Emits events via hive-events:

  • :hot/reload-start before reload
  • :hot/reload-success or :hot/reload-error after

Returns: {:success bool :unloaded [ns ...] :loaded [ns ...] :failed ns-or-nil :error message-or-nil -- the wrapper message followed by the root cause :root-cause {:message :class :ns :file :line :column} -- the innermost ex-cause of the failure (present only on failure) :exception throwable-or-nil :aliases-repaired [{:holder ns :alias sym :target ns :action :reloaded|:realiased|:unaliased} ...] -- present only when a namespace held an alias to a Namespace object the pass replaced (see clj-reload-pass!) :stale-registrations [{:registry :fx :id k :owner ns/name} ...] -- present only when the pass left a hive-events registry entry holding a function from code it just replaced, which happens when the registration is guarded so it runs once (see stale-registrations) :ms elapsed}

Example:

(reload!)                        ; Reload changed
(reload! {:only :all})           ; Reload everything
(reload! {:only #".*-test"})   ; Reload matching
Reload changed namespaces and their dependents.

Without :only this is `(reload-scoped! nil opts)`: every change the
registry's per-file baseline has not seen, under every tracked dir -- which
includes the changes an earlier SCOPED reload declined.

Options:
- :only  - :loaded | :all | #"pattern" -- clj-reload's explicit selection,
           passed straight through (bypasses the baseline)
- :throw - Throw on error (default: false, returns result map)

Emits events via hive-events:
- :hot/reload-start before reload
- :hot/reload-success or :hot/reload-error after

Returns:
{:success bool
 :unloaded [ns ...]
 :loaded [ns ...]
 :failed ns-or-nil
 :error message-or-nil -- the wrapper message followed by the root cause
 :root-cause {:message :class :ns :file :line :column} -- the innermost
   ex-cause of the failure (present only on failure)
 :exception throwable-or-nil
 :aliases-repaired [{:holder ns :alias sym :target ns
                     :action :reloaded|:realiased|:unaliased} ...] --
   present only when a namespace held an alias to a Namespace object the
   pass replaced (see `clj-reload-pass!`)
 :stale-registrations [{:registry :fx :id k :owner ns/name} ...] -- present
   only when the pass left a hive-events registry entry holding a function
   from code it just replaced, which happens when the registration is
   guarded so it runs once (see `stale-registrations`)
 :ms elapsed}

Example:
```clojure
(reload!)                        ; Reload changed
(reload! {:only :all})           ; Reload everything
(reload! {:only #".*-test"})   ; Reload matching
```
sourceraw docstring

reload-all!clj

(reload-all!)

Force reload of all namespaces.

Use sparingly - prefer reload! for incremental reloads.

Force reload of all namespaces.

Use sparingly - prefer reload! for incremental reloads.
sourceraw docstring

reload-scoped!clj

(reload-scoped! roots)
(reload-scoped! roots opts)

Reload the changes under roots — and only those.

clj-reload holds ONE changed-set across every tracked dir, so a plain reload loads whatever any co-tenant has saved anywhere. This pass admits the changed files under roots, drags in the namespaces that depend on them (the cascade has to recompile those against the new vars, wherever they live), and DECLINES every other change: those files keep their baseline and stay pending for the reload that owns their root. roots nil or empty means every tracked dir.

opts :force? true admits every tracked file under the roots whatever its mtime (see scope-plan): the repair for an image that diverged from disk without any file changing.

A pass also runs when nothing under the roots changed but clj-reload holds work an earlier pass left queued (a namespace unloaded and never loaded, or one a caller queued): that work would otherwise wait for an unrelated edit.

Queued work is attributed by file like a change is. A namespace an earlier pass left queued — typically one that FAILED to compile in an unscoped or another root's reload, which clj-reload replays on every later pass — whose files lie outside the roots and the cascade is WITHHELD: it sits this pass out and goes back in the queue afterwards, so one root's broken work in progress cannot fail every other root's reload, and its own root's reload still finds it.

Protocol interlock (see hive-hot.protocols). Reloading a namespace that defines a protocol or interface orphans every implementation compiled against the old one. So a protocol definer in the cascade is either

  • reloaded, and then EVERY live namespace implementing it (defrecord, deftype, extend, extend-type, extend-protocol - whether or not the require graph or loaded-libs reaches it) and every direct dependent is reloaded after it, in dependency order, by a follow-up pass when clj-reload's own cascade missed one; or
  • PINNED - not reloaded in place - when it lies outside roots or one of its implementors is not tracked (a jar, a REPL namespace) and so could never be reloaded after it.

Returns clj-reload's result plus: :success bool :ms elapsed :scoped? true when roots were given :roots the canonical roots :forced? true when the pass ran with :force? :skipped [ns-string ...] changed outside the roots, NOT loaded :dragged [ns-string ...] changed outside the roots, loaded as dependents :unchanged? true when nothing under the roots had changed :pending? true when the pass ran for queued work alone :withheld [ns-string ...] queued work outside the roots, NOT run and left queued (present only when non-empty) :multi-file {ns [path ...]} loaded namespaces found in more than one file :protocol-cascade [{:definer ns-string :reloaded [ns-string ...]} ...] implementors a follow-up pass reloaded after a protocol definer (present only when one ran) :protocol-stale {ns-string [ns-string ...]} implementors STILL not reloaded after their definer (present only when non-empty) :pinned-protocols [{:ns :reason :implementors} ...] protocol definers in the cascade NOT reloaded in place (present only when non-empty)

Reload the changes under `roots` — and only those.

clj-reload holds ONE changed-set across every tracked dir, so a plain reload
loads whatever any co-tenant has saved anywhere. This pass admits the
changed files under `roots`, drags in the namespaces that depend on them
(the cascade has to recompile those against the new vars, wherever they
live), and DECLINES every other change: those files keep their baseline and
stay pending for the reload that owns their root. `roots` nil or empty means
every tracked dir.

opts :force? true admits every tracked file under the roots whatever its
mtime (see scope-plan): the repair for an image that diverged from disk
without any file changing.

A pass also runs when nothing under the roots changed but clj-reload holds
work an earlier pass left queued (a namespace unloaded and never loaded, or
one a caller queued): that work would otherwise wait for an unrelated edit.

Queued work is attributed by file like a change is. A namespace an earlier
pass left queued — typically one that FAILED to compile in an unscoped or
another root's reload, which clj-reload replays on every later pass — whose
files lie outside the roots and the cascade is WITHHELD: it sits this pass
out and goes back in the queue afterwards, so one root's broken work in
progress cannot fail every other root's reload, and its own root's reload
still finds it.

Protocol interlock (see hive-hot.protocols). Reloading a namespace that
defines a protocol or interface orphans every implementation compiled
against the old one. So a protocol definer in the cascade is either
  - reloaded, and then EVERY live namespace implementing it (defrecord,
    deftype, extend, extend-type, extend-protocol - whether or not the
    require graph or *loaded-libs* reaches it) and every direct dependent
    is reloaded after it, in dependency order, by a follow-up pass when
    clj-reload's own cascade missed one; or
  - PINNED - not reloaded in place - when it lies outside `roots` or one of
    its implementors is not tracked (a jar, a REPL namespace) and so could
    never be reloaded after it.

Returns clj-reload's result plus:
  :success    bool
  :ms         elapsed
  :scoped?    true when roots were given
  :roots      the canonical roots
  :forced?    true when the pass ran with :force?
  :skipped    [ns-string ...]  changed outside the roots, NOT loaded
  :dragged    [ns-string ...]  changed outside the roots, loaded as dependents
  :unchanged? true when nothing under the roots had changed
  :pending?   true when the pass ran for queued work alone
  :withheld   [ns-string ...]  queued work outside the roots, NOT run and
                               left queued (present only when non-empty)
  :multi-file {ns [path ...]}  loaded namespaces found in more than one file
  :protocol-cascade [{:definer ns-string :reloaded [ns-string ...]} ...]
                               implementors a follow-up pass reloaded after
                               a protocol definer (present only when one ran)
  :protocol-stale {ns-string [ns-string ...]}
                               implementors STILL not reloaded after their
                               definer (present only when non-empty)
  :pinned-protocols [{:ns :reason :implementors} ...]
                               protocol definers in the cascade NOT reloaded
                               in place (present only when non-empty)
sourceraw docstring

remove-dirs!clj

(remove-dirs! {:keys [dirs owner]})

Stop tracking and watching dirs — the inverse of extend-init!, for a source root being plugged OUT. Drops them from clj-reload's :dirs WITHOUT resetting the change baseline, the per-file view or pending work, and restarts a running file watcher without them.

A dir the INITIAL init declared (see init!; an uninitialized registry first adopts clj-reload's dirs as that initial set) is never removed: it is the host's own source, and is answered under :kept. A dir another owner still claims (see extend-init! :owner) is released for :owner only, stays tracked, and is answered under :kept and :shared. A dir that is not tracked is answered under :absent. Dirs are compared by canonical path and answered in the caller's spelling. Idempotent: a second call removes nothing.

Returns hive-hot.schema/RemoveDirsReport: {:removed [...] :kept [...] :absent [...] :dirs [...] :shared {dir [owner]}} :dirs are the tracked dirs after the call.

Stop tracking and watching `dirs` — the inverse of `extend-init!`, for a
source root being plugged OUT. Drops them from clj-reload's :dirs WITHOUT
resetting the change baseline, the per-file view or pending work, and
restarts a running file watcher without them.

A dir the INITIAL init declared (see `init!`; an uninitialized registry first
adopts clj-reload's dirs as that initial set) is never removed: it is the
host's own source, and is answered under :kept. A dir another owner still
claims (see `extend-init!` :owner) is released for `:owner` only, stays
tracked, and is answered under :kept and :shared. A dir that is not tracked
is answered under :absent. Dirs are compared by canonical path and answered
in the caller's spelling. Idempotent: a second call removes nothing.

Returns hive-hot.schema/RemoveDirsReport:
  {:removed [...] :kept [...] :absent [...] :dirs [...] :shared {dir [owner]}}
:dirs are the tracked dirs after the call.
sourceraw docstring

remove-listener!clj

(remove-listener! listener-id)

Remove a reload event listener.

Remove a reload event listener.
sourceraw docstring

reset-all!clj

(reset-all!)

Reset all registrations, the per-file baseline and the core dirs. Use in tests.

Reset all registrations, the per-file baseline and the core dirs. Use in tests.
sourceraw docstring

scope-planclj

(scope-plan roots)
(scope-plan roots {:keys [force?]})

What a scoped reload of roots WOULD do — no effects.

Compares every tracked file's mtime against this registry's per-file baseline (falling back to clj-reload's :since), splits the changed files by root, and closes the wanted namespaces forward over the current require graph. roots nil or empty means every tracked dir.

opts: :force? treat EVERY tracked file under the roots as changed, whatever its mtime. The image can diverge from disk without any file moving (a load-file from another checkout, a REPL redefinition), and an mtime scan cannot see that; a forced plan re-reads the roots so the image matches the source they hold again. Dependents still cascade and :no-reload still masks.

Returns {:roots [canonical root ...] nil when unscoped :want [File ...] changed under the roots — loaded :dragged [File ...] changed outside, but a dependent of a wanted namespace — loaded, since the cascade must recompile it anyway :skipped [File ...] changed outside, unrelated — DECLINED; stays pending for its own root :cascade [ns ...] tracked require-graph closure, INCLUDING unchanged dependents; potential namespace reloads, before live/no-reload filtering. Untracked namespaces are not covered. :mask #{ns ...} namespaces pinned :no-reload for the run, including the :pinned protocol definers :withheld #{ns ...} work clj-reload holds QUEUED (from an earlier, failed or unscoped pass) for namespaces outside the roots and the cascade — taken out of the pass and put back after it :queued [ns ...] queued work the pass does run :definers {ns #{ns ...}} protocol/interface definers in the cascade the pass reloads, each with the live namespaces that MUST be reloaded after it (implementors and direct dependents; see hive-hot.protocols) :pinned {ns {:reason kw :implementors [ns ...]}} protocol definers in the cascade NOT reloaded in place: outside the roots, or implemented by a namespace no reload can reach :since long | nil the :since window the run needs, nil when there is nothing to load :old-since long :forced? bool}

What a scoped reload of `roots` WOULD do — no effects.

Compares every tracked file's mtime against this registry's per-file
baseline (falling back to clj-reload's :since), splits the changed files by
root, and closes the wanted namespaces forward over the current require
graph. `roots` nil or empty means every tracked dir.

opts:
  :force?  treat EVERY tracked file under the roots as changed, whatever its
           mtime. The image can diverge from disk without any file moving
           (a load-file from another checkout, a REPL redefinition), and an
           mtime scan cannot see that; a forced plan re-reads the roots so the
           image matches the source they hold again. Dependents still
           cascade and :no-reload still masks.

Returns
  {:roots     [canonical root ...]   nil when unscoped
   :want      [File ...]             changed under the roots — loaded
   :dragged   [File ...]             changed outside, but a dependent of a
                                     wanted namespace — loaded, since the
                                     cascade must recompile it anyway
   :skipped   [File ...]             changed outside, unrelated — DECLINED;
                                     stays pending for its own root
   :cascade   [ns ...]              tracked require-graph closure, INCLUDING
                                     unchanged dependents; potential namespace
                                     reloads, before live/no-reload filtering.
                                     Untracked namespaces are not covered.
   :mask      #{ns ...}              namespaces pinned :no-reload for the run,
                                     including the :pinned protocol definers
   :withheld  #{ns ...}              work clj-reload holds QUEUED (from an
                                     earlier, failed or unscoped pass) for
                                     namespaces outside the roots and the
                                     cascade — taken out of the pass and
                                     put back after it
   :queued    [ns ...]               queued work the pass does run
   :definers  {ns #{ns ...}}         protocol/interface definers in the
                                     cascade the pass reloads, each with the
                                     live namespaces that MUST be reloaded
                                     after it (implementors and direct
                                     dependents; see hive-hot.protocols)
   :pinned    {ns {:reason kw :implementors [ns ...]}}
                                     protocol definers in the cascade NOT
                                     reloaded in place: outside the roots, or
                                     implemented by a namespace no reload can
                                     reach
   :since     long | nil             the :since window the run needs, nil
                                     when there is nothing to load
   :old-since long
   :forced?   bool}
sourceraw docstring

statusclj

(status)

Get current hot-reload status.

Every value here is DATA: the report crosses process and serialization boundaries (an MCP tool surface renders it as JSON), so live objects are projected rather than handed over. Callers that need the actual callbacks read the registry, not the report.

Returns: {:initialized? bool :components {component-id {:ns str :status kw :last-reload ms :on-reload? bool :on-error? bool}} :listener-count n :dirs [str ...] tracked source dirs (when initialized) :since ms clj-reload's change baseline (when initialized) :pending [ns ...] namespaces changed on disk that no reload has loaded yet (when initialized)}

Get current hot-reload status.

Every value here is DATA: the report crosses process and serialization
boundaries (an MCP tool surface renders it as JSON), so live objects are
projected rather than handed over. Callers that need the actual callbacks
read the registry, not the report.

Returns:
{:initialized? bool
 :components {component-id {:ns str :status kw :last-reload ms
                            :on-reload? bool :on-error? bool}}
 :listener-count n
 :dirs [str ...]       tracked source dirs (when initialized)
 :since ms             clj-reload's change baseline (when initialized)
 :pending [ns ...]     namespaces changed on disk that no reload has loaded
                       yet (when initialized)}
sourceraw docstring

stop-watcher!clj

(stop-watcher!)

Stop the file watcher if running.

Stop the file watcher if running.
sourceraw docstring

unreg-hotclj

(unreg-hot component-id)

Unregister a component.

Unregister a component.
sourceraw docstring

watcher-statusclj

(watcher-status)

Get watcher status.

Returns nil if not watching, or map with:

  • :watching? true
  • :dirs watched directories
Get watcher status.

Returns nil if not watching, or map with:
- :watching? true
- :dirs watched directories
sourceraw docstring

watching-pathsclj

(watching-paths)

Get list of directories being watched. Returns empty vector if not watching.

Get list of directories being watched.
Returns empty vector if not watching.
sourceraw docstring

with-reloadcljmacro

(with-reload & body)

Execute body, then reload.

Useful for REPL development:

(with-reload
  (spit "src/my/service.clj" new-code))
Execute body, then reload.

Useful for REPL development:
```clojure
(with-reload
  (spit "src/my/service.clj" new-code))
```
sourceraw docstring

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
←Move to previous article
→Move to next article
Ctrl+/Jump to the search field
× close