All notable changes to this project will be documented in this file.
The format follows Keep a Changelog, and this project adheres to Semantic Versioning.
(no changes yet)
Documentation release. Library code is unchanged from 0.6.0; this release ships a Diátaxis-shaped doc set and hosted API references.
doc/cljdoc.edn tree shape: children are inline siblings, not
wrapped in an extra vector. v0.6.2 published cleanly to Clojars
but cljdoc rejected the malformed tree.build.clj writes <licenses> (MIT) into the pom; required by
Clojars as of late 2025.:build deps alias includes slipset/deps-deploy, which the
deploy task in build.clj requires.v0.6.1 was tagged in git but never fully reached Clojars: the pom and jar uploaded but the metadata.xml step failed because the pom was missing the licenses block. Clojars locks coordinates on first attempted upload, so the version became unusable.
v0.6.2 published to Clojars cleanly, but the doc/cljdoc.edn tree
was malformed (children wrapped in an extra vector), causing
cljdoc's analysis step to throw "Don't know how to create ISeq from:
clojure.lang.Keyword". The Clojars artifact at 0.6.2 is installable
and equivalent to 0.6.3 — only the hosted API ref is broken.
0.6.3 is the first version that's both installable and renders on
cljdoc. The v0.6.1 and v0.6.2 git tags are retained for
traceability.
doc/TUTORIAL.md (45-minute walkthrough), doc/DESIGN.md (rationale
consolidating ADRs), doc/WEB_UI.md (page-by-page tour), doc/MCP.md
(16-tool reference), doc/FAQ.md and doc/TROUBLESHOOTING.md, plus
six P0 how-to guides under doc/howto/ (SQLite→Postgres migration,
Docker team deployment, MCP+Claude Code, Slack alerts, sklearn
tracking, HTTP write API).doc/cljdoc.edn bundle config)
and codox (:codox deps alias + bb docs task)..github/workflows/docs.yml.Full backlog complete: S3 artifacts, Slack webhooks, run cleanup, Docker, HTTP write API.
chachaml.store.s3): ArtifactStore
against S3/MinIO via Cognitect aws-api. Metadata in Postgres/SQLite,
bytes in S3. :s3 deps alias.docker compose up for team deployment.
UI server accepts env vars DB_TYPE, JDBC_URL, DB_USER, etc./api/w/runs, /params,
/metrics, /end, /artifacts, /models. Full lifecycle test.
Enables Python/Go/curl clients.webhook_url on alerts. When
check-alerts! triggers, POSTs Slack-formatted JSON to the URL.archive-runs! marks old runs as :archived
by age + experiment. delete-archived! permanently removes data.
2 tests.start! now delegates to chachaml.store/open —
accepts :type :postgres and all store options directly.Team readiness: Postgres backend, user attribution, pipelines, alerts, chat-with-data.
chachaml.pipeline): run-pipeline! executes
named step sequences, each step tracked as a with-run. Results
chain via :prev-result. defpipeline macro. pipelines +
pipeline_steps tables.chachaml.alerts): set-alert! defines metric
threshold rules, check-alerts! evaluates against latest runs,
records triggered events. alert-history, deactivate-alert!.chachaml.chat): ask sends questions to
Anthropic/OpenAI API with chachaml tools injected. Tool-use loop.
/chat UI page with provider selector and localStorage API key.chachaml.store.postgres): full protocol
implementation with HikariCP pool. Same API as SQLite, team-shared
database. chachaml.store/open dispatcher: :type :sqlite or
:type :postgres. :postgres deps alias.created_by column on runs, auto-captured
from system user, filterable in queries and visible in UI.set-note! stores markdown;
the UI renders it with LaTeX math support. set-model-note! added
to the registry for model descriptions.search_runs, best_run, add_tag,
set_note, get_tags, get_datasets, list_experiments,
create_experiment, export_runs, diff_model_versions.log-table + log-dataset!,
UC08 uses with-batched-metrics, UC17 uses create-experiment!,
UC19 uses add-tag!, UC25 uses set-note! with markdown+math,
-main uses best-run + export-runs.chachaml.format namespace with shared
short-id, size-str, fmt-instant, fmt-duration, pad,
metric-summary. Eliminated 4 duplicated helper fns from
chachaml.repl and chachaml.ui.views. Extracted
->experiment-map in sqlite.clj (was copy-pasted 3 times).
Consolidated sklearn interop require/resolve pattern into
core-fn helper.add-tag!, set-note!, get-tags —
annotate runs after they complete. Tags stored in a dedicated table
with upsert semantics; merged with inline tags in (run id).log-dataset!, get-datasets — capture
row/col counts, feature names, content hash, data source per run.
New datasets table. Included in (run id) results.search-runs with :metric-key,
:op, :metric-value filters. best-run shortcut for
{:metric :accuracy :direction :max}.with-batched-metrics macro — buffers
metrics in an atom, flushes to store in one batch on exit (or on
exception). log-metric/log-metrics respect *metric-buffer*.log-table stores tables as EDN
with content-type application/x-chachaml-table. Added to the
serialize content-type→format mapping.image/*
content-type and renders inline <img> tags. Other artifacts get a
download link via /api/artifacts/:id/download.export-runs returns flat maps (params +
final metrics per run). /api/export?format=csv endpoint.create-experiment!, experiment,
experiments — name, description, owner. New experiments table
with upsert.chachaml.registry/diff-versions compares
the runs behind two versions of the same model.sklearn interop and 25 ML use case showcase.
chachaml.interop.sklearn):
tracked-fit! — fit a sklearn-compatible model, logging
training time + model hyperparameters.tracked-predict — predict with timing.evaluate! — compute + log accuracy/R² metrics.train-and-evaluate! — full pipeline: fit, predict, evaluate,
save artifact, optionally register model.extract-params — pull sklearn's .get_params().*bridge* dynamic var so tests
run without Python (mock bridge replaces libpython-clj2).requiring-resolve for the Python bridge — namespace compiles
without libpython-clj2 on the classpath.:python alias in deps.edn for users with Python + sklearn.examples/sklearn_iris.clj — runnable with
clojure -M:python:examples -m sklearn-iris.MCP server, web UI with local JS deps, and SQLite WAL mode for concurrent multi-agent access.
M7 MCP server (chachaml.mcp):
clojure -M:mcp [db-path].list_runs, get_run, compare_runs, list_models,
get_model, get_model_version..claude/mcp.json or any MCP-compatible client.org.clojure/data.json added as an optional dep (:mcp alias
for runtime, test/coverage aliases for CI).SQLite WAL mode + busy_timeout=5000 enabled on every open —
concurrent readers (UI) never block writers (training agents), and
simultaneous writers wait instead of failing with SQLITE_BUSY.
Includes a concurrent-write integration test.
M8 Web UI (chachaml.ui.*):
clojure -M:ui [db-path] [port] (default 8080)./api/{runs,runs/:id,compare,models,models/:name, experiments} — foundation for a future chat-with-data layer.ring-mock (HTML + JSON routes, 404s, filters).chachaml.core and
chachaml.store.sqlite updated to reflect shipped milestones.status->db/stage->db (and inverse)
helpers into a single kw->db/db->kw pair in
chachaml.store.sqlite.chachaml.serialize/auto-format no longer has a dead :nippy
branch for strings; behavior is unchanged (strings still go to
:nippy) but documented as intentional.chachaml.repl/pad reduced to a one-line format call.chachaml.schema/validate docstring tightened (no behavior
change).chachaml.test-helpers/with-fresh-store,
used via (use-fixtures :each h/with-fresh-store) across
core_test, registry_test, repl_test, tracking_test, and
examples_test. Drops ~30 lines of inline (with-fresh-store (fn [] …)) boilerplate per file.use-store!-returns-resolved-store test for the
store-value path.First feature-complete release covering the full minimal MLOps loop: run tracking, artifacts, model registry, tracking macro, REPL helpers.
bb.edn), tools.build entry points (build.clj).clj-kondo config (warning-level fail), cljfmt
config, kaocha runner (tests.edn), cloverage 85% line gate.chachaml.{core,context,env,serialize, registry,tracking,repl,schema} and chachaml.store.{protocol,sqlite}.{deps,lein} × JDK {17,21}) + coverage gate.CONTRIBUTING.md, LICENSE (MIT),
.github/PULL_REQUEST_TEMPLATE.md, ADRs 0001–0004.chachaml.store.sqlite implements RunStore and
Lifecycle against either a file-backed or in-memory SQLite
database. Schema migrates idempotently on every open. Tests cover
CRUD, EDN value round-tripping, query filters, and tempfile
persistence across opens.chachaml.env: best-effort capture of git SHA/branch/dirty
state, JVM, OS, user, and Clojure version.chachaml.context: *store* and *run* dynamic vars plus
a delay-initialized default SQLite store at ./chachaml.db.chachaml.core public API: use-store!, with-store,
start-run!, end-run!, with-run, log-params, log-param,
log-metrics, log-metric, runs, run, last-run. Exceptions
inside with-run mark the run :failed and re-throw; completed
runs are tap>-ed.chachaml.schema: Malli schemas for run lifecycle and logging
inputs (Status, Run, StartRunOpts, Params, Metrics,
MetricRow, QueryFilters) plus a validate helper.doc/USING-LOCALLY.md: how to depend on a local checkout from
another Clojure project (:local/root, lein install, lein
checkouts/).examples/ (added to the test classpath
via the :examples alias):
linear-regression — gradient-descent univariate fit on synthetic
data; logs per-epoch loss and final weight errors.kmeans — Lloyd's algorithm on 2D Gaussian blobs; logs
per-iteration inertia and final cluster sizes.
Each has a run-experiment! fn (called by tests against an
in-memory store) and a -main (called by clojure -M:examples -m <name>).chachaml.serialize: multimethod-dispatched encoding for
:nippy (default), :edn, :bytes, and :file formats.
Auto-detects byte[]/File and falls back to :nippy.ArtifactStore impl with filesystem-backed bytes under
<db>-artifacts/<run-id>/<name> (default
./chachaml-artifacts/). SHA-256 hash + size captured. Unique
(run_id, name) index rejects duplicates.chachaml.core/log-artifact, log-file, load-artifact,
list-artifacts. (run id) now also includes :artifacts.Artifact and ArtifactFormat Malli schemas.close!.test.check) covers
arbitrary nested EDN values for :nippy and :edn.chachaml.tracking/deftracked: defn-shaped macro that wraps
the body in with-run. Supports docstring + opts map (:experiment,
:name, :tags); a :tracked-fn tag carrying the qualified symbol
is auto-added. Nests under existing runs. clj-kondo :lint-as
config registers it as a defn-like macro.models and model_versions tables added to the SQLite schema.ModelRegistry impl with atomic stage transitions in a
transaction.chachaml.registry public API: register-model, models,
model, model-versions, promote!, load-model (with
:version/:stage selectors; default = latest production).Model, Version, Stage, RegisterOpts Malli schemas.:production version
per model survives arbitrary add/promote sequences.:staging version of linear-regression-baseline /
kmeans-baseline. Tests round-trip through the registry too.chachaml.repl:
runs-table — compact one-row-per-run table of recent runsinspect — polymorphic pretty-printer for runs (by id or map),
models (by name or map), and model versionscompare-runs — diff params + latest metric values across N
runs, returns {:runs … :params {…} :metrics {…}} with :same,
:differ, :partial partitionsprint-comparison — render the compare-runs map for humansCan you improve this documentation?Edit on GitHub
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 |