Skip to content

Configuration & environment

All configuration is environment-driven and loaded from <repo>/.env by every entrypoint via shared/loadenv.js (real env / PM2 env win over the file). Secret values resolve through the secret provider; the variables below are non-secret settings and pointers. Every variable has a sensible default — an unset install still runs.

Assistant identity

Variable Default What
ASSISTANT_NAME the assistant Name used in prompts, channel-awareness, and the Discord voice wake word. Never hardcoded in strings.

Identity precedence vs per-engine harness memory

Two layers write a persona into every session, and they load in a fixed order.

The per-engine harness memory file loads first, as the base layer. Each engine spawns a CLI that reads its own memory file from disk before asmltr's prompt is applied: CLAUDE.md for the claude engine, AGENTS.md for codex, GEMINI.md for gemini, each at both project and user scope. The claude engine loads all filesystem settings by default (core/src/engines/claude.js never sets settingSources), so ~/.claude/CLAUDE.md reaches the session even when the working directory points at a project.

asmltr's identity plane loads second, on top. shared/identity.js builds the identity block (ASSISTANT_NAME plus ~/.asmltr/identity.md, editable from the Self view) and the core appends it through the system prompt after the CLI has already read its harness file.

asmltr does not currently remove or override the harness file. So a harness file that names a different assistant sits under asmltr's identity and contradicts it, which is the cross-agent drift the identity plane exists to prevent. shared/identity.js opens by requiring identity be "DECLARED, never inferred from ambiguous context" and calls the plane "the structural fix for cross-agent drift". When the two disagree there are two answers to "who am I" and no code reconciles them.

Which file to edit for what:

For Edit
The asmltr assistant persona ~/.asmltr/identity.md (or the Self view), plus ASSISTANT_NAME
The claude engine's harness memory CLAUDE.md (project) / ~/.claude/CLAUDE.md (user)
The codex harness memory AGENTS.md (project + user)
The gemini harness memory GEMINI.md (project + user)

Keep the harness files free of a second assistant identity, or keep whatever they assert consistent with ASSISTANT_NAME. ASMLTR_SESSION_CWD sets the working directory a session spawns in, which is what selects the CLAUDE.md hierarchy the claude engine reads (see Core runtime).

Before the #43 fix, only the claude engine received asmltr's identity & trust block; codex and gemini dropped it, so the harness file was the only persona in play on those two. With #43 fixed, the block reaches all three engines, so this precedence question applies to all three.

Two larger options are open and not done here: detect a conflicting harness file on session build and surface it in the Self view, and have asmltr own a delimited block inside each engine's harness file so one identity renders across all three. Documenting the precedence is the piece worth having regardless of which follows.

Ports & inter-service URLs

All services bind 127.0.0.1. Front anything public with a reverse proxy.

Variable Default What
ASMLTR_CORE_PORT 3023 core HTTP port
ASMLTR_MANAGER_PORT 3024 connector manager HTTP port
ASMLTR_INSIGHTS_PORT 3017 collector HTTP + socket.io port
ASMLTR_CORE_URL http://127.0.0.1:3023/v2/handle where connectors POST envelopes
ASMLTR_COLLECTOR_URL http://127.0.0.1:3017/ingest where producers POST events
ASMLTR_CORE_BASE http://127.0.0.1:3023 core base (collector → /v2/title; CLI)
ASMLTR_COLLECTOR_BASE http://127.0.0.1:3017 collector base (CLI / claude tailer)
ASMLTR_MANAGER_BASE http://127.0.0.1:3024 manager base (CLI)
ASMLTR_MANAGER_URL http://127.0.0.1:3024 manager base (core's operator-inject /send delivery)

Access tokens

Set these before exposing any service beyond localhost. When unset, the service warns at boot and runs open (dev mode).

Variable Default What
ASMLTR_MANAGER_TOKEN Bearer token gating the manager API
ASMLTR_INSIGHTS_TOKEN Bearer token gating collector read + /ingest
ASMLTR_INSIGHTS_CONTROL_TOKEN Stronger bearer for the collector control plane (/api/control/*)

Core runtime

Variable Default What
ASMLTR_CORE_CONCURRENCY 6 Max concurrent turns (global semaphore; turns on one conversation_key are also serialized)
ASMLTR_CORE_REQUEST_TIMEOUT_MS 0 (unlimited) HTTP request timeout for /v2/handle (agent turns can run minutes)
ASMLTR_SESSION_CWD os.homedir() Spawn/resume working dir for sessions (which CLAUDE.md hierarchy loads)
ASMLTR_MAX_THINKING_TOKENS 4000 Max thinking tokens per turn (0 disables; adaptive — trivial turns don't think)
ASMLTR_SELF_AWARE on (set off to disable) Inject the "asmltr toolbelt" awareness (cross-session asmltr CLI ops) into the system prompt
ASMLTR_CLAUDE_BIN auto-detected Full path to the claude binary (used by asmltr claude)
ASMLTR_RAW_BODY_LIMIT 1024mb Ceiling for a raw (non-JSON) request body on the file routes. The base64-in-JSON shape stays bounded by the 10mb JSON parser instead, roughly 7.5 MiB of file

ASMLTR_SESSION_CWD also decides which CLAUDE.md the claude engine picks up as harness memory, which loads under asmltr's own identity block; see Identity precedence vs per-engine harness memory.

Session titles

Variable Default What
ASMLTR_TITLE_MODEL haiku Cheap model for the no-tools title-generation call (rides the subscription)
ASMLTR_TITLE_REFRESH_TURNS 15 Regenerate a session's title every N inbound turns

Moderation

The classifier resolves its key by name through the secret provider (never ANTHROPIC_API_KEY). See Secrets & configuration.

Variable Default What
ASMLTR_MODERATION_PROVIDER openai openai or anthropic
ASMLTR_MODERATION_MODEL gpt-5-nano (openai) / claude-haiku-4-5-20251001 (anthropic) Classifier model
ASMLTR_MODERATION_KEY openai_api_key / anthropic_api_key Secret key name for the classifier
ASMLTR_MOD_LOG_DIR core/data/moderation-logs Where moderation decisions are logged

Admin / security alerts

Fired on moderation errors and high-risk blocks. Configure any of these (each set one fires); leave all unset to disable.

Variable What
ASMLTR_ADMIN_ALERT_SEND Route through a connector: JSON {"channel":"discord","target":"<id>"}, or shorthand telegram / discord\|<channelId>
ASMLTR_ADMIN_ALERT_CMD Shell command ({msg} = alert text) — good for email/webhooks/custom scripts

Secret provider

See Secrets & configuration for how these compose.

Variable What
ASMLTR_SECRETS_FILE Path to a JSON { key: value } secrets file
ASMLTR_SECRET_CMD Shell template run per key ({key} substituted); stdout is the value
ASMLTR_ENV_FILE Override the .env path loaded by shared/loadenv.js

Data locations

Portable defaults; override to relocate the SQLite stores and workspaces.

Variable Default What
ASMLTR_CORE_DB core/data/asmltr-core.db Sessions store
ASMLTR_TRUST_DB core/data/trust.db Trust store (principals/identifiers/roles/grants)
ASMLTR_TRUST_SEED core/src/trust/seed.json Trust seed file
ASMLTR_INSIGHTS_DB insights/collector/data/insights.db Collector telemetry store
ASMLTR_CONNECTORS_DB connectors/manager/data/connectors.db Connector instance registry
ASMLTR_MCP_CLIENTS_FILE connectors/types/mcp/clients.json MCP OAuth clients
ASMLTR_GITHUB_WORKSPACE ~/.asmltr/github-repos GitHub connector clone workspace

Collector sampling & tailer

Variable Default What
ASMLTR_RECONCILE_MS 15000 Session reconciliation interval
ASMLTR_SAMPLE_MS 30000 System metric sampling interval
ASMLTR_TAIL_MS 5000 JSONL log tail interval
ASMLTR_ENABLE_TAILER on (set 0 to disable) Ingest events from legacy JSONL proxy logs
ASMLTR_TAILER_BACKFILL off (set 1 to enable) Read historical JSONL on start (else tail only new lines)
ASMLTR_TRACKER_PATH Host hook session tracker (screen-based, one identity)
ASMLTR_TRACKER_IDENTITY cli Identity for the host hook tracker
ASMLTR_CLI_TRACKER_PATH ~/.asmltr/cli-sessions.json asmltr claude session tracker
ASMLTR_CLI_IDENTITY OS username Identity used by the CLI / claude tailer
ASMLTR_MULTIPLEXER screen Multiplexer for interactive asmltr claude sessions; set tmux to opt into tmux. screen keeps native mouse-wheel scrollback; tmux needs copy-mode
ASMLTR_QUERY_LOG_DIR Optional legacy query-log dir the tailer reads
ASMLTR_MOD_LOG_DIR_SRC Optional legacy moderation-log dir the tailer reads

MCP connector (only when running the mcp type)

Variable Default What
BASE_URL https://mcp.example.com Public issuer URL for OAuth metadata
TOKEN_EXPIRY_HOURS 720 OAuth token lifetime

Per-connector config

Beyond the global env vars, each connector instance has its own config, validated against that type's meta.configSchema. Discover every type's schema live:

curl -s 127.0.0.1:3024/types | jq '.types[] | {type, configSchema, outbound}'

or read connectors/types/<type>/index.js. Highlights (defaults shown):

Type Key config fields
discord bot_token_bws_key (required), http_port (3016), dm_allowed_user_id, channels_default, voice_id, elevenlabs_key_name, autonomous-response limits
telegram bot_token_bws_key (required), allowed_chat_ids, http_port (3008), photo_dir
mcp port (3018), bind_host (127.0.0.1), base_url
github repos + pat_bws_key (required), mention (*<assistant-name>), poll_interval_ms, clone_repos, stream, dry_run (default true)
openai port (3025), bind_host (127.0.0.1), model_name (asmltr), keys_file, require_key (true)

Config that carries secrets is stored as a secret key name (e.g. bot_token_bws_key, pat_bws_key), never the token itself — see Secrets & configuration.