Getting Started

Try Semantic Rails with one command, create your own package, then connect an HTTP client or an agent. Every command uses the published package from PyPI, except the contributor steps marked "source checkout".

1. Try it, then install

You need uv. It fetches a compatible Python (3.11 or newer) if your system Python is older.

one command, nothing installed
uvx semantic-rails ask --package jaffle_shop "revenue by store" --run

To keep a semantic-rails command on your PATH, install it as a tool. If uv warns that its tool directory isn't on your PATH, run uv tool update-shell and open a new terminal.

install the command
uv tool install semantic-rails

Or install it into a project environment. Pin the Python version: on a machine without a uv-managed Python, a bare uv venv can pick up the system Python (3.9 on stock macOS, 3.10 on Ubuntu 22.04), and then the install fails. With pip, run python -m pip install semantic-rails inside a Python 3.11+ environment. On Windows, activate the environment with .venv\Scripts\activate. Windows isn't covered by our checks yet.

project environment
uv venv --python 3.12
source .venv/bin/activate
uv pip install semantic-rails
source checkout (contributors)
git clone https://github.com/semantic-rails/semantic-rails.git
cd semantic-rails
uv sync --group dev

The source checkout includes the worked examples under examples/. From a checkout, prefix commands with uv run.

2. Create your first package
terminal
uvx semantic-rails init my_package --yes
uvx semantic-rails project validate --path ./my_package
uvx semantic-rails ask --path ./my_package "total amount by event type" --run

If you installed the command, drop uvx. Pass --path on commands that use your own package, or run them inside the package directory. Without either, and without a saved profile, commands stop with no_package_selected and list the ways to choose a package; at an interactive terminal, ask first offers the bundled sample package. (--package only names a bundled package, such as jaffle_shop.)

The interactive wizard, semantic-rails setup --interactive, walks through the same steps. It can set a local profile and add the Query MCP and Architect MCP to Claude Desktop or Codex. On POSIX it can also start a managed MCP HTTP server; on Windows it uses client-launched stdio or a foreground HTTP terminal. Run it from an installed semantic-rails, not through uvx: like mcp setup, it writes the running Python's path into the client config.

This is the deterministic setup layer for a new project. It creates a split-layout package with starter data, examples, and package-local tests. Architect MCP can guide the same workflow from an MCP client, but the terminal path is always available.

The REPL is optional: semantic-rails repl --path ./my_package opens it. It is useful for local authoring loops with repeated ls, ask, run, debug, and validate commands; agents and automation should use explicit CLI commands or MCP tools. Type exit to quit the REPL.

Optional local defaults live in ~/.semantic_rails/profiles.yml. Run semantic-rails profile init --package-path ./my_package when you want the human CLI to use this package without repeating --path. Keep that file local; it is not package source, deployment config, or cloud tenant config.

3. Optional bundled smoke package

These use the semantic-rails command installed in step 1. If you only use uvx, put uvx in front of each one.

terminal
semantic-rails packages
semantic-rails ask --package jaffle_shop "revenue by store" --run
semantic-rails catalog --package jaffle_shop

jaffle_shop is a bundled synthetic fixture for smoke testing. It is not a prerequisite for modeling your own data.

3b. Optional HTTP API and MCP server
terminal
PACKAGE_PATH="$(pwd)/my_package"
semantic-rails mcp setup --path "$PACKAGE_PATH"
stdio client config
semantic-rails mcp setup --path "$PACKAGE_PATH" --client both --mcp query --install --yes

Use absolute paths for MCP client configuration because the client may not start in your project directory. --mcp query installs the query server only; --mcp both also installs the Architect MCP, which can edit package files. Don't run mcp setup --install through uvx: the config would point into uv's cache, which uv cache clean deletes. Install the command first. Copy-paste setup for Claude Code, Codex, Cursor and the hosted demo is in the Agent Quickstart.

For HTTP-capable MCP clients, run one foreground package server in a separate terminal opened in the directory that holds my_package. It serves the HTTP API and stateless Streamable HTTP at http://127.0.0.1:8091/mcp; stop it with Ctrl-C.

HTTP API and MCP (separate terminal)
PACKAGE_PATH="$(pwd)/my_package"
semantic-rails serve --path "$PACKAGE_PATH" --host 127.0.0.1 --port 8091
List MCP tools
curl -s http://127.0.0.1:8091/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -H 'MCP-Protocol-Version: 2025-11-25' \
  --data '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' \
  | python -c 'import json, sys; tools=json.load(sys.stdin)["result"]["tools"]; print(f"{len(tools)} tools"); print("\n".join("- " + tool["name"] for tool in tools))'

When SEMANTIC_RAILS_API_KEYS or SEMANTIC_RAILS_API_KEY_FILE is configured, /mcp requires Authorization: Bearer ..., X-API-Key, or X-Semantic-API-Key. Without configured keys, authentication is disabled for local use; /health stays public. These headers are for the engine you run yourself; Semantic Rails Cloud API keys use Authorization: ApiKey <key> (see Connect assistants to Cloud). Caller policy context comes from trusted transport headers rather than tool arguments. Install a trusted policy-context resolver before exposing the server to callers with different permissions.

HTTP API (separate terminal)
semantic-rails serve --package jaffle_shop --host 127.0.0.1 --port 8081

Steps 4 and 5 use IDs from the bundled jaffle_shop package, so this serves it. For your own package, use --path "$PACKAGE_PATH" and your package's IDs.

semantic-rails serve and semantic-rails mcp stdio are foreground server processes. Run them from a separate terminal or let an MCP client launch stdio from its generated config.

Docker and ASGI make the runtime deployable, but this is not a hosted cloud bundle, managed acceleration layer, or full enterprise auth system.

4. Follow the guided builder path

The preferred public flow is no longer "write raw JSON first." Start with discovery, inspect the semantic object, then ask for the next legal move.

curl
curl -s -X POST http://127.0.0.1:8081/api/v1/discover \
  -H "Content-Type: application/json" \
  -d '{
    "terms": "revenue by store"
  }'
curl
curl -s -X POST http://127.0.0.1:8081/api/v1/build-options \
  -H "Content-Type: application/json" \
  -d '{
    "query": {
      "select": [{ "expression": "measure.jaffle.revenue_usd", "as": "revenue_usd" }]
    },
    "focus_terms": "revenue by store",
    "focus_object_id": "measure.jaffle.revenue_usd",
    "step": "group_by",
    "limit": 6
  }'
5. Run a first query
curl
curl -s -X POST http://127.0.0.1:8081/api/v1/query \
  -H "Content-Type: application/json" \
  -d '{
    "query": {
      "select": ["measure.jaffle.revenue_usd"],
      "group_by": ["dimension.jaffle_store_name"],
      "time": {
        "temporal_role": "temporal_role.jaffle_order_time",
        "grain": "month"
      },
      "order_by": [{ "field": "revenue_usd", "direction": "desc" }],
      "limit": 5
    }
  }'

Querying a package outside configs/semantic_rails/

query, compile, validate, and MCP all accept --path <dir>. Use that form for a package created in your own project folder:

path-based package query
semantic-rails query --path ./my_package --query-json '{
  "select": ["metric.my_package.total_amount"],
  "limit": 5
}' --verbosity minimal --sql-profile off

The compact flags keep first-run output focused on rows and row counts. Omit them when you want SQL, trace, and explain metadata.

6. Run the test suite (source checkout)
terminal
uv run pytest -q tests/semantic_rails
What to do next