Add local-first setup onboarding

This commit is contained in:
Himanshu Dongre 2026-05-16 22:22:21 +05:30
parent f22056418d
commit 8388bf8a1f
8 changed files with 93 additions and 26 deletions

View file

@ -10,7 +10,20 @@
# your shell profile, the shell value takes precedence.
# Database
DATABASE_URL=postgresql://smriti:smriti@localhost:5432/smriti
#
# Solo/local mode is the low-friction default. It uses a local SQLite
# database file and does not require Docker or Postgres.
SMRITI_DB_MODE=local
# Optional: override the local SQLite database path.
# Default: ~/.smriti/smriti.db
# SMRITI_LOCAL_DB_PATH=~/.smriti/smriti.db
# Shared/team mode: uncomment for Postgres-backed operation.
# If DATABASE_URL is explicitly set to a Postgres URL, Smriti preserves
# Postgres behavior.
# SMRITI_DB_MODE=postgres
# DATABASE_URL=postgresql://smriti:smriti@localhost:5432/smriti
# Provider API keys — uncomment and set the ones you want to use.
# If unset, the backend falls back to config/providers.yaml, then to

View file

@ -224,8 +224,8 @@ are a client of it. You do not own it.
That is your reachability check — no separate health probe needed.
- **If the backend is unreachable, stop and tell the human.** Say:
"The Smriti backend is not reachable at http://localhost:8000.
Please start it with `make dev` and ensure Postgres is running
via `docker compose up -d postgres`."
Please start it with `make dev-local` for solo/local mode, or
`make dev-postgres` for Postgres/shared-team mode."
- **Do not attempt to start, restart, or manage the backend or
Docker yourself.** Starting the server from inside an agent's
tool loop creates environment-variable inheritance issues that

View file

@ -1,4 +1,4 @@
.PHONY: help dev up down test test-unit test-int lint format migrate
.PHONY: help dev dev-local dev-postgres up down test test-unit test-int lint format migrate setup setup-local setup-postgres
VENV := cd backend && source .venv/bin/activate &&
@ -21,9 +21,15 @@ logs: ## Follow logs
# ── Backend ──────────────────────────────────────────────────────────────────
dev: ## Run backend dev server locally (requires venv)
dev: ## Run backend dev server with configured DB mode (requires venv)
$(VENV) uvicorn app.main:app --reload --port 8000
dev-local: ## Run backend in local-first SQLite mode
$(VENV) SMRITI_DB_MODE=local uvicorn app.main:app --reload --port 8000
dev-postgres: ## Run backend in Postgres mode
$(VENV) SMRITI_DB_MODE=postgres uvicorn app.main:app --reload --port 8000
test: ## Run all backend tests
$(VENV) python -m pytest -v
@ -44,8 +50,8 @@ format: ## Format backend code
# ── Database ─────────────────────────────────────────────────────────────────
migrate: ## Run database migrations
$(VENV) alembic upgrade head
migrate: ## Run database migrations for Postgres/shared mode
$(VENV) SMRITI_DB_MODE=postgres alembic upgrade head
migration: ## Create a new migration (usage: make migration msg="add users table")
$(VENV) alembic revision --autogenerate -m "$(msg)"
@ -71,11 +77,25 @@ install: ## Install all dependencies (creates venv, installs CLI + MCP server)
cd cli && ../backend/.venv/bin/pip install -e .
cd frontend && npm install
setup: ## Full local setup (venv + deps + migrations)
setup: setup-local ## Default solo setup (local-first SQLite)
setup-local: ## Solo setup: venv + deps + local SQLite path, no Docker
cp -n .env.example .env || true
mkdir -p "$$HOME/.smriti"
$(MAKE) install
@echo "\n✅ Setup complete!"
@echo " Mode: local SQLite"
@echo " Local DB path: $${SMRITI_LOCAL_DB_PATH:-$$HOME/.smriti/smriti.db}"
@echo " Activate the CLI: source backend/.venv/bin/activate"
@echo " Start backend: make dev-local"
@echo " Start frontend: make dev-frontend"
setup-postgres: ## Shared/team setup: venv + deps + Docker Postgres + migrations
cp -n .env.example .env || true
$(MAKE) install
docker compose up -d postgres
$(MAKE) migrate
@echo "\n✅ Setup complete!"
@echo "\n✅ Postgres setup complete!"
@echo " Activate the CLI: source backend/.venv/bin/activate"
@echo " Start backend: make dev"
@echo " Start backend: make dev-postgres"
@echo " Start frontend: make dev-frontend"

View file

@ -72,9 +72,10 @@ One project, one Smriti Space, multiple agents. Each reads the state, declares i
## Getting started
You will need: Python 3.11+, Node 18+, Docker (for Postgres).
You will need: Python 3.11+ and Node 18+. Docker is only needed for
Postgres/shared-team mode.
### 1. Clone and set up
### 1. Clone and set up for solo/local mode
```bash
git clone https://github.com/himanshudongre/smriti
@ -89,11 +90,14 @@ cp .env.example .env
# SMRITI_GENERIC_MODEL=llama3.1:8b
# See .env.example for details.
docker compose up -d postgres # start the database
make setup # backend venv + deps + migrations + CLI + frontend
make setup-local # backend venv + CLI + frontend, no Docker
```
`make setup` installs the backend, the CLI (`smriti` + `smriti-mcp`), and the frontend. The CLI binaries are installed into the backend venv at `backend/.venv/bin/`. To use them from your shell:
Local mode uses SQLite at `~/.smriti/smriti.db` by default. Override it
with `SMRITI_LOCAL_DB_PATH=/path/to/smriti.db` if you want the database
somewhere else.
`make setup-local` installs the backend, the CLI (`smriti` + `smriti-mcp`), and the frontend. The CLI binaries are installed into the backend venv at `backend/.venv/bin/`. To use them from your shell:
```bash
source backend/.venv/bin/activate
@ -102,12 +106,32 @@ source backend/.venv/bin/activate
### 2. Start the backend and frontend
```bash
make dev # backend on http://localhost:8000 (keep running)
make dev-local # backend on http://localhost:8000 (keep running)
make dev-frontend # frontend on http://localhost:5173 (separate terminal)
```
**For the chat UI only, you're done.** Open http://localhost:5173.
### Shared/team mode with Postgres
Postgres remains the stronger shared/team mode. Use it when you want an
explicit database service, Docker-backed state, or a closer path toward a
hosted deployment.
```bash
cp .env.example .env
# In .env, set:
# SMRITI_DB_MODE=postgres
# DATABASE_URL=postgresql://smriti:smriti@localhost:5432/smriti
make setup-postgres # starts Docker Postgres and runs migrations
make dev-postgres # backend on http://localhost:8000
make dev-frontend # frontend on http://localhost:5173
```
If `DATABASE_URL` is explicitly set to a Postgres URL, Smriti preserves
Postgres behavior.
### 3. For coding agents
**Quick path:**
@ -139,7 +163,11 @@ smriti skills install claude-code # → .claude/skills/smriti/SKILL.md
smriti skills install codex # → AGENTS.md (commit it)
```
**Runtime model.** Postgres runs in Docker. The backend runs locally via `make dev`. The human starts both. Agents are clients of `http://localhost:8000` — they do not manage the backend.
**Runtime model.** In solo/local mode, Smriti stores state in a SQLite
file and the backend runs locally via `make dev-local`. In shared/team
mode, Postgres runs in Docker and the backend runs via `make dev-postgres`.
Agents are clients of `http://localhost:8000` — they do not manage the
backend.
### 4. Auto-inject state at session start (Claude Code)
@ -152,7 +180,7 @@ smriti skills install codex # → AGENTS.md (commit it)
"hooks": [
{
"type": "command",
"command": "smriti state my-project --compact 2>/dev/null || echo 'Smriti backend not reachable. Start it with: make dev'"
"command": "smriti state my-project --compact 2>/dev/null || echo 'Smriti backend not reachable. Start it with: make dev-local'"
}
]
}

View file

@ -23,6 +23,11 @@ export SMRITI_API_URL=http://localhost:8000
Or pass `--api-url` on any command.
Local-first vs Postgres storage is configured on the backend, not in the
CLI. For solo use, start the backend with `make dev-local`; for
Postgres/shared-team use, start it with `make dev-postgres`. The CLI and
MCP server keep talking to the same HTTP API either way.
## MCP server
Run Smriti as a local MCP server so agents inside Claude Code, Cursor, or Windsurf can read and write reasoning state natively — no subprocess-shelling to the `smriti` binary.

View file

@ -937,8 +937,8 @@ def cmd_init(client: SmritiClient, args: argparse.Namespace) -> None:
except Exception:
_fail(
f"error: Cannot reach Smriti backend at {client.base_url}.\n"
"Start the backend with `make dev` and ensure Postgres is running "
"via `docker compose up -d postgres`."
"Start the backend with `make dev-local` for solo/local mode, "
"or `make dev-postgres` for Postgres/shared-team mode."
)
return
@ -999,7 +999,7 @@ def cmd_init(client: SmritiClient, args: argparse.Namespace) -> None:
settings_path = Path(".claude/settings.json")
hook_command = (
f"backend/.venv/bin/smriti state {space_name} --preview 2>/dev/null "
f"|| echo 'Smriti backend not reachable. Start with: make dev'"
f"|| echo 'Smriti backend not reachable. Start with: make dev-local'"
)
hook_entry = {
"type": "command",

View file

@ -1,5 +1,5 @@
---
smriti_skill_pack_version: 2.2
smriti_skill_pack_version: 2.3
title: Smriti — how to use it well
target: {{display_name}}
---
@ -241,8 +241,8 @@ are a client of it. You do not own it.
That is your reachability check — no separate health probe needed.
- **If the backend is unreachable, stop and tell the human.** Say:
"The Smriti backend is not reachable at http://localhost:8000.
Please start it with `make dev` and ensure Postgres is running
via `docker compose up -d postgres`."
Please start it with `make dev-local` for solo/local mode, or
`make dev-postgres` for Postgres/shared-team mode."
- **Do not attempt to start, restart, or manage the backend or
Docker yourself.** Starting the server from inside an agent's
tool loop creates environment-variable inheritance issues that
@ -257,7 +257,8 @@ are a client of it. You do not own it.
the backend is running stale code. Tell the human: "The backend
at localhost:8000 does not support [feature]. Its git_sha is
[sha] but the current repo is at [repo sha]. Please restart
the backend with `make dev` to pick up recent changes."
the backend with the same mode you are using (`make dev-local`
or `make dev-postgres`) to pick up recent changes."
For worktree-aware coordination, the capabilities list should include
both `worktrees` and `worktree_binding`.
- **When to check capabilities:** You do NOT need to check on every

View file

@ -43,7 +43,7 @@ def test_load_template_nonempty():
def test_get_version_parses_frontmatter():
version = get_version()
assert version == "2.2"
assert version == "2.3"
def test_get_version_raises_when_frontmatter_missing():