From 78b95f4564f50106736f664cb9219461d13c64b8 Mon Sep 17 00:00:00 2001 From: AivanF Date: Tue, 26 May 2026 10:09:36 +0300 Subject: [PATCH] Consolidate & fix storage docs --- CLAUDE.md | 2 +- docs/configuration/storage.md | 26 +++++++++++++++++++++----- docs/dbt/dbt_import.md | 2 +- docs/getting-started/mcp.md | 2 +- docs/interfaces/cli.md | 22 +++++----------------- docs/interfaces/mcp.md | 8 +++++--- docs/interfaces/rest-api.md | 8 +++++--- docs/reference/cli.md | 20 ++++---------------- docs/reference/mcp.md | 6 +++--- slayer/storage/base.py | 8 ++++++-- 10 files changed, 52 insertions(+), 52 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 071950ea..a628e013 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -147,7 +147,7 @@ poetry run ruff check slayer/ tests/ ## CLI -- All commands accept `--storage` (directory for YAML, `.db` file for SQLite). Defaults to platform-appropriate path (`~/.local/share/slayer` on Linux, `~/Library/Application Support/slayer` on macOS). Override with `$SLAYER_STORAGE` env var. Legacy `--models-dir` still works. +- All commands accept `--storage` (directory for YAML, `.db` file for SQLite). Defaults to platform-appropriate path (`~/.local/share/slayer` on Linux, `~/Library/Application Support/slayer` on macOS, `%LOCALAPPDATA%\slayer` on Windows). Override with `$SLAYER_STORAGE` env var. - `slayer query` supports `--dry-run` (preview SQL) and `--explain` (execution plan, dialect-aware). - `slayer datasources create-inline` supports `--password-stdin` for secure credential input. - `slayer datasources test` verifies connectivity. diff --git a/docs/configuration/storage.md b/docs/configuration/storage.md index 7cb18c6b..6b3d5d5c 100644 --- a/docs/configuration/storage.md +++ b/docs/configuration/storage.md @@ -1,18 +1,34 @@ -# Storage Backends +# Storage -SLayer uses a storage backend to persist model and datasource configurations. +SLayer uses a storage backend to persist model and datasource configurations, agent memories, and embedding indexes. ## Default Location -When no `--storage` flag or `$SLAYER_STORAGE` env var is set, SLayer uses a platform-appropriate default: +When no `--storage` flag or `$SLAYER_STORAGE` env var is set, SLayer picks a platform-appropriate default: | Platform | Default path | |---|---| -| Linux | `~/.local/share/slayer` (or `$XDG_DATA_HOME/slayer`) | +| Linux | `~/.local/share/slayer` (or `$XDG_DATA_HOME/slayer` if set) | | macOS | `~/Library/Application Support/slayer` | | Windows | `%LOCALAPPDATA%\slayer` | -This means `slayer serve` works out of the box with no flags. Override with `--storage` or `$SLAYER_STORAGE`. +This means `slayer serve` works out of the box with no flags. + +## Overriding the Storage Path + +Pass `--storage` to any CLI command, or set the `$SLAYER_STORAGE` environment variable: + +```bash +# YAML directory +slayer serve --storage ./slayer_data + +# SQLite database (auto-detected by .db/.sqlite/.sqlite3 extension) +slayer serve --storage slayer.db + +# Or via environment variable +export SLAYER_STORAGE=./my_project/slayer_data +slayer serve +``` ## Available Backends diff --git a/docs/dbt/dbt_import.md b/docs/dbt/dbt_import.md index ae01e96d..2fb4c0d2 100644 --- a/docs/dbt/dbt_import.md +++ b/docs/dbt/dbt_import.md @@ -246,7 +246,7 @@ Arguments: Options: --datasource NAME SLayer datasource name for imported models (required) - --storage PATH Storage directory for output (default: ./slayer_data) + --storage PATH Storage directory for output (default: platform path, see Storage docs) --include-hidden-models Also import regular dbt models (not wrapped by a semantic_model) as hidden SLayer models via SQL introspection. Requires the `dbt` extra. diff --git a/docs/getting-started/mcp.md b/docs/getting-started/mcp.md index 6c92850d..85e28a80 100644 --- a/docs/getting-started/mcp.md +++ b/docs/getting-started/mcp.md @@ -60,7 +60,7 @@ claude mcp list The recommended approach is to drop a datasource YAML file into your storage folder. This keeps credentials out of the agent conversation and lets you use environment variable references. -Create a file at `slayer_data/datasources/mydb.yaml`: +Create a file in the `datasources/` subdirectory of your [storage path](../configuration/storage.md) (e.g. `~/.local/share/slayer/datasources/mydb.yaml`): ```yaml name: mydb diff --git a/docs/interfaces/cli.md b/docs/interfaces/cli.md index b2c99012..90929215 100644 --- a/docs/interfaces/cli.md +++ b/docs/interfaces/cli.md @@ -4,21 +4,9 @@ SLayer provides a command-line interface for server management, querying, and mo ## Storage -All commands accept a `--storage` flag to specify where models and datasources are stored: +All commands accept a `--storage` flag to specify where models and datasources are stored. When omitted, SLayer uses a platform-appropriate default (`~/.local/share/slayer` on Linux, `~/Library/Application Support/slayer` on macOS, `%LOCALAPPDATA%\slayer` on Windows). See [Storage](../configuration/storage.md) for full details on backends, resolution, and overrides. -```bash -# YAML files in a directory (default) -slayer serve --storage ./slayer_data - -# SQLite database file (auto-detected by .db/.sqlite/.sqlite3 extension) -slayer serve --storage slayer.db -``` - -If unset, SLayer uses a platform-appropriate path: `~/.local/share/slayer` on Linux, `~/Library/Application Support/slayer` on macOS, `%LOCALAPPDATA%\slayer` on Windows. Override with `$SLAYER_STORAGE`. - -Another environment variable, `SLAYER_INGEST_ON_STARTUP`, mirrors the `--ingest-on-startup` flag on `slayer serve` / `slayer mcp` — truthy values (`1`, `true`, `yes`, case-insensitive) enable boot-time idempotent auto-ingestion across every configured datasource. See [Ingesting at Startup](../concepts/ingestion.md#ingesting-at-startup). - -The legacy `--models-dir` flag still works but is deprecated in favor of `--storage`. +The `SLAYER_INGEST_ON_STARTUP` environment variable mirrors the `--ingest-on-startup` flag on `slayer serve` / `slayer mcp` — truthy values (`1`, `true`, `yes`, case-insensitive) enable boot-time idempotent auto-ingestion across every configured datasource. See [Ingesting at Startup](../concepts/ingestion.md#ingesting-at-startup). ## Commands @@ -36,7 +24,7 @@ slayer serve --storage slayer.db |------|---------|-------------| | `--host` | `0.0.0.0` | Bind address | | `--port` | `5143` | Port number | -| `--storage` | platform-appropriate path | Storage path (directory for YAML, `.db` file for SQLite) | +| `--storage` | [platform default](../configuration/storage.md) | Storage path (directory for YAML, `.db` file for SQLite) | | `--demo` | off | Spin up the bundled Jaffle Shop DuckDB datasource and ingest its models on startup. Idempotent; requires the `duckdb` extra and `jafgen`. | | `--ingest-on-startup` | off | Walk every configured datasource and run idempotent auto-ingestion before the port opens. Per-datasource errors are logged to stderr and never abort startup. Also enabled by `SLAYER_INGEST_ON_STARTUP=1`. | @@ -56,7 +44,7 @@ For MCP over HTTP (SSE), use `slayer serve` instead — it exposes MCP at `/mcp/ | Flag | Default | Description | |------|---------|-------------| -| `--storage` | platform-appropriate path | Storage path (directory for YAML, `.db` file for SQLite) | +| `--storage` | [platform default](../configuration/storage.md) | Storage path (directory for YAML, `.db` file for SQLite) | | `--demo` | off | Spin up the bundled Jaffle Shop DuckDB datasource and ingest its models on startup. Idempotent; requires the `duckdb` extra and `jafgen`. | | `--ingest-on-startup` | off | Walk every configured datasource and run idempotent auto-ingestion before stdio JSON-RPC starts. Per-datasource errors are logged to stderr and never abort startup. Also enabled by `SLAYER_INGEST_ON_STARTUP=1`. | @@ -96,7 +84,7 @@ The positional argument is interpreted as: | Flag | Default | Description | |------|---------|-------------| -| `--storage` | platform-appropriate path | Storage path (directory for YAML, `.db` file for SQLite) | +| `--storage` | [platform default](../configuration/storage.md) | Storage path (directory for YAML, `.db` file for SQLite) | | `--format` | `table` | Output format: `table` or `json` | | `--dry-run` | | Generate SQL without executing | | `--explain` | | Run EXPLAIN ANALYZE on the query | diff --git a/docs/interfaces/mcp.md b/docs/interfaces/mcp.md index 52a846af..453b431d 100644 --- a/docs/interfaces/mcp.md +++ b/docs/interfaces/mcp.md @@ -13,11 +13,13 @@ The agent spawns SLayer as a subprocess and communicates via stdin/stdout. You d **Claude Code setup:** ```bash -claude mcp add slayer -- slayer mcp --ingest-on-startup --storage ./slayer_data +claude mcp add slayer -- slayer mcp --ingest-on-startup ``` `--ingest-on-startup` runs idempotent auto-ingestion across every configured datasource before the stdio channel opens. Drop the flag (or set `SLAYER_INGEST_ON_STARTUP=0`) to defer ingestion to a manual `ingest_datasource_models` call. +Storage defaults to the [platform-appropriate path](../configuration/storage.md). Override with `--storage /path/to/data` if needed. + If `slayer` is installed in a virtualenv (e.g. via Poetry), use the full path to the executable so the agent can find it regardless of working directory: ```bash @@ -26,7 +28,7 @@ poetry env info -p # e.g. /home/user/.venvs/slayer-abc123 # Register with the full path -claude mcp add slayer -- /home/user/.venvs/slayer-abc123/bin/slayer mcp --storage /path/to/slayer_data +claude mcp add slayer -- /home/user/.venvs/slayer-abc123/bin/slayer mcp ``` ### SSE (remote) @@ -35,7 +37,7 @@ MCP over HTTP via Server-Sent Events. You run `slayer serve` yourself — it exp ```bash # 1. Start the server -slayer serve --ingest-on-startup --storage ./slayer_data +slayer serve --ingest-on-startup # REST API at http://localhost:5143/ # MCP SSE at http://localhost:5143/mcp/sse ``` diff --git a/docs/interfaces/rest-api.md b/docs/interfaces/rest-api.md index 6efa8483..08810ba1 100644 --- a/docs/interfaces/rest-api.md +++ b/docs/interfaces/rest-api.md @@ -5,14 +5,16 @@ SLayer provides a FastAPI-based REST API on port **5143** by default. ## Start the Server ```bash -slayer serve --storage ./slayer_data -slayer serve --host 0.0.0.0 --port 8080 --storage ./slayer_data +slayer serve +slayer serve --host 0.0.0.0 --port 8080 # Run idempotent auto-ingestion across every configured datasource before # the port opens. Same as setting SLAYER_INGEST_ON_STARTUP=1. -slayer serve --ingest-on-startup --storage ./slayer_data +slayer serve --ingest-on-startup ``` +Storage defaults to the [platform-appropriate path](../configuration/storage.md). Override with `--storage ./slayer_data` or `$SLAYER_STORAGE`. + ## Endpoints ### Health Check diff --git a/docs/reference/cli.md b/docs/reference/cli.md index 2c63bfbe..97b55c40 100644 --- a/docs/reference/cli.md +++ b/docs/reference/cli.md @@ -4,19 +4,7 @@ SLayer provides a command-line interface for server management, querying, and mo ## Storage -All commands accept a `--storage` flag to specify where models and datasources are stored: - -```bash -# YAML files in a directory (default) -slayer serve --storage ./slayer_data - -# SQLite database file (auto-detected by .db/.sqlite/.sqlite3 extension) -slayer serve --storage slayer.db -``` - -The default is `./slayer_data` (YAML). Override with `$SLAYER_STORAGE` or `$SLAYER_MODELS_DIR` env vars. - -The legacy `--models-dir` flag still works but is deprecated in favor of `--storage`. +All commands accept a `--storage` flag to specify where models and datasources are stored. When omitted, SLayer uses a platform-appropriate default (`~/.local/share/slayer` on Linux, `~/Library/Application Support/slayer` on macOS, `%LOCALAPPDATA%\slayer` on Windows). See [Storage](../configuration/storage.md) for full details on backends, resolution, and overrides. ## Commands @@ -36,7 +24,7 @@ slayer serve --ingest-on-startup # run idempotent ingest over every configur |------|---------|-------------| | `--host` | `0.0.0.0` | Bind address | | `--port` | `5143` | Port number | -| `--storage` | `./slayer_data` | Storage path (directory for YAML, .db file for SQLite) | +| `--storage` | [platform default](../configuration/storage.md) | Storage path (directory for YAML, `.db` file for SQLite) | | `--demo` | off | Generate and ingest the bundled Jaffle Shop demo before starting (idempotent). | | `--ingest-on-startup` | off | Walk every configured datasource and run idempotent auto-ingestion before the port opens. Per-datasource errors are logged to stderr and never abort startup. Also enabled by `SLAYER_INGEST_ON_STARTUP=1`. | @@ -56,7 +44,7 @@ For MCP over HTTP (SSE), use `slayer serve` instead — it exposes MCP at `/mcp/ | Flag | Default | Description | |------|---------|-------------| -| `--storage` | `./slayer_data` | Storage path | +| `--storage` | [platform default](../configuration/storage.md) | Storage path (directory for YAML, `.db` file for SQLite) | | `--demo` | off | Generate and ingest the bundled Jaffle Shop demo before starting (idempotent). | | `--ingest-on-startup` | off | Walk every configured datasource and run idempotent auto-ingestion before stdio JSON-RPC starts. Per-datasource errors are logged to stderr and never abort startup. Also enabled by `SLAYER_INGEST_ON_STARTUP=1`. | @@ -83,7 +71,7 @@ slayer query @query.json --explain | Flag | Default | Description | |------|---------|-------------| -| `--storage` | `./slayer_data` | Storage path | +| `--storage` | [platform default](../configuration/storage.md) | Storage path (directory for YAML, `.db` file for SQLite) | | `--format` | `table` | Output format: `table` or `json` | | `--dry-run` | | Generate SQL without executing | | `--explain` | | Run EXPLAIN ANALYZE on the query | diff --git a/docs/reference/mcp.md b/docs/reference/mcp.md index f65d6416..fd23a53e 100644 --- a/docs/reference/mcp.md +++ b/docs/reference/mcp.md @@ -9,7 +9,7 @@ The fastest way to run SLayer is via `uvx` — no install needed. You only need **Claude Code:** ```bash -claude mcp add slayer -- uvx --from 'motley-slayer[postgres]' slayer mcp --ingest-on-startup --storage ./slayer_data +claude mcp add slayer -- uvx --from 'motley-slayer[postgres]' slayer mcp --ingest-on-startup ``` **JSON config** (Claude Desktop, Cursor, and other MCP-compatible agents): @@ -19,7 +19,7 @@ claude mcp add slayer -- uvx --from 'motley-slayer[postgres]' slayer mcp --inges "mcpServers": { "slayer": { "command": "uvx", - "args": ["--from", "motley-slayer[postgres]", "slayer", "mcp", "--ingest-on-startup", "--storage", "./slayer_data"] + "args": ["--from", "motley-slayer[postgres]", "slayer", "mcp", "--ingest-on-startup"] } } } @@ -44,7 +44,7 @@ The agent spawns SLayer as a subprocess and communicates via stdin/stdout. You d MCP over HTTP via Server-Sent Events. You run `slayer serve` yourself — it exposes both the REST API and the MCP SSE endpoint on the same port: ```bash -uvx --from 'motley-slayer[postgres]' slayer serve --ingest-on-startup --storage ./slayer_data +uvx --from 'motley-slayer[postgres]' slayer serve --ingest-on-startup # REST API at http://localhost:5143/ # MCP SSE at http://localhost:5143/mcp/sse ``` diff --git a/slayer/storage/base.py b/slayer/storage/base.py index f93d05cf..0bf5dec9 100644 --- a/slayer/storage/base.py +++ b/slayer/storage/base.py @@ -1,6 +1,7 @@ """Abstract storage protocol and factory.""" import os +import sys from abc import ABC, abstractmethod from pathlib import Path from typing import Any, Callable, Dict, List, Optional, Tuple @@ -41,7 +42,7 @@ def default_storage_path() -> str: 2. $SLAYER_MODELS_DIR environment variable (legacy, if set) 3. Platform default: - Linux: $XDG_DATA_HOME/slayer (defaults to ~/.local/share/slayer) - - macOS: ~/Library/Application Support/slayer + - macOS: ~/Library/Application Support/slayer (ignores $XDG_DATA_HOME) - Windows: %LOCALAPPDATA%/slayer """ env = os.environ.get("SLAYER_STORAGE") or os.environ.get("SLAYER_MODELS_DIR") @@ -51,8 +52,11 @@ def default_storage_path() -> str: if os.name == "nt": # Windows base = Path(os.getenv("LOCALAPPDATA", Path.home() / "AppData" / "Local")) + elif sys.platform == "darwin": + # macOS + base = Path.home() / "Library" / "Application Support" else: - # MacOS, Linux, etc. + # Linux, etc. base = Path(os.getenv("XDG_DATA_HOME", Path.home() / ".local" / "share")) return str(base / "slayer")