{"_id":"@aaronqlf/alfred-agent","name":"@aaronqlf/alfred-agent","dist-tags":{"latest":"0.10.0"},"versions":{"0.10.0":{"name":"@aaronqlf/alfred-agent","version":"0.10.0","description":"Alfred — a provider-agnostic coding agent for your terminal (like Claude Code, for any model provider)","type":"module","bin":{"alfred":"dist/index.js"},"scripts":{"build":"tsc","dev":"tsx src/index.ts","typecheck":"tsc --noEmit","test":"tsx --test test/*.test.ts","smoke":"node scripts/smoke.mjs","prepare":"npm run build","prepublishOnly":"npm run typecheck && npm test && npm run build"},"keywords":["ai","agent","coding-agent","cli","llm","anthropic","openai","mcp","claude","developer-tools"],"author":{"name":"hguessous"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/AaronQLF/Alfredo.git"},"homepage":"https://github.com/AaronQLF/Alfredo#readme","bugs":{"url":"https://github.com/AaronQLF/Alfredo/issues"},"engines":{"node":">=18"},"dependencies":{"@anthropic-ai/sdk":"^0.104.1","@modelcontextprotocol/sdk":"^1.29.0","openai":"^6.42.0","tinyglobby":"^0.2.17"},"devDependencies":{"@types/node":"^25.9.3","tsx":"^4.22.4","typescript":"^6.0.3"},"gitHead":"bf10fc0a895e8603aad43c64386f81c88b3ffef4","_id":"@aaronqlf/alfred-agent@0.10.0","_nodeVersion":"25.9.0","_npmVersion":"11.12.1","dist":{"integrity":"sha512-4wRRt65Pg3WZFJ8cp7XlW2MBgl6BHGRQKup9rqXC2o0cpagFtxfp7fFzpic27CHdhHTa2qk51gzcC4Ipb5LciA==","shasum":"cb438f31e0d5ddf3a0ecd82802ffdbd7d8d2e300","tarball":"https://registry.npmjs.org/@aaronqlf/alfred-agent/-/alfred-agent-0.10.0.tgz","fileCount":37,"unpackedSize":299291,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDGNALI9XIRUZO0K4n8TfG4xiPnmeZZbHrv53aGEJuwXAIgW4SEo9rxRG3LqWJwOfB5jl4v2Abhx/872h65A9CT2g8="}]},"_npmUser":{"name":"aaronqlf","email":"guessous.haroun12@gmail.com"},"directories":{},"maintainers":[{"name":"aaronqlf","email":"guessous.haroun12@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/alfred-agent_0.10.0_1781534500052_0.1794188015144671"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-15T14:41:39.791Z","0.10.0":"2026-06-15T14:41:40.190Z","modified":"2026-06-15T14:41:40.471Z"},"maintainers":[{"name":"aaronqlf","email":"guessous.haroun12@gmail.com"}],"description":"Alfred — a provider-agnostic coding agent for your terminal (like Claude Code, for any model provider)","homepage":"https://github.com/AaronQLF/Alfredo#readme","keywords":["ai","agent","coding-agent","cli","llm","anthropic","openai","mcp","claude","developer-tools"],"repository":{"type":"git","url":"git+https://github.com/AaronQLF/Alfredo.git"},"author":{"name":"hguessous"},"bugs":{"url":"https://github.com/AaronQLF/Alfredo/issues"},"license":"MIT","readme":"# Alfred\n\n[![CI](https://github.com/AaronQLF/Alfredo/actions/workflows/ci.yml/badge.svg)](https://github.com/AaronQLF/Alfredo/actions/workflows/ci.yml)\n[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](./LICENSE)\n[![Node >=18](https://img.shields.io/badge/node-%3E%3D18-brightgreen.svg)](https://nodejs.org)\n\nA provider-agnostic coding agent for your terminal — like Claude Code, but you can point it at **any** model provider.\n\n```\nAlfred v0.6.0 · anthropic/claude-opus-4-8\ncwd: ~/projects/my-app · context: ALFRED.md · mcp: github (12 tools) · /help for commands\n\nanthropic/claude-opus-4-8 · ~18.4k/160k ctx\n❯ find where rate limiting is configured and raise the limit to 100 @config/limits.ts\n\n⏺ grep \"rateLimit\" in . (**/*.ts)\n  ...\n⏺ read_file config/limits.ts\n  ...\n⏺ edit_file config/limits.ts\n  - max: 20,\n  + max: 100,\n  allow edit_file? [y]es / [a]lways / [p] always for \"edit_file …\" / [n]o >\n```\n\n## Features\n\n**Provider-agnostic** — Anthropic via the official SDK (adaptive thinking, streaming, prompt caching, vision), and OpenAI, Google Gemini, OpenRouter, Groq, xAI, Mistral, DeepSeek, Together, Fireworks, Cerebras, Ollama, LM Studio, or any custom OpenAI-compatible endpoint through one adapter. Switch mid-conversation with `/model`.\n\n**Cross-model code review** — because Alfred isn't tied to one vendor, it can get a **second opinion** on its own work: after it edits files, hand the diff to a *different* model to red-team it. A single-vendor agent reviewing its own code inherits its own blind spots; an independent model from another family has uncorrelated failure modes and catches what the author can't see. `/review` reviews the changes since the last review and streams concrete findings (severity · file:line · fix); `reviewAuto: true` runs it silently after every editing turn and speaks up only when something's wrong. Set `reviewModel` to a different vendor than your main model for the most diversity. (Structurally impossible in a single-provider tool.)\n\n**Resilient** — transient provider failures (429/529/5xx, dropped streams, `ECONNRESET`) are retried with exponential backoff honoring `Retry-After`, covering mid-stream drops the SDKs don't — a single API hiccup no longer kills a turn.\n\n**Agentic** — a tool-using loop with:\n- **File tools** — `read_file` (line-numbered, paged; **reads images** as real pixels for vision-capable models, notes PDFs), `write_file`, `edit_file`, `multi_edit` (several atomic edits to one file), `list_dir`. Edits require reading the file first and are **rejected if it changed on disk** since, so the model never writes blind or stale.\n- **Search** — `grep` (regex) and `glob`, skipping `node_modules`/`.git`/build dirs.\n- **`bash`** — runs in its own process group; the **working directory persists between calls** (a `cd` sticks); `run_in_background:true` starts long-running processes (dev servers, watchers) that you poll with **`bash_output`** and stop with **`kill_shell`**. Ctrl+C and the 120s timeout kill the whole group.\n- **`web_fetch`** — URL → text — and **`web_search`** — ranked results (keyed Tavily/Brave, or a keyless DuckDuckGo fallback).\n- **`task` subagents** — delegate self-contained, context-heavy work to a subagent with isolated context; only its final report returns. Define **named agents** in `.alfred/agents/*.md` (own prompt, tool allowlist, model) and invoke with `subagent_type`.\n- **`todo_write`** — a visible, updating task list for multi-step work.\n\n**Security boundary** — file/search tools are **workspace-contained**: a path outside the working directory (or `--add-dir` roots) or one that looks like a secret (`.env`, `id_rsa`, `~/.aws`, `~/.ssh`, Alfred's own key file) forces an explicit prompt **even for read-only tools**, so an injected instruction can't silently exfiltrate credentials. A repo's own `.alfred/settings.json`/`.mcp.json` (permissions, hooks, MCP servers, provider URLs) is **not honored until you trust the directory once** — opening a hostile repo can't run its hooks.\n\n**Plan mode** — `/plan` (or `--plan`) puts Alfred in read-only mode: it investigates and proposes a concrete plan, you approve, then it implements. Nothing is modified before you sign off.\n\n**Reasoning** — the model's thinking streams to the terminal (dimmed; Anthropic adaptive + OpenAI-compatible reasoning models). `/effort low|medium|high` tunes depth/cost on models that support it (Anthropic `output_config.effort`, OpenAI `reasoning_effort`).\n\n**MCP** — connect [Model Context Protocol](https://modelcontextprotocol.io) servers over **stdio, streamable-HTTP, or SSE**, with **static-header or full OAuth** auth (browser flow, tokens cached under `~/.alfred/mcp-auth/`, refreshed automatically — so hosted servers like Linear/Notion/GitHub just work). Their **tools** appear as `mcp__<server>__<tool>`, **prompts** as `/mcp__<server>__<prompt>` slash commands, and **resources** are readable via `mcp_read_resource`.\n\n**Context & compaction** — **recency-preserving compaction** summarizes the older prefix and keeps recent turns verbatim; `/compact [focus]` accepts optional focus instructions, a `preCompact` hook can steer the summary, and an overflow auto-continues instead of losing your request.\n\n**Customizable behavior** — output styles (`/style concise|explanatory`, `--output-style`), full system-prompt control (`--system-prompt`/`--append-system-prompt`), and `/config` to inspect the effective configuration (secrets redacted).\n\n**Permissions** — read-only tools run freely; mutating tools show a diff/preview and prompt. Approve once, for the session (`a`), or — for `bash` — for **all commands with that prefix** (`p` → `bash(npm test *)`), with compound commands (`&&`, `;`, `|`, `$(…)`) always re-prompting. **Grants persist** to your global config, so you're not re-asked every session. A **`deny` list** blocks tools or command families outright (checked even under `--yolo`). `--yolo` skips prompts.\n\n**Hooks** — run shell commands on tool events (`preToolUse`/`postToolUse`) and session events (`userPromptSubmit`/`sessionStart`/`stop`); a `preToolUse` or `userPromptSubmit` hook that exits 2 blocks the action, and `userPromptSubmit`/`sessionStart` stdout is injected as context. Use for formatters, linters, guardrails, context injection.\n\n**Context & sessions** — conversations auto-save (`--continue`, `--resume <id>`, `/resume`); **recency-preserving compaction** summarizes the older prefix but keeps recent turns verbatim, and an overflow auto-continues instead of losing your request; `ALFRED.md`/`AGENTS.md`/`CLAUDE.md` load as project instructions, **walking up to the repo root** (monorepo-aware) with `@path` imports; `/init` generates one; `/cost` shows token usage **and an estimated dollar cost**; `/export [path]` writes the conversation to Markdown.\n\n**Input & UX** — `@path` attaches files and **images** (vision); **persistent input history** (↑ recalls across restarts); **tab completion** for slash commands and `@paths`; a status line (model · context %); streaming markdown, a spinner with elapsed time for long tool runs, Ctrl+C interrupts the turn (not the app); escape sequences in tool output are stripped so untrusted content can't spoof the terminal.\n\n**Customization** — model **aliases** (`opus`, `sonnet`, `haiku`, `fable`, …); custom slash commands from `.alfred/commands/*.md` (with `$ARGUMENTS`); a settings hierarchy where project `.alfred/settings.json` merges over the global `~/.alfred/config.json`; `/doctor` for an environment & provider health check.\n\n**Scriptable** — `alfred -p \"...\"` one-shot mode with stdin piping (`git diff | alfred -p \"review this\"`); **`--output-format json|stream-json`** emits a structured envelope (result, `session_id`, cost, usage) and per-event lines for embedding in pipelines; exits non-zero on failure for CI.\n\n## Setup\n\n```sh\nnpm install\nnpm run build\nnpm link        # optional: `alfred` on your PATH\n```\n\nSet the key for whichever provider you use:\n\n| Provider | Env var |\n|---|---|\n| `anthropic` | `ANTHROPIC_API_KEY` |\n| `openai` | `OPENAI_API_KEY` |\n| `google` | `GEMINI_API_KEY` |\n| `openrouter` | `OPENROUTER_API_KEY` |\n| `groq` / `xai` / `mistral` / `deepseek` | `GROQ_API_KEY` / `XAI_API_KEY` / `MISTRAL_API_KEY` / `DEEPSEEK_API_KEY` |\n| `together` / `fireworks` / `cerebras` | `TOGETHER_API_KEY` / `FIREWORKS_API_KEY` / `CEREBRAS_API_KEY` |\n| `ollama` / `lmstudio` | none (local) |\n\nOptional: `TAVILY_API_KEY` or `BRAVE_API_KEY` for higher-quality `web_search` (a keyless DuckDuckGo fallback works without them).\n\n## Usage\n\n```sh\nalfred                                   # default model\nalfred -m sonnet                         # model aliases: opus, sonnet, haiku, fable, …\nalfred -m openrouter/qwen/qwen3-coder\nalfred --continue                        # resume the latest session here\nalfred --add-dir ../shared-lib           # let file tools reach another directory\ngit diff | alfred -p \"review this change\"\nalfred -p \"summarize TODO.md\" --output-format json     # structured envelope for scripts\nalfred -r <session-id> -p \"now add tests\" --output-format json   # scripted multi-turn\n```\n\nModel resolves: `--model` → `ALFRED_MODEL` → `~/.alfred/config.json` → built-in, with aliases expanded first. Save a default with `/model sonnet --save`. Custom endpoint: set `ALFRED_<NAME>_BASE_URL` (+ `_API_KEY`) and use `-m <name>/<model>`.\n\n## Configuration\n\n`~/.alfred/config.json` (global) and `.alfred/settings.json` (project, merged over global):\n\n```json\n{\n  \"model\": \"openrouter/qwen/qwen3-coder\",\n  \"providers\": {\n    \"openrouter\": { \"baseUrl\": \"https://openrouter.ai/api/v1\", \"apiKey\": \"sk-or-...\", \"model\": \"qwen/qwen3-coder\" },\n    \"openai\":     { \"apiKey\": \"sk-...\", \"model\": \"gpt-5.2\" },\n    \"local\":      { \"baseUrl\": \"http://localhost:1234/v1\", \"model\": \"llama-3.3-70b\" }\n  },\n  \"modelAliases\": { \"fast\": \"anthropic/claude-haiku-4-5\" },\n  \"alwaysAllow\": [\"bash(npm test *)\", \"grep\"],\n  \"deny\": [\"bash(rm *)\", \"web_fetch\"],\n  \"shell\": \"/bin/bash\",\n  \"autoCompactTokens\": 160000,\n  \"effort\": \"high\",\n  \"outputStyle\": \"concise\",\n  \"theme\": \"dracula\",\n  \"subagentModel\": \"anthropic/claude-haiku-4-5\",\n  \"reviewModel\": \"openai/gpt-5.2\",\n  \"reviewAuto\": true,\n  \"search\": { \"provider\": \"tavily\", \"apiKey\": \"tvly-...\" },\n  \"mcpServers\": {\n    \"github\": { \"command\": \"npx\", \"args\": [\"-y\", \"@modelcontextprotocol/server-github\"] },\n    \"docs\":   { \"url\": \"https://example.com/mcp\", \"headers\": { \"Authorization\": \"Bearer ...\" } },\n    \"linear\": { \"url\": \"https://mcp.linear.app/mcp\", \"auth\": \"oauth\" },\n    \"legacy\":  { \"url\": \"https://example.com/sse\", \"transport\": \"sse\" }\n  },\n  \"hooks\": {\n    \"preToolUse\":       [{ \"tools\": [\"bash\"], \"command\": \"./scripts/guard.sh\" }],\n    \"postToolUse\":      [{ \"tools\": [\"write_file\", \"edit_file\"], \"command\": \"npm run format\" }],\n    \"userPromptSubmit\": [{ \"command\": \"git -C . status --short\" }],\n    \"sessionStart\":     [{ \"command\": \"cat .alfred/session-notes.md 2>/dev/null\" }],\n    \"preCompact\":       [{ \"command\": \"echo 'keep the architecture decisions'\" }]\n  }\n}\n```\n\n`subagentModel` runs subagents and compaction on a cheaper model. `reviewModel` is the model that gives the cross-model second opinion (`/review`) — point it at a different vendor than your main model; `reviewAuto` runs that review automatically after every editing turn. `search` configures `web_search` (else `TAVILY_API_KEY`/`BRAVE_API_KEY`, else a keyless DuckDuckGo fallback). A project's `alwaysAllow`, `hooks`, `mcpServers`, and `providers` only take effect after you **trust the directory** (Alfred prompts the first time it sees them).\n\n### Credentials (`providers`)\n\nThe `providers` map is the alternative to environment variables: each entry holds that provider's `apiKey`, `baseUrl`, and a default `model`. A config key takes priority over the corresponding env var, and the base URL extends/overrides the built-in preset — so you can define brand-new endpoints (`\"local\"` above) without `ALFRED_*` env vars. `model` is the model Alfred uses when you switch to that provider. Add `\"type\": \"anthropic\"` for an Anthropic-native endpoint. Because this file can hold keys, Alfred writes it `chmod 600`; keep it out of version control.\n\nThen switch between them in-session: **`/provider`** lists every provider (● configured, ○ needs a key, → current) and lets you pick by number or name; **`/models`** fetches the current provider's model list so you can pick one. `/model openrouter/qwen/qwen3-coder` still works for a direct switch.\n\nMCP servers can also live in a Claude Code-compatible `.mcp.json` at the project root.\n\n### In-session commands\n\n| Command | Effect |\n|---|---|\n| `/model [provider/model] [--save]` | show or switch model (aliases work; history carries over) |\n| `/provider [name]` | switch provider — lists configured ones to pick from |\n| `/models` | list the current provider's models and pick one |\n| `/effort [low\\|medium\\|high] [--save]` | reasoning depth on models that support it |\n| `/review [model] [--save]` | cross-model \"second opinion\" on edits since the last review |\n| `/style [name] [--save]` | output style: default / concise / explanatory |\n| `/theme [name] [--save]` | color theme: default / nord / dracula / solarized / gruvbox / neon / ocean |\n| `/config [edit]` | show effective configuration, or open the config file |\n| `/plan` | toggle plan mode (read-only; propose a plan to approve) |\n| `/export [path]` | write the conversation to a Markdown file |\n| `/compact [focus]` | summarize older history (optional focus), keep recent turns verbatim |\n| `/cost` | token usage and estimated dollar cost for the session |\n| `/resume [n]` | list recent sessions / load one |\n| `/init` | explore the repo and generate `ALFRED.md` |\n| `/tools` | list tools and permission state |\n| `/agents` | list custom subagents (`.alfred/agents/*.md`) |\n| `/doctor` | environment & provider health check |\n| `/mcp` | MCP servers, prompts, and resources |\n| `/clear` | start a fresh conversation (the old one is kept on disk) |\n| `/<custom>`, `/mcp__server__prompt` | your command, or an MCP prompt |\n| `/help`, `/exit` | the obvious |\n\n## Development\n\n```sh\nnpm run dev          # run from source\nnpm run typecheck\nnpm test             # node:test suite via tsx (offline)\nnpm run build\n\n# Dogfooding: drive the built CLI through real -p tasks against a live provider\n# (makes real API calls / spends tokens — not part of `npm test`):\nALFRED_MODEL=anthropic/claude-haiku-4-5 npm run smoke\n```\n\n## Architecture\n\nConversation history is provider-neutral; each adapter converts it to its own wire format. Anthropic turns keep raw content blocks so thinking blocks replay correctly, and history (including tool-call ids and images) survives `/model` switches across providers. Tools receive a `ToolRuntime` carrying the abort signal, the session's `FileTracker` (read/stale state), and — for the main agent only — a `spawnSubagent` hook. The codebase is covered by an offline `node:test` suite and has been through multiple rounds of multi-agent adversarial review.\n\n```\nsrc/\n  index.ts          CLI: args, REPL, slash commands, completion, sessions, trust prompt\n  agent.ts          agent loop, retry wiring, subagents + routing, compaction, headless events\n  workspace.ts      path containment + secret deny-list for file/search tools\n  agents.ts         named subagent definitions (.alfred/agents/*.md)\n  mcp.ts            MCP client (stdio + HTTP + SSE) → tools, prompts, resources\n  mcp-oauth.ts      OAuth provider + token cache for remote MCP servers\n  permissions.ts    tool/bash-prefix rules + compound-command guard\n  hooks.ts          tool + session-event shell hooks\n  mentions.ts       @file / @image expansion\n  commands.ts       custom slash commands\n  config.ts         global + project settings merge + project-trust gating\n  sessions.ts       auto-saved conversations (atomic writes)\n  context.ts        ALFRED.md / AGENTS.md / CLAUDE.md (parent walk + @-imports)\n  files-state.ts    FileTracker (read/stale detection)\n  pricing.ts        per-model cost estimation (/cost in dollars)\n  export.ts         conversation → Markdown (/export)\n  ui.ts             spinner, streaming markdown + thinking, diff previews, control-stripping\n  providers/        types.ts, anthropic.ts, openai-compatible.ts, retry.ts, index.ts\n  tools/            bash (+ background), files (+ multi_edit), search, web (+ search), task, todo\n```\n","readmeFilename":"README.md","_rev":"1-a01071e92bacbe34aaf351ea5e01cc85"}