Skip to main content

Deyta CLI

A unified command-line tool for Deyta's services. Today it wraps Khora (persistent memory for AI agents); the command surface is built so future services and a cloud platform slot in without breaking existing commands.

How it works

Khora is an in-process Python library, not a server. The CLI runs a local daemon (deyta serve — a FastAPI app holding one Khora instance open) and talks to it over HTTP. The CLI itself never imports Khora. The target server is resolved per command:

--host flag  >  DEYTA_HOST env  >  active context  >  http://localhost:8787

That resolution is the local↔cloud seam: switching to a cloud platform later is a new context, not new commands.

Requirements

  • Python 3.13+
  • DEYTA_OPENAI_API_KEY in ~/.config/deyta/.env (Khora uses it for embeddings and entity extraction; deyta init prompts for it, or deyta init --yes picks it up from the environment instead of prompting)
  • Docker — only for the postgres backend (deyta db up); the embedded backend needs none

Install

deyta is a CLI, so install it as an isolated tool rather than into a project environment. This puts the deyta command on your PATH and keeps its dependencies from colliding with anything else:

uv tool install deyta-cli      # recommended
# or:
pipx install deyta-cli

Both create a dedicated environment just for Deyta and expose deyta everywhere — no virtualenv to activate. To upgrade later: uv tool upgrade deyta-cli (or pipx upgrade deyta-cli).

One-line install (curl):

If you'd rather not pick a tool, this script does it for you:

curl -fsSL https://raw.githubusercontent.com/DeytaHQ/deyta-cli/main/install.sh | sh

