diff --git a/README.md b/README.md
index 2ae224c..1035fbb 100644
--- a/README.md
+++ b/README.md
@@ -1,266 +1,52 @@
# Axolotl
-CLI-native lightweight issue tracker for you and your agents. A SQLite-based
-single portable binary, built from ~1300 lines of Go code.
+CLI-native issue tracker for you and your agents. Single binary, SQLite-backed, ~1300 lines of Go.
-## Features
+## Install
-- **Issues with dependencies** - blocks, subtask, related relations
-- **Tagging system** - flexible tags with `_key::value` property pattern
-- **Namespacing** - organize issues by project or team
-- **Due dates** - track deadlines
-- **Thread-safe** - WAL mode for concurrent access
-- **Multiuser support** - @mentions and assignments, inbox per user
-- **JSON output** - all commands support `--json` for agent integration
-- **Alias system** - define custom command shortcuts with argument expansion
-- **Single binary** - no dependencies, portable `.ax.db` file
+**Alpine Linux** (apk):
+Download from the Gitea package registry. Have a look
+[here](https://g.eliaskohout.de/eliaskohout/-/packages/alpine/axolotl/).
-## Installation
+**Arch Linux** (pacman):
+Download from the Gitea package registry. Have a look
+[here](https://g.eliaskohout.de/eliaskohout/-/packages/arch/axolotl/).
+**From source:**
```bash
-go build -o ax .
+go build -o ax ./src
```
+**Docker (server mode):**
+```bash
+docker run -v ./data:/data g.eliaskohout.de/eliaskohout/axolotl-server:latest
+```
+
+Packages are built automatically on every version tag for `linux/amd64` and `linux/arm64`.
+
## Quick Start
```bash
-# Initialize a new database
-ax init .
-
-# Create an issue
-ax add "Implement feature X" --tag backend --prio high
-
-# Create with relations
-ax add "Fix bug in auth" --rel blocks:abc12
-
-# List open issues
-ax list --status open
-
-# Show issue details
-ax show abc12
-
-# Update an issue
-ax update abc12 --status done
-
-# View your inbox
-ax inbox
-
-# Define an alias
-ax alias mywork "list --namespace myproject --status open" --desc "My project tasks"
+ax init . # create .ax.db in current dir
+ax add "Fix login bug" --prio high # create an issue
+ax list --status open # list open issues
+ax show abc12 # show issue details
+ax update abc12 --status done # close issue
+ax inbox # your @mention inbox
```
-## Commands
+## Key Features
-### `ax init [path]`
+- **Graph relations** — `blocks`, `subtask`, `related`, `assignee`
+- **Namespaces** — organize issues by project or team
+- **Permissions** — per-node access control (`can_read`, `can_write`, `has_ownership`)
+- **Aliases** — custom shortcuts with `$me`, `$1`, `$@` expansion
+- **JSON output** — `--json` flag on all commands for agent integration
+- **Multiuser** — `@mention` auto-creates inbox entries; `AX_USER` to switch users
+- **Server mode** — HTTP JSON API with optional OIDC authentication (`ax serve` / `ax login`)
+- **Portable** — single `.ax.db` file, no server required
-Create a new `.ax.db` database in the specified directory (default: current).
-
-### `ax add
[flags]`
-
-Create a new node.
-
-| Flag | Description |
-|------|-------------|
-| `--type` | Node type: `issue` (default), `note`, `user`, `namespace` |
-| `--status` | Status: `open` (default), `done` |
-| `--prio` | Priority: `high`, `medium`, `low` |
-| `--namespace` | Namespace (default: current user) |
-| `--tag` | Add tag (repeatable) |
-| `--due` | Due date |
-| `--content` | Content/body text |
-| `--rel` | Add relation `type:id` (repeatable) |
-
-### `ax update [flags]`
-
-Update a node.
-
-| Flag | Description |
-|------|-------------|
-| `--title` | New title |
-| `--status` | New status |
-| `--prio` | New priority |
-| `--type` | New type |
-| `--namespace` | New namespace |
-| `--assignee` | New assignee |
-| `--due` | New due date |
-| `--clear-due` | Clear due date |
-| `--content` | New content |
-| `--tag` | Add tag (repeatable) |
-| `--tag-remove` | Remove tag (repeatable) |
-| `--rel` | Add relation `type:id` (repeatable) |
-| `--rel-remove` | Remove relation `type:id` (repeatable) |
-
-### `ax show `
-
-Display node details.
-
-### `ax list [flags]`
-
-Query and list nodes.
-
-| Flag | Description |
-|------|-------------|
-| `--type` | Filter by type |
-| `--status` | Filter by status |
-| `--prio` | Filter by priority |
-| `--namespace` | Filter by namespace |
-| `--tag` | Filter by tag (repeatable) |
-| `--assignee` | Filter by assignee |
-| `--mention` | Filter by mention |
-
-### `ax edit `
-
-Open node content in `$EDITOR`.
-
-### `ax del [-f|--force]`
-
-Delete a node. Prompts for confirmation unless `--force`.
-
-### `ax alias [name] [command] [flags]`
-
-Manage aliases.
-
-```bash
-ax alias # list all aliases
-ax alias mywork "list --tag work" # create alias
-ax alias mywork # show alias command
-ax alias mywork "list --tag work2" # update alias
-ax alias del mywork # delete alias
-```
-
-**Default aliases:**
-
-| Alias | Command | Description |
-|-------|---------|-------------|
-| `mine` | `list --assignee $me --type issue --status open` | Show open issues assigned to you |
-| `due` | `list --type issue --status open` | Show open issues |
-| `inbox` | `list --mention $me` | Show your inbox |
-
-**Alias argument expansion:**
-
-| Variable | Expands to |
-|----------|------------|
-| `$me` | Current username |
-| `$@` | All arguments |
-| `$1`, `$2`, ... | Positional arguments |
-
-```bash
-# Create alias with argument expansion
-ax alias find "list --tag $1 --status $2"
-ax find backend open # expands to: list --tag backend --status open
-```
-
-## Relations
-
-Relations connect nodes together:
-
-| Type | Meaning | Behavior |
-|------|---------|----------|
-| `blocks` | A blocks B — B can't close until A is done | Enforced on status=done |
-| `subtask` | A is a subtask of B | |
-| `related` | A is related to B | |
-| `assignee` | A is assigned to user | Single-value; set via `--assignee` flag |
-| `in_namespace` | A belongs to namespace | Single-value; set via `--namespace` flag |
-
-```bash
-# Block an issue (B can't close until A is done)
-ax update A --rel blocks:B
-
-# Assign to user
-ax update abc12 --assignee alice
-
-# Create subtask
-ax update abc12 --rel subtask:parent12
-```
-
-## Tags and Properties
-
-Tags are flexible labels. Tags with pattern `_key::value` are properties:
-
-```bash
-# Regular tag
-ax add "Task" --tag backend
-
-# Property tags (set via flags)
-ax add "Task" --type issue --status open --prio high
-# Equivalent to: --tag _type::issue --tag _status::open --tag _prio::high
-```
-
-**Built-in properties:**
-
-| Property | Values | Required |
-|----------|--------|----------|
-| `_type` | `issue`, `note`, `user`, `namespace` | Yes (default: `issue`) |
-| `_status` | `open`, `done` | No |
-| `_prio` | `high`, `medium`, `low` | No |
-
-## Mentions and Inbox
-
-Use `@username` in title or content to automatically add to user's inbox:
-
-```bash
-ax add "Review PR @alice" --content "@bob please check"
-# Both alice and bob get this in their inbox
-```
-
-View inbox:
-```bash
-ax inbox # your inbox
-AX_USER=alice ax inbox # alice's inbox
-```
-
-## JSON Output
-
-All commands support `--json` for machine-readable output:
-
-```bash
-ax list --status open --json
-ax show abc12 --json
-```
-
-Example output:
-```json
-{
- "id": "abc12",
- "title": "Implement feature",
- "content": "Description here",
- "created_at": "2026-03-25T10:00:00Z",
- "updated_at": "2026-03-25T10:00:00Z",
- "tags": ["_type::issue", "_status::open", "backend"],
- "relations": {
- "blocks": ["def34"]
- }
-}
-```
-
-## Configuration
-
-`ax` stores user configuration in a JSON file. It searches for `.axconfig` in the
-current directory and parent directories (like git finds `.git`), falling back to
-`~/.config/ax/config.json`.
-
-**Config file format:**
-```json
-{
- "user": "alice",
- "aliases": [
- {"name": "mywork", "command": "list --namespace myproject", "description": "My tasks"}
- ]
-}
-```
-
-## Database Location
-
-`ax` searches for `.ax.db` in the current directory and parent directories,
-similar to how git finds `.git`. This allows you to run commands from any
-subdirectory.
-
-## Environment Variables
-
-| Variable | Description |
-|----------|-------------|
-| `AX_USER` | Override current username |
-| `EDITOR` | Editor for `ax edit` (default: `vi`) |
+For full command reference and examples, see [USAGE.md](USAGE.md).
## License
diff --git a/USAGE.md b/USAGE.md
new file mode 100644
index 0000000..b1ad238
--- /dev/null
+++ b/USAGE.md
@@ -0,0 +1,194 @@
+# Axolotl Usage Reference
+
+## Commands
+
+### `ax init [path]`
+Create a new `.ax.db` in the specified directory (default: current).
+
+### `ax add [flags]`
+| Flag | Description |
+|------|-------------|
+| `--type` | `issue` (default), `note`, `user`, `namespace` |
+| `--status` | `open` (default), `done` |
+| `--prio` | `high`, `medium`, `low` |
+| `--namespace` | Namespace (default: current user) |
+| `--tag` | Add tag (repeatable) |
+| `--due` | Due date |
+| `--content` | Body text |
+| `--rel` | Relation `type:id` (repeatable) |
+
+### `ax update [flags]`
+| Flag | Description |
+|------|-------------|
+| `--title` | New title |
+| `--status` | New status |
+| `--prio` | New priority |
+| `--type` | New type |
+| `--namespace` | Transfer to namespace |
+| `--assignee` | Assign to user |
+| `--due` / `--clear-due` | Set or clear due date |
+| `--content` | New body text |
+| `--tag` / `--tag-remove` | Add or remove tag |
+| `--rel` / `--rel-remove` | Add or remove relation `type:id` |
+
+### `ax show `
+Display node details.
+
+### `ax list [flags]`
+| Flag | Description |
+|------|-------------|
+| `--type` | Filter by type |
+| `--status` | Filter by status |
+| `--prio` | Filter by priority |
+| `--namespace` | Filter by namespace |
+| `--tag` | Filter by tag (repeatable) |
+| `--assignee` | Filter by assignee |
+| `--mention` | Filter by mention |
+
+### `ax edit `
+Open node content in `$EDITOR`.
+
+### `ax del [-f]`
+Delete a node. Prompts for confirmation unless `--force`.
+
+### `ax alias [name] [command]`
+```bash
+ax alias # list all aliases
+ax alias mywork "list --tag work" # create/update alias
+ax alias del mywork # delete alias
+```
+
+**Built-in aliases:** `mine`, `due`, `inbox`
+
+**Argument expansion:** `$me` → current user, `$@` → all args, `$1`/`$2`/… → positional
+
+## Relations
+
+| Type | Description |
+|------|-------------|
+| `blocks` | Prevents target from closing until this is done |
+| `subtask` | Marks as subtask of target |
+| `related` | General association |
+| `assignee` | Assigns to a user (single-value) |
+
+```bash
+ax update A --rel blocks:B # A blocks B
+ax update abc12 --assignee alice # assign to alice
+```
+
+## Tags and Properties
+
+Tags follow the `_key::value` pattern for properties:
+
+| Property | Values |
+|----------|--------|
+| `_type` | `issue`, `note`, `user`, `namespace` |
+| `_status` | `open`, `done` |
+| `_prio` | `high`, `medium`, `low` |
+
+## Mentions and Inbox
+
+Use `@username` in title or content to add to a user's inbox:
+```bash
+ax add "Review PR @alice" # alice gets an inbox entry
+ax inbox # your inbox
+AX_USER=alice ax inbox # alice's inbox
+```
+
+## JSON Output
+
+All commands support `--json`:
+```bash
+ax list --status open --json
+ax show abc12 --json
+```
+
+## Configuration
+
+`ax` searches upward from CWD for `.axconfig`, falling back to `~/.config/ax/config.json`.
+
+```json
+{
+ "user": "alice",
+ "aliases": [
+ {"name": "mywork", "command": "list --namespace myproject", "description": "My tasks"}
+ ]
+}
+```
+
+## Server Mode
+
+`ax` can run as a shared HTTP JSON API server:
+
+```bash
+ax serve # starts server on configured host:port (default: 0.0.0.0:7000)
+```
+
+The server exposes the same operations (add, list, show, update, delete) over HTTP. Clients connect by setting `remote.host` / `remote.port` in their config — the CLI then transparently routes calls to the server instead of a local database.
+
+### OIDC Authentication
+
+The server supports OIDC for authentication. Configure in `.axconfig`:
+
+```json
+{
+ "serve": { "host": "0.0.0.0", "port": 7000 },
+ "oidc": {
+ "issuer": "https://your-idp.example.com",
+ "client_id": "axolotl",
+ "client_secret": "secret",
+ "public_url": "https://ax.example.com",
+ "user_claim": "preferred_username"
+ }
+}
+```
+
+Client login:
+```bash
+ax login # opens browser for OIDC flow, saves session token
+```
+
+Without OIDC configured, the server accepts an `X-Ax-User` header for the username (development/trusted networks only).
+
+### Docker
+
+```bash
+docker run -v ./data:/data g.eliaskohout.de/eliaskohout/axolotl-server:latest
+```
+
+The image runs `ax serve` and exposes port 7000. Mount a volume at `/data` to persist the database.
+
+## Permission Model
+
+Every node has per-node access control. Permissions are transitive via BFS from the requesting user's own node.
+
+| Level | Relation | Grants |
+|-------|----------|--------|
+| 1 | `can_read` | Read / show / list |
+| 2 | `can_create_rel` | Create relations pointing to this node |
+| 3 | `can_write` | Update title, content, tags |
+| 4 | `has_ownership` | Full control including delete and granting access |
+
+- Creators automatically get `has_ownership` on nodes they create.
+- Namespace nodes own regular nodes within them; users own their namespaces.
+- Deleting an owner cascades to all nodes it owns.
+- User nodes and namespace nodes are globally readable.
+
+```bash
+# Grant bob read access to a node
+ax update --rel can_read:
+
+# Grant bob write access
+ax update --rel can_write:
+```
+
+## Environment Variables
+
+| Variable | Description |
+|----------|-------------|
+| `AX_USER` | Override current username |
+| `EDITOR` | Editor for `ax edit` (default: `vi`) |
+
+## Database Location
+
+`ax` searches for `.ax.db` upward from CWD (like git finds `.git`), so commands work from any subdirectory.