A command-line driver for a KB — the shell dual of the in-process API, launched with
lein run -m vaelii.host.cli <cmd> <args…>. It runs the engine in-process (no
daemon); to talk to a running daemon use vaelii.host.client instead.
lein run -m vaelii.host.cli assert '(dog Muffet)' CxNaturalWorld --dir /tmp/kb lein run -m vaelii.host.cli query '(dog ?x)' CxNaturalWorld --dir /tmp/kb lein run -m vaelii.host.cli why 3 --dir /tmp/kb lein run -m vaelii.host.cli export /tmp/dump --dir /tmp/kb lein run -m vaelii.host.cli repl --starter # interactive, starter schema lein cli help # every command and what it takes
help is a word rather than only a flag because Leiningen answers lein cli --help
itself, printing the alias expansion — the flag never reaches this namespace through
the alias, though it does through the full lein run -m vaelii.host.cli --help.
Backend. --dir <path> opens the store there under the backend its files were
written by (v/store-backend), or a new durable :disk-log store when it holds none —
recovered on open, so a fact asserted in one invocation is there in the next. A --dir
whose parent does not exist is refused (open-kb-from) rather than created.
upgrade opens a store, brings its reasoning image and index image up to this build, and
closes it (upgrade!); --verify recovers anyway and compares the two images,
--trust keeps an image written under other engine source, and --sync brings the
shipped contexts to what this engine ships.
With no --dir the KB is
in-memory and lives only for the process — useful for repl or a single compound
session, pointless across one-shot commands. --starter loads the shipped schema
(types, contexts, relation rules) so you can explore the ontology. --strength monotonic marks an assert or assert-rule known-true. export takes --variant records|records+index and --compression gzip|xz|none.
A flag belongs to the commands that read it (command-flags), and one carried by
a command that does not is refused rather than dropped — those three are the driver's
and go anywhere, the rest do not. A value it cannot honour is refused on the same
argument: --format texr and --depth twice name nothing.
stdout is the answer. err! keeps a refusal off it, and on-stderr keeps the
engine's own log lines off it too — Trove's console backend prints to *out*, which
here is what a script redirects. A refusal is one stderr line, error: [<:type>] <message> (refusal-line), so a script branches on the keyword and not on the prose.
One writer. A --dir KB takes the single-writer file lock (docs/storage.md), so
the CLI and a daemon cannot own the same directory at once — by design. diff and
upgrade open no KB of the run's (without-a-kb), so diff answers beside a daemon
that holds --dir.
A command-line driver for a KB — the shell dual of the in-process API, launched with `lein run -m vaelii.host.cli <cmd> <args…>`. It runs the engine in-process (no daemon); to talk to a running daemon use `vaelii.host.client` instead. lein run -m vaelii.host.cli assert '(dog Muffet)' CxNaturalWorld --dir /tmp/kb lein run -m vaelii.host.cli query '(dog ?x)' CxNaturalWorld --dir /tmp/kb lein run -m vaelii.host.cli why 3 --dir /tmp/kb lein run -m vaelii.host.cli export /tmp/dump --dir /tmp/kb lein run -m vaelii.host.cli repl --starter # interactive, starter schema lein cli help # every command and what it takes `help` is a word rather than only a flag because Leiningen answers `lein cli --help` itself, printing the alias expansion — the flag never reaches this namespace through the alias, though it does through the full `lein run -m vaelii.host.cli --help`. **Backend.** `--dir <path>` opens the store there under the backend its files were written by (`v/store-backend`), or a new durable `:disk-log` store when it holds none — recovered on open, so a fact asserted in one invocation is there in the next. A `--dir` whose parent does not exist is refused (`open-kb-from`) rather than created. `upgrade` opens a store, brings its reasoning image and index image up to this build, and closes it (`upgrade!`); `--verify` recovers anyway and compares the two images, `--trust` keeps an image written under other engine source, and `--sync` brings the shipped contexts to what this engine ships. With no `--dir` the KB is in-memory and lives only for the process — useful for `repl` or a single compound session, pointless across one-shot commands. `--starter` loads the shipped schema (types, contexts, relation rules) so you can explore the ontology. `--strength monotonic` marks an `assert` or `assert-rule` known-true. `export` takes `--variant records|records+index` and `--compression gzip|xz|none`. **A flag belongs to the commands that read it** (`command-flags`), and one carried by a command that does not is refused rather than dropped — those three are the driver's and go anywhere, the rest do not. A *value* it cannot honour is refused on the same argument: `--format texr` and `--depth twice` name nothing. **stdout is the answer.** `err!` keeps a refusal off it, and `on-stderr` keeps the engine's own log lines off it too — Trove's console backend prints to `*out*`, which here is what a script redirects. A refusal is one stderr line, `error: [<:type>] <message>` (`refusal-line`), so a script branches on the keyword and not on the prose. **One writer.** A `--dir` KB takes the single-writer file lock (docs/storage.md), so the CLI and a daemon cannot own the same directory at once — by design. `diff` and `upgrade` open no KB of the run's (`without-a-kb`), so `diff` answers beside a daemon that holds `--dir`.
(-main & argv)Run one command (run) and leave with its exit status.
Run one command (`run`) and leave with its exit status.
(check-args! cmd args opts)Refuse what dispatch refuses of a command line without reading a KB: the operand count
(check-arity!), a whole-number flag's value (count-option), --nearest beside a
handle, and an export --format that names nothing or comes with a dump's flags. -main
asks this before it opens the KB, so a refused line leaves no --dir store behind and
--starter loads nothing; dispatch asks it again for the lines a REPL session runs.
args are data, as dispatch takes them.
Refuse what `dispatch` refuses of a command line without reading a KB: the operand count (`check-arity!`), a whole-number flag's value (`count-option`), `--nearest` beside a handle, and an `export --format` that names nothing or comes with a dump's flags. `-main` asks this before it opens the KB, so a refused line leaves no `--dir` store behind and `--starter` loads nothing; `dispatch` asks it again for the lines a REPL session runs. `args` are data, as `dispatch` takes them.
(check-arity! cmd args)Refuse a command line with the wrong number of operands, naming what the command takes
and what it got. A short line would reach dispatch's nth as
IndexOutOfBoundsException, and a long line would drop the extra operand in silence,
storing a fact somewhere other than where it was meant to go.
Refuse a command line with the wrong number of operands, naming what the command takes and what it got. A short line would reach `dispatch`'s `nth` as `IndexOutOfBoundsException`, and a *long* line would drop the extra operand in silence, storing a fact somewhere other than where it was meant to go.
(check-flags! cmd opts)Refuse a flag cmd does not read, naming what it does read. -main calls this rather
than dispatch, since the REPL reuses one option map for every line, so a session opened
--strength monotonic must not have a later match line refused for the session's flag.
The line naming repl is checked against the union, and the lines inside it against
nothing. An unknown command word is left alone: -main reports :unknown-command.
Refuse a flag `cmd` does not read, naming what it does read. `-main` calls this rather than `dispatch`, since the REPL reuses one option map for every line, so a session opened `--strength monotonic` must not have a later `match` line refused for the session's flag. The line naming `repl` is checked against the union, and the lines inside it against nothing. An unknown command word is left alone: `-main` reports `:unknown-command`.
Every command word, in the order --help prints it: [word min max operands gloss run],
where run is (fn [kb args o]) and o is {:strength :depth :ctx :nearest :opts}.
max is nil for a command whose last operand is optional. One table rather than
two, because the arity a command takes and the arity --help advertises going
out of step is how a usage message starts lying — and dispatch reaches into args
with nth, so an unchecked short line raises IndexOutOfBoundsException, whose
message is the class name and names neither the command nor the argument.
Every command word, in the order `--help` prints it: `[word min max operands gloss run]`,
where `run` is `(fn [kb args o])` and `o` is `{:strength :depth :ctx :nearest :opts}`.
`max` is nil for a command whose last operand is optional. One table rather than
two, because the arity a command *takes* and the arity `--help` *advertises* going
out of step is how a usage message starts lying — and `dispatch` reaches into `args`
with `nth`, so an unchecked short line raises `IndexOutOfBoundsException`, whose
message is the class name and names neither the command nor the argument.The command words dispatch knows, for the usage message and unknown command.
The command words `dispatch` knows, for the usage message and `unknown command`.
(count-option flag s)The whole number flag carries, refused by name when its value is not one.
Long/parseLong on the raw string reports For input string: "twice" — one line and
exit 1, so no stack trace, but the line names neither the flag nor the command and is
java.lang's rather than the engine's. That is the sentence check-arity! exists to
stop being printed for an operand count, reached one argument in.
The whole number `flag` carries, refused **by name** when its value is not one. `Long/parseLong` on the raw string reports `For input string: "twice"` — one line and exit 1, so no stack trace, but the line names neither the flag nor the command and is java.lang's rather than the engine's. That is the sentence `check-arity!` exists to stop being printed for an operand count, reached one argument in.
(dispatch kb cmd args opts)Run one command against kb and return its result (a handle, a seq of sentences /
solutions, a proof tree, …). args are data; opts is the parsed option map.
A command that answers a set answers it sorted (in-content-order): match,
query and ask alongside types and contexts, so one KB prints the same output
however its knowledge arrived. prove keeps the DFS's order, which is a reading rather
than an artifact.
Run one command against `kb` and return its result (a handle, a seq of sentences / solutions, a proof tree, …). `args` are data; `opts` is the parsed option map. **A command that answers a set answers it sorted** (`in-content-order`): `match`, `query` and `ask` alongside `types` and `contexts`, so one KB prints the same output however its knowledge arrived. `prove` keeps the DFS's order, which is a reading rather than an artifact.
(on-stderr f)A log fn that writes where f does, with *out* bound to *err*. The engine's log!
calls go through Trove's console backend, which prints to *out* (docs/operations.md,
"Logging"), and *out* here is a script's lein cli match … > answers.edn: at :info
an ordinary export or a starter load lands lines inside the answer. A wrapper, not a
level, since the daemon and the browser want the lines where they are.
A log fn that writes where `f` does, with `*out*` bound to `*err*`. The engine's `log!` calls go through Trove's console backend, which prints to `*out*` (docs/operations.md, "Logging"), and `*out*` here is a script's `lein cli match … > answers.edn`: at `:info` an ordinary `export` or a starter load lands lines inside the answer. A wrapper, not a level, since the daemon and the browser want the lines where they are.
(open-kb-from {:keys [dir starter memory] :as _opts})Build the KB a run operates on from the parsed opts: :dir -> durable disk (recovered,
with the reasoners the store records registered), else in-memory, which :memory also
names explicitly, so --memory --dir <path> is refused. :starter loads the shipped
schema. A --dir whose parent does not exist is refused (:unknown-source) and
nothing is created, since the store creates every missing path component and a mistyped
path would answer a read with [] at exit 0. The CLI creates the KB's own directory and
nothing above it, which is how a new KB is made from the shell. A throw from the
:starter load closes the KB before it propagates.
Build the KB a run operates on from the parsed `opts`: `:dir` -> durable disk (recovered, with the reasoners the store records registered), else in-memory, which `:memory` also names explicitly, so `--memory --dir <path>` is refused. `:starter` loads the shipped schema. **A `--dir` whose parent does not exist is refused** (`:unknown-source`) and nothing is created, since the store creates every missing path component and a mistyped path would answer a read with `[]` at exit 0. The CLI creates the KB's own directory and nothing above it, which is how a new KB is made from the shell. A throw from the `:starter` load closes the KB before it propagates.
(parse-opts args)Split raw args into [positionals opts]. --k v becomes {:k v}, a bare flag
(bare-flags) becomes {:flag true}; everything else is a positional, in order.
A value-taking flag with no value is refused (:unknown-option) rather than bound
nil: assert … --strength with nothing after it would otherwise store at :default
— the exact class the flag was written to escape — and --dir at the end of a line
would open the in-memory KB, gone at process exit. A flag the accepted-flag list does
not name is refused the same way.
Split raw args into `[positionals opts]`. `--k v` becomes `{:k v}`, a bare flag
(`bare-flags`) becomes `{:flag true}`; everything else is a positional, in order.
A value-taking flag with no value is refused (`:unknown-option`) rather than bound
nil: `assert … --strength` with nothing after it would otherwise store at `:default`
— the exact class the flag was written to escape — and `--dir` at the end of a line
would open the in-memory KB, gone at process exit. A flag the accepted-flag list does
not name is refused the same way.(read-arg cmd s)One argv string as data: the EDN it reads as (a sentence, a context symbol, a handle) and
the raw string when it reads as none, which is what a filesystem path is
(/var/lib/vaelii is not a symbol). One argument is one form: edn/read-string
drops a second form, so assert '(dog Muffet) (cat Felix)' CxWell would store the dog
and exit 0; a second form is refused (:bad-args, as a wrong operand count is). A
string that reads as no form, or as none because it is empty, stays the string. cmd
names the command in the refusal and is the :op every :bad-args throw carries.
One argv string as data: the EDN it reads as (a sentence, a context symbol, a handle) and the **raw string** when it reads as none, which is what a filesystem path is (`/var/lib/vaelii` is not a symbol). **One argument is one form**: `edn/read-string` drops a second form, so `assert '(dog Muffet) (cat Felix)' CxWell` would store the dog and exit 0; a second form is refused (`:bad-args`, as a wrong operand count is). A string that reads as no form, or as none because it is empty, stays the string. `cmd` names the command in the refusal and is the `:op` every `:bad-args` throw carries.
(read-forms s)Every EDN form in s, in order — how a REPL line's args ((dog ?x) CxMy) are
parsed into data.
Every EDN form in `s`, in order — how a REPL line's args (`(dog ?x) CxMy`) are parsed into data.
(refusal-line e)The line a refusal prints: error: [<:type>] <message>.
The :type is what a caller branches on (docs/troubleshooting.md), and every other
surface carries it — the daemon on the wire, the browser as a chip. A shell reads
only the line, so the keyword goes on it, in brackets straight after error:, and
the message after it is the engine's own words, unchanged. A throwable carrying no :type — a
FileNotFoundException, a StackOverflowError — is :internal-error, the class the
daemon answers one with, so the bracket is on every refusal line and never empty.
The line a refusal prints: `error: [<:type>] <message>`. The `:type` is what a caller branches on (docs/troubleshooting.md), and every other surface carries it — the daemon on the wire, the browser as a chip. A shell reads only the line, so the keyword goes on it, in brackets straight after `error: `, and the message after it is the engine's own words, unchanged. A throwable carrying no `:type` — a `FileNotFoundException`, a `StackOverflowError` — is `:internal-error`, the class the daemon answers one with, so the bracket is on every refusal line and never empty.
(run argv)Parse argv, open the KB, run the command and print its result; return the exit status.
With repl (or no command) it drops into the interactive loop. Every refusal is one
line on stderr and exit 1 (refusal-line), naming its :type. An unknown command word
is exit 2, with the command list and the help pointer after the line. Everything that
needs no KB is answered before one is opened (it would take the single-writer lock and
may create a store): help, the flag and operand checks, and the commands in
without-a-kb. It catches Throwable, since a missing load file raises
FileNotFoundException and a deeply nested EDN argument raises StackOverflowError.
Parse `argv`, open the KB, run the command and print its result; return the exit status. With `repl` (or no command) it drops into the interactive loop. **Every refusal is one line on stderr and exit 1** (`refusal-line`), naming its `:type`. An unknown command word is exit 2, with the command list and the `help` pointer after the line. **Everything that needs no KB is answered before one is opened** (it would take the single-writer lock and may create a store): `help`, the flag and operand checks, and the commands in `without-a-kb`. It catches `Throwable`, since a missing `load` file raises `FileNotFoundException` and a deeply nested EDN argument raises `StackOverflowError`.
(upgrade! dir)(upgrade! dir {:keys [verify trust] sync? :sync})Bring the store in dir up to this build, and report what that took. Opens the store
under the backend its files were written by, with :recover? :auto: a reasoning image this
build can install is installed, and one written under another layout, engine source or
policies is declined, belief is recovered from the records, and the recover writes a new
image. Closing the store writes the index image a rebuilt index leaves due. Returns
{:dir :backend :reasoning :current | :rebuilt | :written | :no-image :image {:format :network :written-at :source} ; the manifest now on disk, :source cut to 12 :index :current | :rewritten | :no-image :verify … ; with :verify only :sync {:added :removed :forwarded :refused} :renames {:rewritten …}} ; with :sync only
:reasoning: :current is an image it installed; :rebuilt one it declined and replaced;
:written the first image of a store that held none; :no-image a backend that keeps none.
Without :sync the records are never rewritten. Options:
:verify moves the image to reasoning.prev/ before the open, so the open recovers from
the records, then compares the two (reasoning-image/compare-images) and deletes the old
one. :verify in the result is {:against source :labels :network :state}, or one
keyword: :no-previous-image, :no-image, :layout-changed or :records-moved.:trust opens with :recover? :trust: belief is recovered only when the records
moved. It refuses :verify (:unknown-option).:sync rewrites what a release renamed (sync/rename!) and syncs the shipped contexts
(sync/sync-each!, a progress line per change on stderr) after the open and :verify.
A KB whose v/write-hazards is not empty is not synced: :sync is {:skipped [hazard …]}.A directory holding no store is refused (:unknown-source). ! because the image it
replaces cannot be read back.
Bring the store in `dir` up to this build, and report what that took. Opens the store
under the backend its files were written by, with `:recover? :auto`: a reasoning image this
build can install is installed, and one written under another layout, engine source or
policies is declined, belief is recovered from the records, and the recover writes a new
image. Closing the store writes the index image a rebuilt index leaves due. Returns
{:dir :backend
:reasoning :current | :rebuilt | :written | :no-image
:image {:format :network :written-at :source} ; the manifest now on disk, :source cut to 12
:index :current | :rewritten | :no-image
:verify … ; with :verify only
:sync {:added :removed :forwarded :refused} :renames {:rewritten …}} ; with :sync only
`:reasoning`: `:current` is an image it installed; `:rebuilt` one it declined and replaced;
`:written` the first image of a store that held none; `:no-image` a backend that keeps none.
Without `:sync` the records are never rewritten. Options:
- `:verify` moves the image to `reasoning.prev/` before the open, so the open recovers from
the records, then compares the two (`reasoning-image/compare-images`) and deletes the old
one. `:verify` in the result is `{:against source :labels :network :state}`, or one
keyword: `:no-previous-image`, `:no-image`, `:layout-changed` or `:records-moved`.
- `:trust` opens with `:recover? :trust`: belief is recovered only when the records
moved. It refuses `:verify` (`:unknown-option`).
- `:sync` rewrites what a release renamed (`sync/rename!`) and syncs the shipped contexts
(`sync/sync-each!`, a progress line per change on stderr) after the open and `:verify`.
A KB whose `v/write-hazards` is not empty is not synced: `:sync` is `{:skipped [hazard …]}`.
A directory holding no store is refused (`:unknown-source`). `!` because the image it
replaces cannot be read back.(usage)The --help text: every command, its operands and a one-line gloss.
The `--help` text: every command, its operands and a one-line gloss.
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 |