vis CLI binary - :db Telemere handler, one-shot agent helper,
built-in CLI commands, and the -main dispatcher entry point.
Everything in this file is binary-only. The library surface
(iteration loop, turn engine, environment lifecycle, session
cache) lives in com.blockether.vis.internal.loop; this namespace requires
that one and wires it into the command tree the vis binary
exposes.
Public entry point:
(-main & args) - invoked by the :vis alias / bin/vis.
Configures logging, runs the unified extension
discovery scan, redirects stderr to ~/.vis/vis.log
for any TTY-owning channel, then dispatches to
the resolved command's :cmd/run-fn.
Built-in commands registered here: vis providers - provider inspection, auth, and limits vis sessions - list persisted sessions vis ext list - list registered extensions vis channels <name> - auto-mounted via the channel registry
vis doctor is host-owned. Extensions plug diagnostics into it
with :ext/doctor-fn; extension-owned CLI commands stay under
vis ext.
vis CLI binary - :db Telemere handler, one-shot agent helper,
built-in CLI commands, and the `-main` dispatcher entry point.
Everything in this file is binary-only. The library surface
(iteration loop, turn engine, environment lifecycle, session
cache) lives in `com.blockether.vis.internal.loop`; this namespace requires
that one and wires it into the command tree the `vis` binary
exposes.
Public entry point:
(-main & args) - invoked by the `:vis` alias / `bin/vis`.
Configures logging, runs the unified extension
discovery scan, redirects stderr to ~/.vis/vis.log
for any TTY-owning channel, then dispatches to
the resolved command's `:cmd/run-fn`.
Built-in commands registered here:
vis providers - provider inspection, auth, and limits
vis sessions - list persisted sessions
vis ext list - list registered extensions
vis channels <name> - auto-mounted via the channel registry
`vis doctor` is host-owned. Extensions plug diagnostics into it
with `:ext/doctor-fn`; extension-owned CLI commands stay under
`vis ext`.(-main & raw-args)Discover extensions, walk the command tree, dispatch.
Behavior:
help / --help / -h -> help for the resolved command:cmd/run-fnRoot prompt shortcut lives here, not in commandline/dispatch!, so
the generic dispatcher stays a pure command tree while the binary owns
CLI ergonomics (vis fix this, vis --json summarize).
Discover extensions, walk the command tree, dispatch. Behavior: - No args -> top-level help - `help` / `--help` / `-h` -> help for the resolved command - Recognized command -> invoke its `:cmd/run-fn` - Bare prompt / run flags -> one-shot CLI agent - Unknown command + help -> honest unknown-command error Root prompt shortcut lives here, not in `commandline/dispatch!`, so the generic dispatcher stays a pure command tree while the binary owns CLI ergonomics (`vis fix this`, `vis --json summarize`).
(agent {:keys [name] :as opts})Create an agent definition (data map).
Options:
The iteration loop runs until the model emits :answer or the
user cancels.
Example: (agent {:name "code-reviewer" :description "Reviews Clojure code for quality" :model "gpt-4o"})
Create an agent definition (data map).
Options:
- :name - Agent name (string, default "default")
- :description - What the agent does
- :constants - Map of {symbol value} constants for the Python sandbox
- :model - Override default model selection
The iteration loop runs until the model emits `:answer` or the
user cancels.
Example:
(agent {:name "code-reviewer"
:description "Reviews Clojure code for quality"
:model "gpt-4o"})(all-extension-cmds)Return a flat vec of {:cmd :doc :ext-ns :args} for every registered extension CLI command.
Return a flat vec of {:cmd :doc :ext-ns :args} for every registered extension CLI command.
(discover-all!)Run the unified extension discovery scan. Idempotent through
Clojure's require cache. Returns nil.
Prints a stderr banner enumerating every extension namespace
whose (require) failed during discovery. The same warnings are
also fed into the per-turn (:project ctx) :warnings slice, so
both the user (at the terminal) and the LLM (reading ctx) see the failure
immediately instead of bouncing off Unable to resolve symbol
for an entire session.
Run the unified extension discovery scan. Idempotent through Clojure's `require` cache. Returns nil. Prints a stderr banner enumerating every extension namespace whose `(require)` failed during discovery. The same warnings are also fed into the per-turn `(:project ctx) :warnings` slice, so both the user (at the terminal) and the LLM (reading `ctx`) see the failure immediately instead of bouncing off `Unable to resolve symbol` for an entire session.
(find-extension-cmd cmd-name)Find an extension CLI command by name. Returns {:ext ext :cmd cmd-map} or nil.
Find an extension CLI command by name. Returns {:ext ext :cmd cmd-map} or nil.
(format-cmd-help {:keys [cmd doc args ext-ns]})Build help text for a single extension CLI command.
Build help text for a single extension CLI command.
(handler:db)(handler:db _opts)Telemere handler that persists every signal through the
com.blockether.vis.core/log! facade.
The handler reads :db-info from the signal's telemere context
(*ctx*). When :db-info is absent (no DB connection active in
scope), the signal is silently dropped - the console handler still
prints it.
Usage: (tel/add-handler! :db (handler:db))
(tel/with-ctx+ {:db-info db-info :session-soul-id session-id} (tel/log! :info "something happened"))
Telemere handler that persists every signal through the
`com.blockether.vis.core/log!` facade.
The handler reads `:db-info` from the signal's telemere context
(`*ctx*`). When `:db-info` is absent (no DB connection active in
scope), the signal is silently dropped - the console handler still
prints it.
Usage:
(tel/add-handler! :db (handler:db))
(tel/with-ctx+ {:db-info db-info :session-soul-id session-id}
(tel/log! :info "something happened"))(list-extensions)Return all registered extensions with their metadata (table rows).
:namespace is shortened with the v/ prefix (see
short-ext-ns). :kind carries the categorical bucket
(providers, channels, foundation, ...) used to render the
table in grouped sections. :group is a finer label inside the
kind (provider label / channel cmd / persistance id), blank for
kinds that don't have one. :author, :owner, and :license come
straight from the extension manifest; :owner identifies the
package's distribution ("vis" for everything bundled here), and :license carries the SPDX
identifier (e.g. Apache-2.0).
Return all registered extensions with their metadata (table rows).
`:namespace` is shortened with the `v/` prefix (see
`short-ext-ns`). `:kind` carries the categorical bucket
(`providers`, `channels`, `foundation`, ...) used to render the
table in grouped sections. `:group` is a finer label *inside* the
kind (provider label / channel cmd / persistance id), blank for
kinds that don't have one. `:author`, `:owner`, and `:license` come
straight from the extension manifest; `:owner` identifies the
package's distribution ("vis" for everything bundled here), and `:license` carries the SPDX
identifier (e.g. `Apache-2.0`).(parse-ext-args arg-specs raw-args)Parse CLI args against an arg spec. Returns a map of {arg-name value}.
:kind :positional args are matched in declaration order. :kind :flag args are matched by --name. Boolean flags need no value.
Parse CLI args against an arg spec. Returns a map of {arg-name value}.
:kind :positional args are matched in declaration order.
:kind :flag args are matched by --name. Boolean flags need no value.(root-command)Build the root vis command tree. Subcommands are pulled fresh on
every call so newly registered extensions show up immediately.
Build the root `vis` command tree. Subcommands are pulled fresh on every call so newly registered extensions show up immediately.
(run! agent-def
prompt
&
[{:keys [spec model provider on-chunk debug? config db persist?
no-persist? session-id]
:as _opts}])Execute a one-shot agent turn.
Runs one turn. Default is ephemeral: in-memory SQLite only, no
:cli session written to disk.
Returns map with:
:error or :cancelled).Options:
:memory, path, or db spec):cli
session. Default false.:persist? is true.Ephemeral runs use an in-memory SQLite DB (:db :memory), run the
turn, then dispose the env (which vaporizes the DB). Result has
:session-id nil. Useful for CI, scripting, sensitive prompts.
Persistent calls (:persist? true) create a fresh session in
the :cli channel. Past runs are browsable via
(sessions/by-channel :cli).
Execute a one-shot agent turn.
Runs one turn. Default is ephemeral: in-memory SQLite only, no
`:cli` session written to disk.
Returns map with:
- :session-id - Session ID (UUID string) when persisted;
nil for default ephemeral runs
- :answer - The agent's response
- :iteration-count - Number of iterations executed
- :duration-ms - Total wall-clock time
- :tokens - {:input N :output N :reasoning N :cached N :total N}
- :cost - {:input-cost N :output-cost N :total-cost N :model str}
- :trace - Full iteration trace
- :confidence - :high/:medium/:low (when present)
- :status - Only on failure (`:error` or `:cancelled`).
- :error - Error message (only on failure).
Options:
- :spec - Output spec for structured responses
- :provider - Override provider (keyword or string, e.g. :openai)
- :model - Override model
- :on-chunk - Streaming callback fn
- :debug? - Enable debug logging (default false)
- :config - Provider config override (skips ~/.vis/config.edn)
- :db - DB target for ephemeral runs (`:memory`, path, or db spec)
- :persist? - Write the run to ~/.vis/vis.mdb as a `:cli`
session. Default false.
- :session-id - Continue an existing persisted session (full UUID or
unambiguous prefix). Implies persistent execution.
- :no-persist? - Backward-compatible override; when true, forces
ephemeral execution even if `:persist?` is true.
Ephemeral runs use an in-memory SQLite DB (`:db :memory`), run the
turn, then dispose the env (which vaporizes the DB). Result has
`:session-id nil`. Useful for CI, scripting, sensitive prompts.
Persistent calls (`:persist? true`) create a fresh session in
the `:cli` channel. Past runs are browsable via
`(sessions/by-channel :cli)`.(run-extension-cmd! cmd-name raw-args)Parse args, validate, and run an extension CLI command. Returns {:ok result} or {:error message}.
Parse args, validate, and run an extension CLI command.
Returns {:ok result} or {:error message}.(setup-db-handler!)Install the :db Telemere handler. Idempotent - reusing the same
handler key replaces the previous registration. Call once at
process startup, after the persistence backend is loaded
(otherwise the handler will silently drop signals because no
backend is registered with the facade yet).
The handler is asynchronous (dropping mode, 2048-entry buffer, single drain thread) so a slow DB write never back-pressures the call site that emitted the signal.
Install the `:db` Telemere handler. Idempotent - reusing the same handler key replaces the previous registration. Call once at process startup, after the persistence backend is loaded (otherwise the handler will silently drop signals because no backend is registered with the facade yet). The handler is asynchronous (dropping mode, 2048-entry buffer, single drain thread) so a slow DB write never back-pressures the call site that emitted the signal.
(validate-ext-args arg-specs parsed)Validate parsed args against spec. Returns nil on success, error string on failure.
Validate parsed args against spec. Returns nil on success, error string on failure.
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |