diff --git a/README.md b/README.md
index 346138d5..07bfc0c7 100644
--- a/README.md
+++ b/README.md
@@ -110,6 +110,14 @@ Requires Python 3.13+.
uv tool install authsome
```
+By default, the CLI talks to hosted Authsome at `https://api.authsome.ai`. To use a local or self-hosted daemon instead, set `AUTHSOME_BASE_URL`:
+
+```bash
+export AUTHSOME_BASE_URL=http://127.0.0.1:7998
+```
+
+You only need `AUTHSOME_CALLBACK_BASE_URL` when you operate a self-hosted server or run a local daemon on a non-default host or port. Set it to the URL users can open in their browser for claim and OAuth callback links.
+
## Self-hosting
Run a persistent daemon in Docker — no Python required on the host:
diff --git a/docker-compose.yml b/docker-compose.yml
index 08fe4cf1..15c239f5 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -9,9 +9,9 @@ services:
- authsome-data:/data/authsome
environment:
AUTHSOME_HOME: /data/authsome
- # Set this to the public URL of this server so OAuth callbacks resolve correctly.
- # Example: AUTHSOME_SERVER_BASE_URL: https://auth.example.com
- AUTHSOME_SERVER_BASE_URL: ""
+ # Self-hosted servers need this public URL so OAuth callbacks resolve correctly.
+ # Example: AUTHSOME_CALLBACK_BASE_URL: https://auth.example.com
+ AUTHSOME_CALLBACK_BASE_URL: http://localhost:7998
# Encryption mode: "local_key" (default) or "keyring"
AUTHSOME_ENCRYPTION_MODE: local_key
AUTHSOME_LOG_LEVEL: info
diff --git a/docs/guides/self-hosting.md b/docs/guides/self-hosting.md
index f174b850..9d1d164f 100644
--- a/docs/guides/self-hosting.md
+++ b/docs/guides/self-hosting.md
@@ -18,12 +18,14 @@ curl http://localhost:7998/health
The daemon is now available at `http://localhost:7998`.
-Point agents at it by setting:
+Authsome clients use hosted Authsome by default. Point agents at this self-hosted daemon by setting:
```bash
export AUTHSOME_BASE_URL=http://localhost:7998
```
+Because this is a self-hosted server, set `AUTHSOME_CALLBACK_BASE_URL` to the URL users can open in their browser for claim, input, and OAuth callback links. The Docker Compose quick start sets it to `http://localhost:7998`. Change it only when you bind the daemon to a different host or port, or put it behind a reverse proxy.
+
## Environment variables
| Variable | Default | Description |
@@ -31,7 +33,8 @@ export AUTHSOME_BASE_URL=http://localhost:7998
| `AUTHSOME_HOME` | `/data/authsome` | Root directory for credentials, keys, and the database |
| `AUTHSOME_HOST` | `0.0.0.0` | Interface the daemon binds to inside the container |
| `AUTHSOME_PORT` | `7998` | TCP port |
-| `AUTHSOME_BASE_URL` | _(derived from host:port)_ | Public URL used to build OAuth callback URLs. **Must be set when behind a reverse proxy.** On client machines, set this to point the CLI at a remote daemon. |
+| `AUTHSOME_BASE_URL` | `https://api.authsome.ai` | Client runtime target. On client machines, set this to point the CLI and proxy at a local or self-hosted daemon. |
+| `AUTHSOME_CALLBACK_BASE_URL` | `http://127.0.0.1:7998` | Server public URL used to build claim, input, and OAuth callback links. Set this only for self-hosted servers or local daemons running on a non-default browser-facing host or port. |
| `AUTHSOME_ENCRYPTION_MODE` | `local_key` | `local_key` stores the master key on disk; `keyring` uses the OS keyring (not available in containers) |
| `AUTHSOME_LOG_LEVEL` | `info` | Uvicorn log level (`debug`, `info`, `warning`, `error`) |
| `AUTHSOME_ANALYTICS` | `1` | Set to `0` to disable telemetry |
@@ -83,7 +86,7 @@ services:
expose:
- "7998"
environment:
- AUTHSOME_BASE_URL: https://auth.example.com
+ AUTHSOME_CALLBACK_BASE_URL: https://auth.example.com
volumes:
- authsome-data:/data/authsome
diff --git a/docs/site/concepts/the-daemon.mdx b/docs/site/concepts/the-daemon.mdx
index 1ed50aa2..7ee0ce17 100644
--- a/docs/site/concepts/the-daemon.mdx
+++ b/docs/site/concepts/the-daemon.mdx
@@ -6,7 +6,7 @@ icon: "server"
keywords: ["authsome daemon", "AUTHSOME_BASE_URL", "AUTHSOME_BASE_URL", "authsome dashboard"]
---
-Authsome operates as a persistent local daemon (by default running on `127.0.0.1:7998`). The CLI and the injection proxy act as thin clients that communicate with this daemon.
+Authsome can operate against a persistent local daemon, usually running on `127.0.0.1:7998`. Hosted Authsome is the default client target; set `AUTHSOME_BASE_URL=http://127.0.0.1:7998` when you want the CLI and injection proxy to use a local daemon. You only need `AUTHSOME_CALLBACK_BASE_URL` for self-hosted servers or local daemons running on a non-default browser-facing host or port.
## Concept and motivation
diff --git a/docs/site/installation.mdx b/docs/site/installation.mdx
index eaebaf15..2268ffac 100644
--- a/docs/site/installation.mdx
+++ b/docs/site/installation.mdx
@@ -66,6 +66,10 @@ Authsome runs on Python 3.13 or newer. It ships as a single PyPI package with no
+
+ Authsome clients use hosted Authsome at `https://api.authsome.ai` by default. Set `AUTHSOME_BASE_URL` only when you want the CLI and proxy to use a local or self-hosted Authsome server.
+
+
Every command in the docs is written as `authsome ` and assumes you ran `uv tool install authsome` (or `pip install authsome`). If you skipped install and prefer one-off runs, prefix every command with `uvx authsome@latest` instead of `authsome`.
@@ -83,7 +87,7 @@ If `doctor` reports failures, see [Diagnose with doctor](/troubleshooting/doctor
## First-run initialization
-On `authsome init`, authsome initializes its home directory at `~/.authsome/`, creates a generated identity handle and Ed25519 DID, and registers that identity with the local daemon:
+On `authsome init`, authsome initializes its home directory at `~/.authsome/`, creates a generated identity handle and Ed25519 DID, and registers that identity with the configured Authsome server:
```text
~/.authsome/
diff --git a/docs/site/quickstart.mdx b/docs/site/quickstart.mdx
index 69579a30..af9443ca 100644
--- a/docs/site/quickstart.mdx
+++ b/docs/site/quickstart.mdx
@@ -15,6 +15,10 @@ This page covers both. Pick the one that matches how you will actually use it.
- Python 3.13 or newer
- A graphical browser on the same machine (for the initial login). For SSH or CI, see [Headless setup](/guides/headless-device-code).
+
+ The CLI targets hosted Authsome by default. For local development or self-hosted deployments, set `AUTHSOME_BASE_URL` before running `authsome` commands.
+
+
## Verify the install
```bash
diff --git a/docs/site/reference/cli.mdx b/docs/site/reference/cli.mdx
index 78cf8a17..be7cae77 100644
--- a/docs/site/reference/cli.mdx
+++ b/docs/site/reference/cli.mdx
@@ -12,7 +12,7 @@ All commands support `--json` for machine-readable output, `--quiet` to suppress
| `connections` | Inspect and manage stored provider connections. |
| `daemon` | Manage the local Authsome daemon. |
| `doctor` | Run health checks on directory layout and encryption. |
-| `init` | Initialize local storage and register a fresh profile. |
+| `init` | Create a local identity and register it with the configured Authsome server. |
| `log` | View structured audit entries or the raw client debug log. |
| `login ` | Authenticate with PROVIDER using the configured flow. |
| `logout ` | Log out of the specified PROVIDER connection. |
diff --git a/docs/site/reference/environment-variables.mdx b/docs/site/reference/environment-variables.mdx
index e659afac..d7ca4b2f 100644
--- a/docs/site/reference/environment-variables.mdx
+++ b/docs/site/reference/environment-variables.mdx
@@ -9,26 +9,41 @@ Authsome interacts with environment variables in three roles: **inputs** that ch
| Variable | Purpose |
|----------|---------|
-| `AUTHSOME_BASE_URL` | The daemon URL. On client machines, set this to point the CLI and proxy at a remote daemon instead of auto-starting one locally. On the daemon host, set this to the public URL when behind a reverse proxy — authsome uses it to build OAuth callback URLs such as `/auth/callback/oauth`. Defaults to `http://127.0.0.1:7998`. |
+| `AUTHSOME_BASE_URL` | Client runtime target. Defaults to `https://api.authsome.ai`. Set this on client machines to point the CLI and proxy at a local or self-hosted daemon. |
+| `AUTHSOME_CALLBACK_BASE_URL` | Server public URL used to build claim, input, device, success, and OAuth callback links. If unset, the server falls back to the default local daemon URL, `http://127.0.0.1:7998`. Set this only when you operate a self-hosted server or run a local daemon on a non-default browser-facing host or port. |
| `AUTHSOME_HOME` | Override the default `~/.authsome` directory. Useful for tests, ephemeral environments, and per-project vaults. |
| `HTTP_PROXY` / `HTTPS_PROXY` | Honored by authsome's own outbound HTTP requests (token endpoints, device flow polling). The proxy started by `authsome run` is **set** as these variables in the child process; it does not chain through them. |
-### `AUTHSOME_BASE_URL` for remote daemons
+### Runtime target and callback URL
For remote daemon deployments:
- set `AUTHSOME_BASE_URL` to the full daemon URL on client machines
-- set `AUTHSOME_BASE_URL` to the public-facing URL on the daemon host when behind a reverse proxy
+- set `AUTHSOME_CALLBACK_BASE_URL` on the daemon host only when you are self-hosting, such as behind a reverse proxy
- when `AUTHSOME_BASE_URL` points at a non-local host, the CLI will not attempt to manage daemon state
-Example:
+Client example:
```bash
export AUTHSOME_BASE_URL=https://authsome.internal.example.com
-uv run authsome list
+authsome provider list
```
-When running the daemon locally, you typically do not need to set `AUTHSOME_BASE_URL`.
+Server example:
+
+```bash
+export AUTHSOME_CALLBACK_BASE_URL=https://authsome.internal.example.com
+authsome daemon serve
+```
+
+For local daemon mode, set `AUTHSOME_BASE_URL` explicitly:
+
+```bash
+export AUTHSOME_BASE_URL=http://127.0.0.1:7998
+authsome login github
+```
+
+The default local daemon address, `http://127.0.0.1:7998`, does not need `AUTHSOME_CALLBACK_BASE_URL`. If you run the local daemon on a custom host or port, also set `AUTHSOME_CALLBACK_BASE_URL` to the browser-facing URL. Authsome does not infer callback URLs from custom daemon bind flags.
### Provider-specific input variables
diff --git a/docs/site/troubleshooting/daemon-issues.mdx b/docs/site/troubleshooting/daemon-issues.mdx
index 71462732..587e3309 100644
--- a/docs/site/troubleshooting/daemon-issues.mdx
+++ b/docs/site/troubleshooting/daemon-issues.mdx
@@ -54,7 +54,7 @@ Common root causes:
## CLI can't find the daemon
-The CLI looks at `AUTHSOME_BASE_URL` first, then falls back to `http://127.0.0.1:7998`.
+The CLI looks at `AUTHSOME_BASE_URL` first, then falls back to hosted Authsome at `https://api.authsome.ai`. Set `AUTHSOME_BASE_URL=http://127.0.0.1:7998` for local daemon mode.
```bash
echo $AUTHSOME_BASE_URL
@@ -63,7 +63,7 @@ echo $AUTHSOME_BASE_URL
If it's set to a hosted URL that's currently unreachable:
```bash
-unset AUTHSOME_BASE_URL
+export AUTHSOME_BASE_URL=http://127.0.0.1:7998
authsome whoami
```
@@ -72,7 +72,8 @@ The CLI will start a local daemon and verify it's reachable.
If you do want a hosted daemon and it's unreachable, the fix is on the daemon host. Check that:
- The daemon process is running there.
-- `AUTHSOME_BASE_URL` on the daemon matches the URL you're calling.
+- `AUTHSOME_BASE_URL` on the client matches the URL you're calling.
+- if this is self-hosted, `AUTHSOME_CALLBACK_BASE_URL` on the daemon host matches the browser-facing URL used for claim and OAuth callback links.
- Ingress is allowed from your client's network (private VPC, VPN, or whatever the team uses).
diff --git a/src/authsome/__init__.py b/src/authsome/__init__.py
index ae168d79..98e5bf42 100644
--- a/src/authsome/__init__.py
+++ b/src/authsome/__init__.py
@@ -1,15 +1,16 @@
"""
-Authsome — A portable local authentication library for AI agents and developer tools.
+Authsome — A hosted-by-default authentication library for AI agents and developer tools.
Provides credential management for third-party services with support for:
- OAuth2 (PKCE, Device Code, DCR + PKCE)
- API key management
-- Encrypted local storage (OS keyring or local file)
+- Encrypted credential storage
Usage:
- Run `authsome login openai` to start the local daemon and connect a
- provider, then use `authsome run ...` to inject credentials through the
- local proxy.
+ Run `authsome login openai` to connect a provider through the configured
+ Authsome server, then use `authsome run ...` to inject credentials through
+ the local proxy. Set `AUTHSOME_BASE_URL` to opt into a local or self-hosted
+ Authsome server.
"""
from importlib.metadata import PackageNotFoundError as _PkgNotFoundError
diff --git a/src/authsome/cli/commands/core.py b/src/authsome/cli/commands/core.py
index 668615dc..f51d3412 100644
--- a/src/authsome/cli/commands/core.py
+++ b/src/authsome/cli/commands/core.py
@@ -269,7 +269,7 @@ async def run(ctx_obj: ContextObj, command: tuple[str]) -> None:
@click.command()
@auth_command
async def init(ctx_obj: ContextObj) -> None:
- """Initialize local storage and register a fresh profile."""
+ """Create a local identity and register it with the configured Authsome server."""
home = get_authsome_config().home
RuntimeIdentity.ensure_local(home)
diff --git a/src/authsome/cli/main.py b/src/authsome/cli/main.py
index 6e95b9b5..19f558c3 100644
--- a/src/authsome/cli/main.py
+++ b/src/authsome/cli/main.py
@@ -25,9 +25,10 @@
@common_options
@click.pass_context
def cli(ctx: click.Context, verbose: bool, log_file: str) -> None:
- """Authsome: Portable local authentication library for AI agents and tools.
+ """Authsome: Credential broker for AI agents and tools.
- Securely manage credentials and API keys for third-party providers from your terminal.
+ Uses hosted Authsome by default. Set AUTHSOME_BASE_URL to use a local daemon
+ or self-hosted Authsome server.
"""
resolved = Path(log_file) if log_file else None
setup_logging(verbose=verbose, log_file=resolved)
diff --git a/src/authsome/config.py b/src/authsome/config.py
index c5bb3997..3000cd7f 100644
--- a/src/authsome/config.py
+++ b/src/authsome/config.py
@@ -7,6 +7,8 @@
from authsome import __version__
+DEFAULT_BASE_URL = "https://api.authsome.ai"
+
class AuthsomeConfig(BaseSettings):
"""Shared Authsome configuration resolved from environment variables."""
@@ -15,7 +17,7 @@ class AuthsomeConfig(BaseSettings):
version: str = __version__
home: Path = Field(default=Path.home() / ".authsome")
- base_url: str = Field(default="http://127.0.0.1:7998")
+ base_url: str = Field(default=DEFAULT_BASE_URL)
@property
def client_home(self) -> Path:
diff --git a/src/authsome/server/config.py b/src/authsome/server/config.py
index 746aa9b8..2e1d0322 100644
--- a/src/authsome/server/config.py
+++ b/src/authsome/server/config.py
@@ -14,6 +14,7 @@ class ServerConfig(AuthsomeConfig):
# Network
host: str = "127.0.0.1"
port: int = 7998
+ callback_base_url: str | None = None
# Store
database_url: str | None = Field(default=None, validation_alias="DATABASE_URL")
diff --git a/src/authsome/server/urls.py b/src/authsome/server/urls.py
index a9786188..3a194a59 100644
--- a/src/authsome/server/urls.py
+++ b/src/authsome/server/urls.py
@@ -6,15 +6,17 @@
# Invariant: must match the OAuth callback route declared in routes/auth.py.
DEFAULT_CALLBACK_PATH = "/api/auth/callback/oauth"
+DEFAULT_LOCAL_SERVER_BASE_URL = "http://127.0.0.1:7998"
def build_server_base_url() -> str:
"""Return the canonical external base URL for the daemon."""
- return get_server_config().base_url
+ config = get_server_config()
+ return config.callback_base_url or DEFAULT_LOCAL_SERVER_BASE_URL
def _base_url(base_url: str | None = None) -> str:
- return (base_url or get_server_config().base_url).rstrip("/")
+ return (base_url or build_server_base_url()).rstrip("/")
def build_callback_url(base_url: str | None = None) -> str: