There is no Batman without Alfred.
Alfred is a general-purpose AI agent — a co-conspirator, not a butler. He reasons, acts, remembers, and can extend his own capabilities. Talk to him via Telegram, the web UI, or the terminal. Give him a task; he figures out how to do it.
Alfred remains general-purpose, while the product roadmap is game-development first, with dedicated Game Development and Game Testing modes planned over the same core runtime. See the roadmap.
The npm package is still private while its public name and license are being
decided. Once published, people who want to use Alfred will install the npm
package and keep all personal state under ~/.alfred:
alfred setup
alfred doctor
alfred start
alfred tuialfred setup creates private configuration, identity, workspace, logs, and
extension directories under ~/.alfred. It asks how Alfred should work with
you and whether host access should be limited, approval-based, or trusted.
Existing files are preserved on every rerun. API keys are never requested
through visible terminal input; setup tells you which key to add to the
mode-0600 configuration file, or directs Codex users through
alfred auth login openai.
People who want to change Alfred itself should clone this repository and use pnpm. The two paths, provider setup, first conversation, background service, updates, and extensions are covered in the getting-started guide.
Npm-installed Alfred instances expand through digest-approved user-space extensions rather than editing the replaceable package. See the extension trust model and commands.
On macOS, alfred service install creates and starts a neutral per-user
LaunchAgent. Use alfred service status, alfred service restart, and
alfred service uninstall to manage it; uninstalling preserves ALFRED_HOME.
- General-purpose ReAct agent — research, writing, lead generation, ops, file work, shell commands
- Multi-provider LLM — Gemini, Anthropic, OpenAI, Ollama, LM Studio, OpenRouter, and Codex subscription auth through the supervised Codex App Server; OpenRouter deployments can explicitly tune supported models' reasoning effort or token budget
- Pinchtab-first read-only browsing —
web_fetchand lead extraction prefer healthy Pinchtab, with supervised startup and lazy Playwright fallback - Interactive browser control — Alfred can drive a persistent Playwright session: navigate, click, type, fill forms, and take screenshots
- Remote agent orchestration — monitors and dispatches tasks to coding agents (Claude, Codex, Pi, …) running in Herdr workspaces
- Decoupled agent event webhook — external agents/terminal wrappers push lifecycle events (
needs_approval,completed,failed,progress) to Alfred, which routes them to Telegram - Telegram + Web + TUI — continue the same conversation from your phone, browser, or terminal; the gateway owns history and execution
- Tiered persistent memory — context card, per-day session logs, group chat logs, and QMD semantic recall across sessions
- Self-extending — source checkouts can change core tools; packaged installs can create reviewable, digest-approved user-space extensions that survive updates
- Credential-safe by default — tool output and run telemetry are scrubbed of API keys and high-entropy secrets before they enter LLM context or logs
- Grounded action reporting — claims that Alfred searched, fetched, read, wrote, ran, tested, or browsed require a matching successful current-run tool receipt
- Tool ecosystem — 30+ tools: search, web fetch, file ops, shell exec, process management, lead pipeline, writer, browser control, Herdr, memory (full catalog below)
- Personality - Alfred's personality is meant to be a first principle's thinker, but not one who will overthink.
- Ownership - Packaged onboarding creates private identity and instructions; source-install users should review the generic
SOUL.mdtemplate before running Alfred. - Features - Alfred is substantially built out (browser control, agent events, persistent memory, remote agent orchestration), but he's still evolving — new capabilities land regularly and behaviour may shift between releases.
- Conversation history is injected once as ordinary messages, with the current request exactly once and last. This removes duplicated summary/window branches that could pull weaker models back toward stale turns.
- OpenRouter reasoning is configurable per deployment, reasoning-token usage is tracked, Alfred forwards a stable session ID, and bounded upstream routing metadata is recorded for diagnosis.
- Pinchtab is now the preferred backend for read-only browsing. Playwright is created only as an enabled fallback; Pinchtab startup failures are visible and supervised.
- Final replies are checked against the current run's successful tool ledger. An unsupported action claim is withheld and repaired once; a repeated claim becomes an explicit correction.
With the gateway running, launch alfred tui for a package install or
pnpm alfred tui in a source checkout. Select an existing
conversation—including a Telegram conversation—to continue with the same context.
Use pnpm alfred tui --session ID to attach directly, or --url https://HOST for
a remote gateway. Local authentication uses ALFRED_API_KEY or the workspace's
api-key file; remote connections require ALFRED_API_KEY.
Enter sends, Ctrl-J inserts a newline, Ctrl-P opens conversations, Ctrl-T expands
tool receipts, PgUp/PgDn scroll, Ctrl-L loads older history, Ctrl-X cancels active work, and Ctrl-Q detaches
without stopping Alfred. /newsession [name] creates a separate conversation;
/model, /reasoning, /usage, and /status use shared session controls.
Codex assistant text streams during the turn; other runtimes currently publish at completion. Reconnect uses a durable change cursor and resynchronizes from a snapshot when necessary. Queued turns acknowledge immediately, execute in order, and deduplicate retries. Alfred can retrieve older turns across all surfaces.
/attach-channel telegram:CHAT_ID attaches a known Telegram chat to the selected
conversation. /link-telegram USER_ID explicitly links an allowlisted account
to the API owner for task access within shared conversations. Attachment alone
does not link identities or redirect existing notifications.
Restart the gateway after updating. See the brief for the continuity contract and remaining provider/restart limitations.
Alfred auto-discovers tools from src/tools/definitions/ — each *.tool.ts file exports one tool. Everything below is enabled for the main agent.
| Tool | What it does |
|---|---|
| Memory & knowledge | |
rag_memory_query |
Semantic search of the long-term knowledge base (QMD) over past sessions, links, and decisions |
log_session |
Writes a summary of the current session to knowledge/sessions/ for future recall |
save_link |
Persists a bookmark/summary/note to the knowledge base, updates INDEX.md, re-indexes QMD |
fetch_tweet |
Fetches a tweet via the Twitter API (TWITTER_BEARER_TOKEN) |
| Search & web | |
search |
Web search via SearXNG (primary), with Bright Data and Brave fallbacks |
web_fetch |
One-shot page extraction via healthy Pinchtab first, with lazy Playwright fallback when enabled |
pinchtab_fetch / pinchtab_search |
Direct JS-rendered fetch and search through Pinchtab |
search_status / recover_search / run_diagnostics |
Search health checks and recovery |
| Browser control (persistent session) | |
browser_navigate |
Open a URL; returns page text + numbered interactive elements |
browser_snapshot |
Re-read the current page state (elements re-numbered after each change) |
browser_click |
Click an element by snapshot index or text label |
browser_type |
Type into an input (optionally press Enter) |
browser_nav |
History (back/forward/reload) and key presses (Enter, Escape, Tab, …) |
browser_screenshot |
Save a PNG of the current page (or full-page) to the workspace |
browser_tabs |
List, open, activate, and close tabs |
browser_close |
Release the session browser when interaction is done |
| Writing | |
writer_agent |
Delegated drafting — blog posts, memos, emails, outlines, notes |
| Ops & self-development | |
code_discover |
Pattern-aware code search of the repo |
file_list / file_read / file_write / file_edit |
Workspace file operations (path-safe, project-rooted) |
extension_write |
Create or update a disabled user-space extension for explicit human review and digest approval |
shell_exec |
Project-rooted shell commands (disabled, exact-action approval, or direct according to access mode) |
process_list / process_stop |
Process inspection and termination |
doc_qa |
Answers questions from local docs/files with citations |
lead_extractor / lead_generation |
Lead pipeline (extract, score, persist) |
herdr_control |
Inspect/monitor/dispatch tasks to coding agents in Herdr workspaces (see docs/features/herdr_control.md) |
| Autonomous scheduling | |
schedule_reminder |
Deliver a durable reminder to the originating Telegram or web channel |
schedule_wake |
Start a bounded autonomous Alfred turn at a later time |
schedule_watch |
Watch a run, safe relative file path, or Herdr agent for a meaningful transition |
list_scheduled_tasks / cancel_scheduled_task |
Inspect or cancel the current user's scheduled tasks |
All configuration uses environment variables documented in .env.example.
Package installs store them in the private
ALFRED_HOME/config/config.env; source checkouts may create a repository-local
.env from the template:
cp .env.example .envExisting source installs can preview a non-destructive move into private
ALFRED_HOME storage with pnpm alfred migrate home. See the
migration guide; do not add
--apply until the reported paths are correct.
| Variable | Default | Purpose |
|---|---|---|
ALFRED_LLM_PROVIDER |
openai |
openai | anthropic | gemini | ollama | lmstudio | openrouter | codex (Codex App Server) |
OPENAI_API_KEY |
— | OpenAI |
ANTHROPIC_API_KEY |
— | Anthropic |
GEMINI_API_KEY |
— | Google Gemini (Google's naming convention) |
OPENROUTER_API_KEY |
— | OpenRouter (one key, many models) |
OPENROUTER_BASE_URL |
https://openrouter.ai/api |
OpenRouter API root — the code appends /v1/chat/completions, so do not set the /api/v1 form |
OPENROUTER_REASONING_ENABLED |
auto |
Preserve the model default, or explicitly set true / false |
OPENROUTER_REASONING_EFFORT |
— | Optional none / minimal / low / medium / high / xhigh / max effort for supporting models |
OPENROUTER_REASONING_MAX_TOKENS |
— | Optional positive reasoning-token budget; mutually exclusive with effort |
OPENROUTER_REASONING_EXCLUDE |
false |
Request that reasoning content be excluded from the response |
OLLAMA_BASE_URL |
http://localhost:11434 |
Local Ollama (OpenAI-compatible) |
LMSTUDIO_BASE_URL |
http://localhost:1234 |
Local LM Studio (OpenAI-compatible) |
ALFRED_MODEL_SMART |
gpt-4o |
Main agent loop; Codex validates it against the live catalog and reports any fallback |
ALFRED_MODEL_FAST |
gpt-4o-mini |
Cheap/fast calls for API-key providers |
For OpenRouter, use model slugs exactly as OpenRouter lists them (e.g. anthropic/claude-sonnet-4-20250514, openai/gpt-4o). If reasoning is configured, Alfred asks OpenRouter to route only to endpoints that accept the requested parameters; unsupported model/provider combinations therefore fail clearly instead of silently ignoring the setting. Effort and token budget cannot both be set. With Ollama/LM Studio use the model id the local server reports (e.g. gemma-4-31b-it-qat). pnpm probe:model helps discover locally served models.
Set ALFRED_LLM_PROVIDER=codex and install the Codex CLI so codex app-server --stdio is available. Sign in through the App Server-owned account flow:
pnpm alfred auth login openai
pnpm alfred auth login openai --device-code # remote/headless host
pnpm alfred auth status openai
pnpm alfred auth logout openaipnpm codex:login, pnpm codex:status, and pnpm codex:logout remain compatibility aliases. Alfred does not read or persist ChatGPT tokens; Codex owns credentials and refresh. The web UI exposes the same status, login, model catalog, and account quota under Settings → Models & Accounts. Account quota/reset data is separate from per-run Alfred usage. Codex turns use ephemeral App Server threads, inject only Alfred's durable session context, and execute external effects only through Alfred's dynamic tool registry and policy envelope. Built-in Codex shell, filesystem, patch, browser, network, and MCP capabilities are disabled/rejected by the runtime boundary.
The Settings panel labels the configured provider as Active and a connected ChatGPT subscription as Standby when another provider is selected. Standby means an explicitly selectable alternative, not automatic failover: Alfred never changes LLM providers on its own.
By default, the App Server uses the same Codex credential home as the Codex CLI. To keep Alfred on a separate ChatGPT account, give its process a dedicated absolute CODEX_HOME, add cli_auth_credentials_store = "file" to that directory's config.toml, restart Alfred, and sign in from Alfred's Web UI. See docs/operations/chatgpt_subscription.md for the isolated-profile setup.
Terminal login prints the browser authorization URL or device-code verification URL and one-time code, then keeps the App Server process open until account/login/completed. Use --timeout-ms <ms> to change the ten-minute timeout; Ctrl-C sends account/login/cancel before the client closes. The Web UI opens browser login automatically, polls completion, and provides cancellation; use device code there for a remote host. Neither path prints access or refresh tokens.
In both Telegram and the Web UI, these commands are handled by ChatService and are not sent to a model or written to conversation history:
/model list six live picker-visible models
/model page 2 show the next deterministic page
/model N choose the numbered model for this session
/model NAME choose an exact id/display name or unambiguous alias
/model default clear the session model override
/reasoning list efforts supported by the effective model
/reasoning N|NAME choose an effort for this session
/reasoning default use that model's default effort
/usage show App Server subscription quota and local Alfred tokens separately
/status show session, effective model/reasoning, and local token totals
/approve TOKEN approve one exact pending tool action for one retry
/reject TOKEN reject one exact pending tool action
The live App Server model/list response is authoritative. Numbering is only a shortcut for the currently displayed list, and ambiguous aliases are rejected. Model and reasoning overrides are session-scoped, persist across a normal Alfred restart, and start from the configured global defaults in a new session. A vanished model or unsupported saved effort is reported and falls back to the live/default catalog. Changing .env provider or model settings requires restarting Alfred.
| Variable | Default | Purpose |
|---|---|---|
PORT |
3000 |
HTTP gateway port |
ALFRED_ACCESS_MODE |
derived from ALFRED_ENV |
limited disables shell/process termination; approval requires /approve TOKEN for each exact action; trusted grants direct access with Alfred's OS permissions |
ALFRED_ENV |
dev |
Compatibility default only: dev maps to trusted and prod to approval when ALFRED_ACCESS_MODE is unset |
ALFRED_API_KEY |
auto-generated | Protects the web UI and all /v1/* routes; auto-generated on first start if unset |
ALFRED_AGENT_EVENT_TOKEN |
— | Shared secret for POST /api/events/agent; when unset the endpoint accepts loopback callers only |
TELEGRAM_BOT_TOKEN |
— | Enables the Telegram channel |
TELEGRAM_ALLOWED_USER_IDS |
— | Comma-separated numeric user IDs allowed to talk to the bot (fail-closed when empty) |
TELEGRAM_ALERT_CHAT_ID |
— | Chat ID for proactive agent-event pushes (approval gates, failures); leave blank to disable |
The scheduler is disabled by default. Set ALFRED_SCHEDULER_ENABLED=true to run it inside the existing gateway process:
ALFRED_SCHEDULER_ENABLED=true pnpm startInteractive turns can use these tools when the scheduler is enabled:
schedule_remindersends text to the originating channel once, or at a fixed-delay interval.schedule_wakestarts a bounded autonomous turn with a short instruction. The turn can inspect the explicitly available read-only probes and must finish with a scheduler completion or reschedule action.schedule_watchpollsrun_status,file_exists, orherdr_agentstate and notifies when a meaningful transition occurs. Agent lifecycle webhooks can nudge matching watches immediately.list_scheduled_tasksandcancel_scheduled_taskmanage tasks belonging to the current user and session.
Tasks, leases, task-cycle logs, and deterministic delivery ledgers are stored under workspace/alfred/scheduler/ (or under ALFRED_WORKSPACE_DIR/scheduler). The store is recovered on restart; expired work is reclaimed, and recurring tasks use fixed-delay scheduling from cycle completion so an outage does not create a catch-up storm. Notifications are delivered only to the originating web:<sessionId> or allowed telegram:<chatId> destination.
Scheduler-origin turns are deliberately constrained: they have a separate execution profile, a bounded duration and tool budget, no mutating tools, no direct messaging tools, no nested scheduling, and no interactive conversation-memory writes. The scheduler also enforces per-principal and global active-task quotas, a minimum 60-second interval, and a maximum cycle count.
The gateway exposes read/control endpoints for web integrations:
curl http://localhost:9001/v1/scheduler/status
curl 'http://localhost:9001/v1/scheduled-tasks?sessionId=<session-id>'
curl -X POST 'http://localhost:9001/v1/scheduled-tasks/<task-id>/cancel?sessionId=<session-id>'GET /v1/scheduler/status reports whether the engine is running, its concurrency, tick timing, and task counts. The scheduler remains opt-in so existing Alfred deployments continue to behave as interactive-only agents.
| Variable | Default | Purpose |
|---|---|---|
SEARXNG_BASE_URL / SEARXNG_SEARCH_PATH / SEARXNG_HEALTH_PATH |
http://127.0.0.1:8888 / /search / /search?q=ping&format=json |
Primary search provider |
SEARXNG_START_CMD |
— | Command to auto-start SearXNG with Alfred (blank = run it yourself/Docker) |
SEARXNG_START_TIMEOUT_MS / SEARXNG_RETRY_INTERVAL_MS / SEARXNG_HEALTH_RETRIES / SEARXNG_HEALTH_RETRY_DELAY_MS / SEARXNG_HEALTH_GRACE_MS |
15000 / 1000 / 2 / 250 / 15000 | Startup & health-check tuning |
BRIGHTDATA_SEARCH_API_KEY + BRIGHTDATA_SEARCH_* |
— | Bright Data search fallback (zone, engine, country, timeouts) |
BRAVE_SEARCH_API_KEY |
— | Brave search fallback |
ALFRED_SEARCH_MAX_RESULTS |
15 |
Max results per search |
| Variable | Default | Purpose |
|---|---|---|
ALFRED_ENABLE_PLAYWRIGHT |
true |
Enables persistent interactive browser tools and fallback for Pinchtab-first read-only browsing |
ALFRED_BROWSE_CONCURRENCY |
3 |
Parallel pages per web_fetch |
ALFRED_ENABLE_PINCHTAB |
false |
Enable Pinchtab as the preferred read-only browser and expose its direct tools |
PINCHTAB_BASE_URL / PINCHTAB_START_CMD |
http://127.0.0.1:9867 / — |
Pinchtab endpoint and optional supervised startup command; it need not share SearXNG's container |
| Variable | Default | Purpose |
|---|---|---|
ALFRED_WORKSPACE_DIR |
./workspace/alfred |
Where Alfred stores sessions, runs, knowledge, groups, browser screenshots, and agent-event logs |
ALFRED_HOME |
unset during compatibility phase | Opt into private state rooted at this directory; when set, the default workspace becomes ALFRED_HOME/workspace |
ALFRED_PROJECT_ROOT |
current launch directory | Directory deliberately exposed to Alfred's project-oriented file and shell tools |
ALFRED_CONCURRENCY |
2 |
Concurrent runs |
ALFRED_RUN_MAX_STEPS |
6 |
Steps per run |
ALFRED_AGENT_MAX_DURATION_MS |
600000 |
Hard deadline per run |
ALFRED_AGENT_MAX_TOOL_CALLS |
18 |
Tool-call budget per run |
ALFRED_AGENT_MAX_PARALLEL_TOOLS |
3 |
Parallel tool calls |
ALFRED_SCHEDULER_ENABLED |
false |
Enable autonomous reminders, wake turns, and watches |
ALFRED_SCHEDULER_TICK_MAX_MS |
15000 |
Maximum scheduler recovery/tick interval |
ALFRED_SCHEDULER_MAX_CONCURRENCY |
1 |
Concurrent scheduler cycles (hard capped at 2) |
ALFRED_SCHEDULER_GLOBAL_WAKE_INTERVAL_MS |
30000 |
Minimum interval between autonomous LLM wake starts |
ALFRED_FAST_SCRAPE_COUNT |
10 |
Fast-scrape page budget |
TWITTER_BEARER_TOKEN |
— | Twitter API (for fetch_tweet) |
For the product-install flow, start with the getting-started guide. The steps below are for people working on Alfred's core repository.
- Node.js 22+
pnpm- SearXNG instance (for search — self-host or use a public instance), or Bright Data / Brave keys as fallback
- At least one LLM API key (Anthropic, Google Gemini, OpenAI, or OpenRouter), or a Codex CLI/App Server subscription login
git clone https://github.com/Bingeljell/AlfredAI.git
cd AlfredAI
pnpm install
pnpm setup:browsers # optional: installs Chromium for browser control / web_fetchcp .env.example .envEdit .env — minimum required:
# LLM — set at least one
ALFRED_LLM_PROVIDER=gemini
GEMINI_API_KEY=
# or: ALFRED_LLM_PROVIDER=openrouter + OPENROUTER_API_KEY=
# Server
PORT=9001
# Search
SEARXNG_BASE_URL=http://localhost:8080
# Telegram (optional but recommended)
TELEGRAM_BOT_TOKEN=
TELEGRAM_ALLOWED_USER_IDS=
For OpenRouter specifically:
ALFRED_LLM_PROVIDER=openrouter
OPENROUTER_API_KEY=sk-or-...
ALFRED_MODEL_SMART=anthropic/claude-sonnet-4-20250514
ALFRED_MODEL_FAST=openai/gpt-4o-mini
# Optional: use one supported reasoning control (effort OR token budget)
OPENROUTER_REASONING_ENABLED=true
OPENROUTER_REASONING_EFFORT=high
OPENROUTER_REASONING_EXCLUDE=true
pnpm run build
pnpm startOpen http://localhost:9001/ui — create a session and start talking to Alfred.
For development (auto-rebuild on save):
pnpm run dev:gatewayAlfred's memory is tiered:
- Context card —
workspace/alfred/knowledge/context-card.md, injected at the top of every run. - Session logs — written via
log_sessiontoworkspace/alfred/knowledge/sessions/YYYY-MM-DD.md. - Saved knowledge — links/summaries/notes via
save_linkunderworkspace/alfred/knowledge/links/. - Group chat logs — daily JSONL per channel group under
workspace/alfred/groups/. - Run logs — raw run telemetry under
workspace/alfred/runs/.
The rag_memory_query tool provides semantic recall over tiers 1–3 using QMD. Without QMD, Alfred still works fully — it just won't have long-term recall.
To enable:
npm install -g @tobilu/qmd
# Index Alfred's workspace knowledge
qmd collection add ./workspace/alfred/knowledge --name alfred-knowledge
qmd embedRe-run qmd embed periodically (or after significant sessions) to keep the index fresh. log_session and save_link trigger re-indexing automatically when QMD is available.
Alfred has two explicit browser paths:
- Read-only extraction (
web_fetch, lead tools) prefers healthy Pinchtab. If Pinchtab is down or returns only failures, Alfred falls back to Playwright whenALFRED_ENABLE_PLAYWRIGHT=trueand reports the backend/fallback reason. - Interactive work uses one persistent Playwright Chromium session per chat, so Alfred can navigate → snapshot (numbered interactive elements) → click/type → re-snapshot → screenshot.
Pinchtab and SearXNG are independent services. They can run on the host or in separate containers as long as Alfred can reach PINCHTAB_BASE_URL and SEARXNG_BASE_URL.
Typical flow:
browser_navigate— open a URL, get text + elements[0],[1],[2], …browser_type— fill a search box by index ({"index": 1, "value": "…", "pressEnter": true})browser_snapshot— see the result before deciding the next stepbrowser_click— click a result or button ({"index": 3})browser_screenshot— capture a PNG (saved toworkspace/alfred/browser/screenshots/)browser_close— release the session when done
Prefer browser_* whenever the task needs interaction (forms, logins, site search, click-through); use web_fetch for one-shot read-only extraction.
External agents and terminal wrappers (Herdr hooks, tmux/Zellij wrappers, standalone agent hooks) can push lifecycle events to Alfred over HTTP, so Alfred reacts instantly instead of polling. See docs/architecture/agent_event_webhook_spec.md for the full contract.
Endpoint: POST /api/events/agent
curl -X POST http://localhost:9001/api/events/agent \
-H "Content-Type: application/json" \
-H "X-Agent-Event-Token: $ALFRED_AGENT_EVENT_TOKEN" \
-d '{
"version": "1.0",
"source": "herdr",
"agentKind": "pi",
"workspaceId": "w9",
"paneId": "p2",
"eventType": "needs_approval",
"timestamp": 1755271200000,
"payload": {
"promptText": "Allow command: git push origin main [y/n]?",
"suggestedAction": "confirm",
"cwd": "/Users/yourname/projects/AlfredAI",
"details": "git push origin main"
}
}'Event types
eventType |
Alfred's action |
|---|---|
needs_approval |
Push an actionable Telegram alert with /approve w9:p2 / /reject w9:p2 hints |
completed |
Record; push to Telegram only when payload.ping is true |
failed |
Push an error alert (includes error + exit code) |
progress |
Record only (optional milestone) |
Auth: requests must present X-Agent-Event-Token matching ALFRED_AGENT_EVENT_TOKEN. When no token is configured, only loopback callers (127.0.0.1 / ::1) are accepted.
Dispatch: needs_approval/failed/pinged completed events are pushed to TELEGRAM_ALERT_CHAT_ID (console fallback if Telegram is not configured). Every event is appended to a JSONL job log under workspace/alfred/agent-events/YYYY/MM/YYYY-MM-DD.jsonl.
herdr_control lets Alfred act as a remote command centre for coding agents (Claude, Codex, Pi, …) running in Herdr workspaces — listing workspaces/panes, capturing pane output, and dispatching prompts. Alfred talks to Herdr over its local JSON socket; no raw tmux parsing. See docs/features/herdr_control.md.
Before tool results enter LLM context (and before run telemetry/debug exports are persisted), Alfred runs them through a shared redaction pipeline (src/utils/redact.ts) that:
- Drops values whose JSON key names a secret (
api_key,token,password, …) - Drops strings that are whole known API keys (Anthropic/OpenAI/GitHub/Slack/AWS prefixes, JWTs)
- Drops high-entropy strings that look like keys, with safe-pattern exemptions
- Masks known key patterns embedded inline in prose or log lines
This unifies the former redact/scrubber pair into one implementation so LLM context, run telemetry, and debug exports are scrubbed identically. See docs/architecture/security-upgrade-2026-07.md.
To start Alfred automatically on login and keep it running, install the generated per-user LaunchAgent after setup:
alfred service install
alfred service status
alfred service restart
alfred service uninstallThe command validates and writes ~/Library/LaunchAgents/com.alfred.agent.plist,
uses modern launchctl user-domain operations, and stores output under
ALFRED_HOME/logs. Uninstalling the service does not delete configuration,
identity, conversations, extensions, or other files in ALFRED_HOME.
src/runtime/ — agent loop, system prompt, specialists config
src/runtime/operatingInstructions.ts — generic product-level operating contract
src/agentEvents/ — agent event webhook (schema, auth, dispatcher, Telegram notifier, event store)
src/tools/ — all tool definitions (drop a *.tool.ts here to add a tool)
src/tools/browser/ — Pinchtab-first read-only routing plus persistent Playwright interaction
src/tools/search/ — search providers (SearXNG, Bright Data, Brave)
src/provider/ — LLM adapters plus Codex App Server account/runtime integration
src/channels/ — Telegram + channel adapter interface
src/runner/ — ChatService, conversation window management
src/gateway/ — HTTP server, Web UI API, agent event endpoint
src/scheduler/ — durable task store, leases, delivery ledger, probes, and autonomous execution
src/memory/ — session memory, group chat store, RAG
src/utils/ — redaction (credential scrubbing), path safety
webui/ — Web UI
workspace/alfred/scheduler/ — persisted scheduler tasks, deliveries, and cycle logs
SOUL.md — Alfred's identity and values
AGENTS.md — developer-only codebase conventions; never injected at runtime
docs/ — architecture docs, spec, changelog, feature specs
pnpm run build # compile TypeScript
pnpm pack:check # build and verify the exact private npm tarball manifest
pnpm start # run compiled build
pnpm run dev:gateway # run with auto-rebuild
pnpm setup:browsers # install Playwright Chromium (interactive control and read-only fallback)
pnpm probe:model # probe a local LLM server for its model list
pnpm codex:app-server-gate # verify the installed Codex App Server capability boundary
pnpm run test # unit + integration + security
pnpm run test:unit
pnpm run test:integration
pnpm run test:smoke
pnpm run test:security
pnpm run lint:layers # eslint + architectural boundary checksdocs/spec.md— architecture and product blueprintdocs/roadmap.md— what's done, what's nextdocs/changelog.md— change historydocs/tool_contract.md— the single-agent tool contractdocs/features/herdr_control.md— Herdr remote orchestration feature specdocs/architecture/provider-and-grounding-reliability.md— Pinchtab routing, OpenRouter reasoning, and action-claim groundingdocs/architecture/— deep dives: security model, agent event webhook spec, Alfred's identity, turn lifecycle, refactor history
