dither
CLI reference

dither init

Initialize the dither config dir, write config, and choose where the markdown library lives.

dither init is the required first step before any library-needing command will run. It writes <config-dir>/config.json, creates the library directory, starts the daemon, and lets it index + embed your library so the first dither search doesn't hang.

dither init
dither init --library ~/Documents/dither
dither init --no-download
dither init --library ~/Documents/dither --no-wait

Config dir

Resolved once, first match wins:

  1. $DITHER_DIR
  2. $XDG_CONFIG_HOME/dither
  3. ~/.dither

Arguments

FlagDefaultEffect
--library <p>prompt on TTY, else errorLibrary directory. Created if missing. Canonicalised via realpath. Must be a writable directory.
--no-downloaddownload onSkip qmd model weight prefetch (offline / CI) by disabling embedding for this init. dither index update clears it.
--no-welcomewelcome onSkip writing <library>/welcome/welcome.md.
--no-waitwait onDispatch the daemon work and return immediately; check progress with dither status.

If you don't pass --library on a TTY, init drops into an interactive prompt for the path (default: $DITHER_DIR/library, else ~/.dither/library — the library default deliberately ignores XDG). Without a TTY, --library is required and init exits with code 2 if it's missing. Cancelling the prompt exits 130 with no partial state.

What it does

  1. Ensure the config dir exists.
  2. If config.json already exists: print the current paths and exit 0. --library on a re-run is ignored with a note that re-init isn't supported.
  3. Resolve the library path (flag or interactive prompt):
    • If the path doesn't exist, create it (with parents) and report (created). Errors if the parent doesn't exist or isn't writable.
    • If the path exists and isn't a directory, error out.
    • If the path exists and isn't writable, error out.
    • Resolve symlinks via realpath and store the canonical target in config.
  4. If a qmd config is found, adopt its collections into collections.external (silent no-op otherwise). Collections inside the library are skipped.
  5. Write <config-dir>/config.json (schema.version: 2, library.path, collections.external).
  6. Unless --no-welcome, write <library>/welcome/welcome.md (never clobbers an existing file).
  7. Start the daemon (or reuse a running one) and — unless --no-wait — follow its reconcile: model download, indexing, embedding. Ctrl-C detaches; the daemon keeps going.

Pre-init guardrail

Until init has run, every library-needing command refuses with:

error: dither is not initialized. Run `dither init` to set up your library.

Library-needing commands: search, get, index update, index cancel, collection, plugin install, plugin run, daemon start. Commands that don't touch the library (--help, --version, env, plugin list, plugin remove, plugin runs, plugin oauth, daemon status/stop/reload/logs, status, init itself) keep working.

Where things land

After a successful init:

<config-dir>/config.json            ← schema + library.path + external collections
<config-dir>/qmd-index.sqlite       ← always in the config dir, regardless of library
<library>/welcome/welcome.md        ← starter doc (skip with --no-welcome)
<library>/                          ← markdown lives here; collections are top-level subdirs

The qmd index always lives in the config dir. If you point dither at a folder also indexed by qmd-CLI elsewhere, the two indices are independent.

Reconfiguring later

dither init is one-shot — re-running it on an already-initialised config dir is a read-only no-op. There is no --force. To change the library path, remove <config-dir>/config.json and run dither init again:

rm ~/.dither/config.json
dither init --library ~/Documents/dither

The old library directory is not moved or deleted — it stays on disk for you to handle. The qmd index also stays; drop qmd-index.sqlite if you want it rebuilt against the new library.

If the daemon is running, send it a reload after the reconfig so it picks up the new library:

dither daemon reload

Without the reload, the daemon keeps watching the previous library until it next restarts.

Examples

Fresh user, default everything (interactive prompt):

$ dither init

Welcome to dither.

? Where should your library live? (ENTER for ~/.dither/library)

 library: ~/.dither/library (created)
 wrote ~/.dither/config.json
 wrote welcome doc to ~/.dither/library/welcome/welcome.md
 starting dither daemon...
 daemon started (pid 41233)
 indexing library indexed 1 file
 embedding library embedded 4 chunks in 2.1s

next:
  dither search 'welcome to dither'
  dither get <id from above>

Adopt an existing folder as the library:

$ dither init --library ~/Documents/dither
 library: ~/Documents/dither
 found qmd config at ~/.config/qmd/config.toml
  adopted 2 collections: notes, papers
 wrote ~/.dither/config.json
...

CI / offline:

$ dither init --library ~/.dither/library --no-download --no-wait
 library: ~/.dither/library (created)
 wrote ~/.dither/config.json
 weights skipped (--no-download)
 daemon started (pid 41240)
 dispatched daemon will finish in background
  dither status         # check progress

Re-run is a no-op:

$ dither init
dither is already initialized at ~/.dither
  library: ~/.dither/library