Metadata-Version: 2.4
Name: deyta-cli
Version: 0.4.0
Summary: A unified command-line tool for Deyta's services, wrapping Khora persistent memory for AI agents.
Project-URL: Homepage, https://github.com/DeytaHQ/deyta-cli
Project-URL: Repository, https://github.com/DeytaHQ/deyta-cli
Project-URL: Issues, https://github.com/DeytaHQ/deyta-cli/issues
Author-email: "AllTheData Inc. (Deyta)" <dev@deyta.ai>
License-Expression: MIT
License-File: LICENSE
Keywords: agents,ai,cli,embeddings,khora,memory,rag,typer
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Utilities
Requires-Python: >=3.13
Requires-Dist: fastapi>=0.115.0
Requires-Dist: httpx>=0.28.0
Requires-Dist: khora[embedded]>=0.21.1
Requires-Dist: mcp>=1.27.0
Requires-Dist: packaging>=24.0
Requires-Dist: questionary>=2.1.1
Requires-Dist: rich>=15.0.0
Requires-Dist: textual>=0.80.0
Requires-Dist: tomli-w>=1.0.0
Requires-Dist: typer>=0.26.7
Requires-Dist: uvicorn[standard]>=0.34.0
Provides-Extra: test
Requires-Dist: pytest-asyncio>=0.25; extra == 'test'
Requires-Dist: pytest>=8.0; extra == 'test'
Description-Content-Type: text/markdown

# Deyta CLI

A unified command-line tool for Deyta's services. Today it wraps
[Khora](https://github.com/DeytaHQ/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)
- 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:

```bash
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:

```bash
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:

```bash
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):**

```bash
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)

```bash
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)

```bash
deyta init                 # choose "embedded (sqlite_lance, no Docker)"
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).

## Commands

| Command | Purpose |
|---|---|
| `deyta init` | Scaffold `deyta.toml` (pick backend, ontology defaults) |
| `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`) |
| `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 (future) cloud |
| `deyta deploy fly [--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. 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:

```toml
[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).

- **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.

### 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; 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](RELEASING.md) for the one-time setup and the release steps.