It picks an installer in order: uv if present (uv also fetches a Python 3.13 runtime, so you don't need a matching Python first); else pipx if you already have it and Python 3.13+; otherwise it asks before installing uv (and aborts with instructions if you decline) — it never modifies your system silently. Pin a version with DEYTA_VERSION=0.2.0, or set DEYTA_YES=1 to skip the uv prompt in CI.

Prefer to read before you pipe to a shell? Download, inspect, then run:

curl -fsSLO https://raw.githubusercontent.com/DeytaHQ/deyta-cli/main/install.sh
less install.sh        # review it
sh install.sh

This is a convenience wrapper, not a separate channel — it installs the same PyPI package as uv tool / pipx below.

macOS (Homebrew):

brew tap deytahq/deyta
brew trust deytahq/deyta    # current Homebrew requires trusting any third-party tap
brew install deyta

This installs into its own virtualenv (using prebuilt wheels for the native dependencies) and puts deyta on your PATH. Upgrade with brew upgrade deyta.

The brew trust step is a Homebrew default for all non-official taps, not something specific to Deyta — without it Homebrew refuses to load the formula.

Avoid pip install deyta-cli. Bare pip installs into whatever Python environment happens to be active, so the deyta command only works while that environment is activated — and it can clash with other packages. Use uv tool / pipx for CLIs.

From source (development)

git clone https://github.com/DeytaHQ/deyta-cli && cd deyta-cli
uv sync                        # creates .venv with all deps
uv run deyta --help            # run without activating the venv

Quickstart (embedded, no Docker)

deyta init                 # choose "embedded (sqlite_lance, no Docker)"
deyta init --yes           # or scripted: embedded backend + default models, no prompts
deyta up                   # start the whole stack in the background (datastores if postgres, then the daemon)

deyta ns create demo       # create a namespace; becomes active
deyta ingest ./docs        # walk files, chunk + remember (Rich progress)
deyta query "your question"

deyta down                 # stop the stack when you're done

deyta up is the one-command path; deyta serve still exists if you'd rather run the daemon in the foreground (and deyta db up to manage just the datastores).

Non-interactive setup

deyta init --yes runs the wizard with no prompts — every unanswered question takes its default. Flags override individual answers (each provided flag skips its own prompt even without --yes), and the API keys are read from the environment rather than prompted for. It prints a resolved-config summary so you can see exactly what it chose. Handy in CI, containers, and agent-driven setups:

DEYTA_OPENAI_API_KEY=sk-… deyta init --yes                 # embedded backend, default models
deyta init --yes --backend postgres --llm-model gpt-4o     # postgres, custom LLM

API keys are never accepted as flags (secrets don't belong in argv). Under --yes, deyta init reads DEYTA_OPENAI_API_KEY and DEYTA_API_KEY from the environment (or the global .env) and persists them; a missing key is a warning, not an error.

Commands

Command Purpose
deyta init [--yes] Scaffold deyta.toml (pick backend, ontology defaults); --yes for non-interactive/scripted setup
deyta serve [--port] [--detach] Start the daemon (foreground by default)
deyta status / deyta stop Inspect / stop a detached daemon
deyta up / deyta down Bring the whole local stack up/down (datastores + server)
deyta db up|down|status|logs Manage Postgres + Neo4j (Docker; postgres backend)
deyta ns create|list|get|delete|use Manage namespaces (namespace is the long form)
deyta memory remember|recall|forget|ingest Khora primitives
deyta ingest <path> Shorthand for memory ingest
deyta query "<text>" Shorthand for memory recall (--mode, -k, --json, --context, --filter)
deyta config Interactive TUI editor for deyta.toml settings
deyta config get|set <key> Read/write a single config value (dot notation, e.g. llm.model)
deyta config path Print the resolved config file path
deyta context use|list|current Switch between local and cloud contexts
deyta context add <name> --host <url> --api-key <key> Connect to a deployment someone else created
deyta context remove <name> Remove a context (does not destroy the deployment)
deyta deploy fly [--name] [--vm-size] [--vm-memory] [--volume-size] Deploy to Fly.io (create or redeploy)
deyta deploy scale Resize the deployed machine/volume in place (no image rebuild)
deyta deploy config Apply the deployment's config to the running app (no image rebuild)
deyta deploy destroy Tear down the Fly app and all its data
deyta login / logout Cloud auth (not yet available)
deyta version [--no-check] Show installed CLI + Khora versions; flag PyPI updates
deyta update [--yes] [--dry-run] Upgrade whichever of the CLI / Khora is outdated

Backends

  • embedded (sqlite_lance) — SQLite + LanceDB, fully in-process, zero infra. Default for quickstart.
  • postgres — Postgres + pgvector + Neo4j via deyta db up (vendored Docker Compose, pinned to pgvector/pgvector:pg17 and neo4j:2025.12.1).

Configuration & state

  • ~/.config/deyta/deyta.toml — main config: backend, server port, LLM settings, default ontology, namespace aliases, active namespace.
  • ~/.config/deyta/.env — secrets (DEYTA_OPENAI_API_KEY, optionally DEYTA_API_KEY).
  • ~/.config/deyta/config.toml — contexts (local/cloud). auth.json holds cloud tokens.
  • ~/.config/deyta/daemon.json — runtime state for a detached daemon (pid/port).

deyta config opens an interactive editor for deyta.toml — arrow keys to navigate, Enter to edit a value inline, s to save, q to quit. The editor has two views:

  • Simple (default) — shows backend, server, LLM, ontology, and secrets, plus any Khora overrides you've already set.
  • Advanced (press a) — shows every available Khora tuning parameter (~250 across 8 sections) with their defaults. Values you haven't changed appear dimmed. Edit any parameter inline; clear a value to reset it to the default.

For scripting: deyta config get llm.model / deyta config set llm.model gpt-4o.

Ontology: deyta init writes a generic default entity_types / relationship_types so deyta ingest works with no flags; override per run with --entity-types / --relationship-types.

Advanced Khora settings ([khora.*])

Beyond the basics above, every Khora tuning parameter can be set in deyta.toml under [khora.<section>] tables that mirror Khora's own config sections:

Section What it tunes
[khora.recall_vectorcypher] Recall engine: fusion weights, graph traversal depth, BM25 channel, cross-encoder + LLM reranking, extraction concurrency
[khora.llm] Temperature, max_tokens, retries, concurrency, extraction model, connection pool
[khora.pipeline] Chunking strategy/size/overlap, conversation grouping, selective entity extraction
[khora.query] Query pipeline: channel weights, entity linking, HyDE, multi-stage limits, temporal resolver
[khora.storage] Pool sizes, HNSW index parameters (connection URLs/credentials are managed by deyta and rejected here)
[khora.hooks], [khora.tenancy], [khora.dream] Semantic hooks, tenancy mode, dream-phase maintenance

Example:

[khora.recall_vectorcypher]
enable_reranking = true
enable_llm_reranking = true
llm_reranking_mode = "always"
fusion_vector_weight = 0.6
bm25_top_k = 50

[khora.llm]
temperature = 0.7
max_concurrent_llm_calls = 10

[khora.pipeline]
chunking_strategy = "semantic"
chunk_size = 512

Keys are validated against the installed Khora version's config classes — a typo fails with a suggestion instead of being silently ignored. Scripting: deyta config set khora.recall_vectorcypher.bm25_top_k 40 (values are parsed as JSON: true, 0.4, [1, 2]).

Deploy to Fly.io

deyta deploy fly runs Postgres + Neo4j + the Deyta daemon on a single Fly Machine with one persistent volume mounted at /data (both databases store their data there — it survives restarts, redeploys, and resizes).

  • Multiple deployments — pass --name to create a new deployment even when one already exists. Each deployment gets its own context. Without --name, the CLI detects the existing deployment and offers to redeploy it.

    deyta deploy fly                        # creates deyta-quiet-maple (random name)
    deyta deploy fly --name khora-staging   # creates a second deployment
    
  • Machine sizing — defaults to performance-4x / 16 GB with a 20 GB volume. Override at deploy time (--vm-size performance-2x --vm-memory 8gb --volume-size 40) or later with deyta deploy scale (in-place update, no image rebuild; volumes can grow, never shrink). A plain redeploy reuses the deployment's stored sizing. The entrypoint gives Neo4j a quarter of machine memory for JVM heap and a quarter for page cache.

  • Config of record — each deployment keeps a config snapshot under ~/.config/deyta/deploy/<app>/deyta.toml. With the Fly context active, deyta config edits that snapshot (not your local deyta.toml) and offers to apply it. deyta deploy config pushes it to the running app as Fly secrets — no image rebuild. Redeploys ask which config to use (deployment's current config, local deyta.toml, or step-by-step; --config-source deployed|local for scripts) and never silently pick up local settings.

  • Restarts and downtime — applying config or scaling restarts the machine behind Fly's health checks. There is no zero-downtime path with this architecture: a Fly volume attaches to exactly one machine and both databases live on it, so a second machine can't take over the data. Config-only applies skip the image pull; the restart window is dominated by Neo4j startup (roughly 20–60 s), during which Fly's proxy queues incoming requests.

Sharing a deployment with teammates

The person who runs deyta deploy fly gets a local context wired up automatically. A teammate who needs to use the same deployment can connect with deyta context add:

deyta context add deyta-quiet-maple \
    --host https://deyta-quiet-maple.fly.dev \
    --api-key <key>

This creates a local context pointing at the existing deployment and switches to it. All deyta commands (query, ingest, config, etc.) now target that deployment. The API key is the one printed at the end of deyta deploy fly — share it through a secure channel.

To switch back to local development:

deyta context use local

To list all contexts or remove one:

deyta context list
deyta context remove deyta-quiet-maple   # does not destroy the deployment

Server API key (optional)

Set DEYTA_API_KEY to require Bearer-token authentication on every request. When the variable is unset the server accepts unauthenticated requests (the default for local-only use). deyta init prompts for this; under deyta init --yes it is read from the environment (DEYTA_API_KEY) instead — unset just means the server runs without auth. You can also add it directly to ~/.config/deyta/.env:

DEYTA_API_KEY=your-secret-here

Clients must then send Authorization: Bearer your-secret-here on each request. The TypeScript SDK already sends the apiKey you pass at construction, so no SDK changes are needed — just pass the same value.

Releasing

The package builds with hatchling; the deyta command comes from the [project.scripts] entry point in pyproject.toml. Pushing a vX.Y.Z tag publishes to PyPI (via GitHub Actions Trusted Publishing) and bumps the Homebrew tap. See RELEASING.md for the one-time setup and the release steps.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

deyta_cli-0.4.2.tar.gz (67.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

deyta_cli-0.4.2-py3-none-any.whl (84.7 kB view details)

Uploaded Python 3

File details

Details for the file deyta_cli-0.4.2.tar.gz.

File metadata

  • Download URL: deyta_cli-0.4.2.tar.gz
  • Upload date:
  • Size: 67.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for deyta_cli-0.4.2.tar.gz
Algorithm Hash digest
SHA256 063a5497eff8fd2472fb5410b56701ff7b90d76826c35512b50acf748d708971
MD5 f4d5fb4e85887ce4fd2dcf32ef59a593
BLAKE2b-256 433bbd142b0cddf2a7f8266f5418d281a11d8240ab2ad514614ae1138454042b

See more details on using hashes here.

Provenance

The following attestation bundles were made for deyta_cli-0.4.2.tar.gz:

Publisher: release.yml on DeytaHQ/deyta-cli

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file deyta_cli-0.4.2-py3-none-any.whl.

File metadata

  • Download URL: deyta_cli-0.4.2-py3-none-any.whl
  • Upload date:
  • Size: 84.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for deyta_cli-0.4.2-py3-none-any.whl
Algorithm Hash digest
SHA256 d9959dd05e774f65a931c6cfcab9e8e166d6885b57ed3a002ed3500f26c1e5f0
MD5 0811fbbf1f85de45d17384c0c5d46708
BLAKE2b-256 46529c9678fe401e53ff6e3a0c635ed4904bf082fe4f90fc6cd203ebf8546e17

See more details on using hashes here.

Provenance

The following attestation bundles were made for deyta_cli-0.4.2-py3-none-any.whl:

Publisher: release.yml on DeytaHQ/deyta-cli

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page