{"id":50294538,"url":"https://github.com/ayvazyan10/asterisk","last_synced_at":"2026-05-28T08:02:27.919Z","repository":{"id":354130691,"uuid":"1222194581","full_name":"ayvazyan10/asterisk","owner":"ayvazyan10","description":"Lightweight, personal AI assistant — Ollama-first with Anthropic optional, daemon mode, Telegram + WhatsApp bot bridges. Apache 2.0.","archived":false,"fork":false,"pushed_at":"2026-05-05T22:06:42.000Z","size":553,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-05-05T23:29:18.414Z","etag":null,"topics":["ai-agent","anthropic","bun","claude","cli","local-first","ollama","telegram-bot","typescript","whatsapp-bot"],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ayvazyan10.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-27T06:11:32.000Z","updated_at":"2026-05-05T22:06:46.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/ayvazyan10/asterisk","commit_stats":null,"previous_names":["ayvazyan10/asterisk"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ayvazyan10/asterisk","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ayvazyan10%2Fasterisk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ayvazyan10%2Fasterisk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ayvazyan10%2Fasterisk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ayvazyan10%2Fasterisk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ayvazyan10","download_url":"https://codeload.github.com/ayvazyan10/asterisk/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ayvazyan10%2Fasterisk/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33599465,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-28T02:00:06.440Z","response_time":99,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-agent","anthropic","bun","claude","cli","local-first","ollama","telegram-bot","typescript","whatsapp-bot"],"created_at":"2026-05-28T08:02:26.765Z","updated_at":"2026-05-28T08:02:27.912Z","avatar_url":"https://github.com/ayvazyan10.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Asterisk\n\nA lightweight, personal AI assistant. Asterisk gives you an interactive\nagent in your terminal and an optional long-running daemon that bridges the\nsame assistant to Telegram and WhatsApp.\n\n- **Local by default** — talks to a local [Ollama](https://ollama.com) model\n  out of the box; the public `@anthropic-ai/sdk` is wired in as an opt-in\n  alternative.\n- **Real tools** — filesystem, shell, web, **a real Chromium browser via\n  Playwright**, MCP-server integration, sub-agents, scheduled and recurring\n  prompts, and more.\n- **No telemetry, no cloud control plane.** Everything runs on your machine.\n- **Built on documented APIs** — Anthropic Messages + tool-use loop, Ollama\n  HTTP, Telegram Bot API ([grammY](https://grammy.dev)), WhatsApp Meta Cloud\n  API, [Model Context Protocol](https://modelcontextprotocol.io), Playwright.\n- **Apache 2.0** licensed.\n\nStatus `0.1.0` — early but real. ~36 built-in tools, 20 slash commands,\n14 daemon-managed scheduling/lifecycle features, **29 bundled skills**,\n**27 specialised sub-agent types** the agent can dispatch on demand,\nlayered multi-language rules, switchable output styles\n(default / concise / explanatory / learning), a SOUL.md persona\nsystem that bot users can manage per-chat, and an agent loop\nhardened with tool concurrency, context compaction, prompt caching,\nbash safety guards, file history, and conversation persistence.\n\n## Install\n\nOne-line install (macOS / Linux / WSL):\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/ayvazyan10/asterisk/master/install.sh | bash\n```\n\nThe installer:\n\n1. Installs [Bun](https://bun.sh) ≥ 1.2 if it isn't already on your machine.\n2. Clones Asterisk into `~/.local/share/asterisk`.\n3. Builds `dist/`.\n4. Downloads Chromium for Playwright (~150 MB; skip with `ASTERISK_SKIP_BROWSERS=1`).\n5. Symlinks `~/.local/bin/asterisk` so the `asterisk` command is on your PATH.\n\nOverride locations or branch via env vars on the receiving `bash`:\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/ayvazyan10/asterisk/master/install.sh \\\n  | ASTERISK_INSTALL_DIR=/opt/asterisk ASTERISK_BIN_DIR=/usr/local/bin bash\n```\n\nAvailable: `ASTERISK_INSTALL_DIR` (default `~/.local/share/asterisk`),\n`ASTERISK_BIN_DIR` (default `~/.local/bin`), `ASTERISK_BRANCH` (default\n`master`), `ASTERISK_REPO_URL`, `ASTERISK_SKIP_BROWSERS`.\n\nTo uninstall:\n\n```bash\nbash \u003c(curl -fsSL https://raw.githubusercontent.com/ayvazyan10/asterisk/master/uninstall.sh)\n```\n\nYour `~/.asterisk/` config is preserved unless you delete it explicitly.\n\n### From source\n\n```bash\ngit clone https://github.com/ayvazyan10/asterisk.git \u0026\u0026 cd asterisk\nbun install\nbun playwright install chromium    # optional — only if you want browser tools\nbun run build\n./bin/asterisk help\n```\n\n## Quick start\n\nRequirements:\n\n- [Bun](https://bun.sh) ≥ 1.2 (handled by the installer).\n- An Ollama server reachable from this machine, OR an `ANTHROPIC_API_KEY`.\n\n```bash\nasterisk                # interactive REPL\nasterisk start          # daemon mode (Telegram / WhatsApp bridges)\nasterisk status         # daemon pid + log size\nasterisk logs 100\nasterisk restart\nasterisk stop\nasterisk configure      # interactive wizard for provider + bots + MCP\nasterisk help\n```\n\n## REPL highlights\n\n- Type `/` and a filtered command picker pops up — `↑↓` navigate, `Tab`\n  completes, `Enter` runs, `Esc` clears.\n- Slash commands open **forms** for fields and **list pickers** for choices,\n  not CLI args. Ask the agent to add an MCP server and it walks you through\n  a transport-pick → form flow.\n- Long tool output is collapsed by default with `[+N more lines · Ctrl+O to expand]`.\n- The thinking indicator sits **above** the input, not inside it — you can\n  type a side question while the agent works; it gets queued and runs after\n  the current turn.\n- Markdown rendered: `**bold**`, `*italic*`, `` `code` ``, fenced code blocks,\n  bullets, headers, blockquotes — all properly indented under the cyan\n  assistant marker.\n- Screenshots render inline on iTerm2 / WezTerm / Kitty; on other terminals\n  the `file://` URL is clickable and `open: true` launches the OS viewer.\n\n## Slash commands\n\n| Command            | What it does                                                |\n| ------------------ | ----------------------------------------------------------- |\n| `/help [name]`     | List commands or show details for one                       |\n| `/clear`           | Forget the current conversation history                     |\n| `/model [name]`    | List installed models or switch the active one              |\n| `/provider [name]` | Switch between `ollama` and `anthropic` at runtime          |\n| `/tools`           | List registered tools (built-ins + MCP)                     |\n| `/status`          | Live runtime view: provider, bots, MCP, daemon              |\n| `/config`          | Interactive forms for each config section                   |\n| `/reset`           | Clear history and rebuild the provider from config          |\n| `/mcp`             | Manage MCP servers — list/add/edit/remove/reload (visual)   |\n| `/agents`          | List specialised sub-agent types you can dispatch           |\n| `/output-style`    | Switch reply style — default / concise / explanatory / learning |\n| `/rules`           | List the rules currently loaded into the system prompt      |\n| `/skills`          | List installed skills (bundled + user + project)            |\n| `/skill [name]`    | Run a skill — picker if no name given                       |\n| `/soul [verb]`     | Show / `init` / `where` your SOUL.md persona                |\n| `/plan`            | Toggle Plan Mode (read-only research mode)                  |\n| `/tasks`           | List the agent's in-flight tasks for this session           |\n| `/hooks`           | Manage agent-loop lifecycle hooks (visual)                  |\n| `/doctor`          | Diagnostics — checks Ollama, Anthropic, system tools, MCP   |\n| `/quit`            | Exit the REPL                                               |\n\n## Built-in tools\n\nThe agent has these tools out of the box:\n\n**Filesystem \u0026 shell**\n`Bash` · `Read` · `Write` · `Edit` · `Grep` · `Glob`\n\n**Browser (real Chromium via Playwright)**\n`BrowserNavigate` · `BrowserClick` · `BrowserType` · `BrowserPress` ·\n`BrowserSnapshot` · `BrowserScreenshot` · `BrowserWait` · `BrowserClose`\n\n**Web research**\n`WebFetch` (URL → readable text) · `WebSearch` (Brave / Tavily / SearXNG /\nDDG instant-answer, picks the first backend you've configured a key for)\n\n**Planning**\n`TaskCreate` · `TaskUpdate` · `TaskList` · `TaskGet` · `TaskStop` — the\nagent's own todo list, used to track multi-step work.\n\n**Plan Mode**\n`EnterPlanMode` / `ExitPlanMode` — toggle a flag that hides write tools so\nthe agent can only research.\n\n**Delegation**\n`Agent` — spawn a sub-agent in an isolated conversation for focused\nresearch or parallel investigation. Pass `subagent_type: \u003cname\u003e` to\ndispatch a specialised role (code-reviewer, security-reviewer, planner,\nexplore, …) — see [Sub-agent types](#sub-agent-types) below.\n\n**Worktree**\n`EnterWorktree` / `ExitWorktree` — create / remove a `git worktree` for\nrisky changes that shouldn't touch the active branch.\n\n**Monitoring \u0026 notifications**\n`Monitor` (start/tail/stop background commands) · `PushNotification`\n(webhook out-of-band) · `RemoteTrigger` (generic HTTP request).\n\n**Interactive**\n`AskUserQuestion` — pause the loop and ask the user a question with\nfree-text or a list-picker; user's answer resolves the tool.\n\n**Scheduling** (daemon-managed)\n`ScheduleWakeup` (one-shot delay) · `CronCreate` / `CronDelete` / `CronList`\n(5-field cron expressions). The daemon polls every 30s and dispatches due\nitems as fresh agent turns.\n\n**Tool discovery**\n`ToolSearch` — keyword search across all registered tools. Enables\ndeferred tool loading so the full tool list doesn't bloat every prompt.\n\nPlus any tools exposed by configured MCP servers, namespaced as\n`\u003cservername\u003e__\u003ctoolname\u003e`.\n\n## Skills, rules, hooks, souls\n\n**Skills** — reusable workflows. 29 bundled out of the box:\n\n*Core workflow:*\n- `simplify` — review your recent changes for reuse / quality / efficiency\n- `batch` — apply one operation across many targets, with progress tracking\n- `stuck` — diagnose why a task is blocked, propose alternatives\n- `dream` — free-form roam, find one improvement worth making\n- `skillify` — capture the current conversation as a new SKILL.md\n- `verify` — run typecheck / lint / tests / build, classify each result,\n  isolate root causes for any failures\n- `debug` — diagnose a specific failure end-to-end: reproduce, read the\n  error literally, hypothesise + verify, propose a concrete fix, re-run\n- `feature` — drive a feature plan → implement → review → verify →\n  commit, with Plan Mode discipline on the planning phase\n\n*PRP pipeline (granular alternative to `feature`):*\n- `prp-plan` — write a one-page Plan-Requirements-Pitch doc in Plan Mode\n- `prp-implement` — execute against the PRP doc, with task tracking + verify\n- `prp-pr` — open a real GitHub PR with summary + test plan via `gh`\n- `prp-commit` — write a coherent commit with a real WHY message\n\n*Loops + scheduling:*\n- `loop` — recurring task with explicit stop conditions\n- `schedule` — friendly wrapper over `ScheduleWakeup` / `CronCreate`\n- `santa-loop` — adversarial dual-review: dispatches `code-reviewer`\n  and `security-reviewer` sub-agents in parallel, iterates until both\n  approve or hits a 5-round cap\n\n*Quality / security tooling:*\n- `dep-audit` — `npm audit` / `cargo audit` / `pip-audit` / `govulncheck`,\n  classify by severity, propose upgrades\n- `security-scan` — active scanning (gitleaks for secrets, trivy / gosec /\n  bandit / semgrep / tfsec depending on stack)\n- `cloud-infrastructure-security` — IaC review for Terraform / Pulumi /\n  CDK / Helm / K8s / CloudFormation: IAM wildcards, exposed ports,\n  plaintext secrets, supply-chain\n- `pr-review` — review an open GitHub PR end-to-end via \\`gh\\`\n\n*LLM / agent ops:*\n- `ai-regression-testing` — golden-trace harness for LLM outputs\n- `eval-harness` — score outputs against a rubric (graded eval)\n- `prompt-optimizer` — iterate on a prompt with measurable lift\n- `mcp-server-patterns` — build an MCP server with the public SDK\n- `data-scraper-agent` — robust scraper using `BrowserNavigate` + `Snapshot`\n- `regex-vs-llm-structured-text` — tactical guide on when to reach for\n  each (and the hybrid pre-filter pattern)\n\n*Auditing your setup:*\n- `audit-memory` — inventory rules / souls / hooks; flag stale entries\n- `skill-stocktake` — inventory user-installed skills + agents; surface\n  dead weight\n\n*Other:*\n- `release-notes` — generate notes from `git log \u003cprev\u003e..HEAD`, grouped\n  by type, with breaking changes promoted\n- `youtube-summarizer` — summarise a YouTube video (uses `yt-dlp` if\n  available for the transcript, falls back to WebFetch on description)\n\nAdd your own at `~/.asterisk/skills/\u003cname\u003e/SKILL.md` (user-global) or\n`\u003crepo\u003e/.asterisk/skills/\u003cname\u003e/SKILL.md` (project-local). User/project\nskills override bundled ones with the same name.\n\n**Rules** — markdown auto-loaded into the system prompt. Two layouts:\n\n*Flat (simple):*\n- `~/.asterisk/rules/*.md` — user-global (e.g. tone, coding style)\n- `\u003crepo\u003e/.asterisk/rules/*.md` — project-local\n- `\u003crepo\u003e/ASTERISK.md` — project root marker\n\n*Layered (multi-language):*\n- `~/.asterisk/rules/common/*.md` — universal, always loaded\n- `~/.asterisk/rules/\u003clang\u003e/*.md` — only loaded when the project's\n  primary language matches (`typescript`, `python`, `golang`, `rust`,\n  `java`, `php`, `swift`, `dart`, `cpp`, `web`, `ruby`, …).\n- Same structure under `\u003crepo\u003e/.asterisk/rules/`.\n- Auto-detection from manifest files (`package.json`, `Cargo.toml`,\n  `pyproject.toml`, `go.mod`, …). Override via `ASTERISK_LANG=python`.\n\n**Output styles** — pluggable behaviour modifiers spliced into the\nsystem prompt alongside rules + soul. Switch via `/output-style \u003cname\u003e`\nin the REPL or `/style \u003cname\u003e` in the bots; persists to `config.json`.\nFour bundled:\n\n- `default` — baseline, no extra style instructions.\n- `concise` — trim every reply to the minimum useful answer; lists\n  over prose; skip preambles and pleasantries.\n- `explanatory` — show reasoning + tradeoffs alongside the answer.\n  Good for learning a codebase or onboarding to a domain.\n- `learning` — collaborative; the agent surfaces non-trivial design\n  decisions via `AskUserQuestion` and waits for the user to pick before\n  applying.\n\n**Hooks** — shell commands fired at agent-loop lifecycle events\n(`before_turn`, `after_turn`, `before_tool`, `after_tool`, `on_error`).\nConfigured via `/hooks` (visual). The hook command receives the event\npayload as JSON on stdin; stdout is surfaced as a system note in the\ntranscript.\n\n**Souls** — `SOUL.md` describes who the assistant should be and who it's\ntalking to. Spliced into the system prompt before rules. Three layers,\nall optional, later wins on conflict:\n\n- `~/.asterisk/SOUL.md` — operator persona (applies everywhere)\n- `~/.asterisk/souls/\u003cscope\u003e-\u003csid\u003e.md` — **per-chat** persona; written by\n  Telegram / WhatsApp users via `/soul set \u003ctext\u003e`, so each chat owns its\n  own description without affecting anyone else\n- `\u003crepo\u003e/.asterisk/SOUL.md` or `\u003crepo\u003e/SOUL.md` — project-local persona\n\nIn the REPL: `/soul` shows what's loaded, `/soul init` drops a starter\ntemplate at `~/.asterisk/SOUL.md`, `/soul where` lists the search paths.\n\nIn Telegram / WhatsApp: `/soul`, `/soul set \u003cmulti-line markdown\u003e`,\n`/soul edit`, `/soul clear`, `/soul help` — all scoped to the current\nchat. `/soul set Call me Levon, reply in Russian, skip apologies` is\nenough to teach the bot a new persona for that chat alone.\n\n## Sub-agent types\n\nThe `Agent` tool can dispatch a sub-agent with a tailored system prompt\nand (sometimes) a restricted tool-set. The parent agent passes\n`subagent_type: \u003cname\u003e` to pick a specialist; omitting it spawns a\ngeneral-purpose sub-agent with the parent's full tools.\n\n**27 bundled types out of the box:**\n\n- **Exploration / research:** `general-purpose`, `explore` (read-only\n  scout), `docs-lookup`\n- **Planning / architecture:** `planner`, `architect`\n- **Code review:** `code-reviewer`, `security-reviewer`,\n  `database-reviewer`, `performance-optimizer`, `refactor-cleaner`,\n  `doc-updater`\n- **Language-specific reviewers:** `typescript-reviewer`,\n  `python-reviewer`, `go-reviewer`, `rust-reviewer`\n- **Build / test:** `build-error-resolver`, `tdd-guide`, `e2e-runner`\n- **Domain:** `chief-of-staff` (multi-channel triage),\n  `healthcare-reviewer`\n- **Open-source pipeline:** `opensource-forker` →\n  `opensource-sanitizer` → `opensource-packager`\n- **Loops / harnesses:** `loop-operator`, `gan-planner`,\n  `gan-generator`, `gan-evaluator`\n\nAdd your own at `~/.asterisk/agents/\u003cname\u003e.md` (user-global) or\n`\u003crepo\u003e/.asterisk/agents/\u003cname\u003e.md` (project-local). Same markdown +\nfrontmatter format as skills:\n\n```markdown\n---\nname: my-reviewer\ndescription: Reviews against our internal style guide.\nallowedTools: Read, Grep, Glob, Bash\nmaxTurns: 12\n---\nYou review code against the patterns in our internal style guide …\n```\n\nUser/project files override bundled by name. Run `/agents` to see what's\nloaded.\n\n## Bot transports\n\n| Transport            | Status                | Notes                                              |\n| -------------------- | --------------------- | -------------------------------------------------- |\n| Telegram (grammY)    | Recommended           | Bot token from @BotFather; allowlist required.     |\n| WhatsApp Meta Cloud  | Recommended           | ToS-compliant; needs Meta Business Manager setup.  |\n| WhatsApp web-js      | **Personal use only** | Drives WhatsApp Web via Puppeteer. Violates WhatsApp ToS. Risks number bans. |\n\nAll bot writes are gated by config — no transport runs unless you explicitly\nenable it via `asterisk configure`. Both bots can also send media: any\nattachment the agent emits via the `Attach` tool (image, video, audio,\ndocument) is delivered as a real Telegram / WhatsApp media message.\n\n**Telegram reply modes** (`bots.telegram.streamMode`):\n\n- `final` *(default)* — one message at the end of the turn. Cheapest, no\n  edit churn, identical to a typical chat reply.\n- `status` — sends a `◐ working…` placeholder, edits it with live\n  tool-call status (`BrowserNavigate · https://wttr.in/...`,\n  `WebFetch · https://...`), and replaces it with the final reply when\n  the turn ends. Good for visibility into long-running tool chains.\n- `stream` — placeholder is progressively edited with the model's text\n  as it arrives, so the reply types itself out in front of the user.\n  Active tool calls surface as a faded tail line under the streaming\n  text.\n\nTelegram's Bot API rate-limits edits to ~1/sec/chat; `streamThrottleMs`\n(default 1000) coalesces rapid updates so we stay under the limit.\nWhatsApp transports don't expose `editMessageText`, so this knob is\nTelegram-only — WhatsApp always uses the equivalent of `final` mode.\n\n**Text formatting** (`bots.telegram.parseMode`):\n\n- `html` *(default)* — the agent's markdown is converted to Telegram HTML\n  on the way out, so `**bold**`, `*italic*`, `` `code` ``, fenced code\n  blocks, `[links](https://…)`, headings, bullets and `\u003e quotes` all\n  render as the user expects. Mid-stream tag balancing keeps live edits\n  valid; if Telegram still rejects the markup we silently fall back to\n  plain text rather than dropping the reply.\n- `plain` — send exactly what the agent emits. Use this if you want the\n  raw markdown markers visible (debugging, or if your persona instructs\n  the model to avoid markup entirely).\n\n**Per-user isolation.** Each chat — Telegram chatId, WhatsApp number, or\nthe local REPL — gets its own task list, plan-mode flag, browser context,\nmonitored processes, and SOUL.md persona. Two users sharing a daemon\nnever see each other's state.\n\n**Bot-side slash commands** (auto-completed in Telegram via\n`setMyCommands`):\n\n| Command  | What it does                                              |\n| -------- | --------------------------------------------------------- |\n| `/help`  | How to use the bot                                        |\n| `/status`| Provider, model, your tasks, plan mode, worktree          |\n| `/clear` | Forget conversation history                               |\n| `/reset` | Clear history + tasks + plan mode                         |\n| `/tasks` | List your tasks                                           |\n| `/plan`  | Toggle Plan Mode (read-only research mode)                |\n| `/soul`  | Show / `set` / `edit` / `clear` your personal persona     |\n\n## MCP servers\n\nAsterisk speaks the [Model Context Protocol](https://modelcontextprotocol.io)\nas a **client**. Add servers via `/mcp` (or hand-edit\n`~/.asterisk/config.json` `mcpServers[]`):\n\n- **stdio**: `{ name, transport: \"stdio\", command, args, env }`\n- **http**: `{ name, transport: \"http\", url, headers }`\n\nTools exposed by connected MCP servers are namespaced as\n`\u003cservername\u003e__\u003ctoolname\u003e` and added to the agent's tool registry on\nstartup. Failures during connect surface in `/mcp list`, never crash\nstartup.\n\n## Architecture\n\n```\nbin/asterisk         # Bash dispatcher: REPL | start | stop | status | logs | configure\nsrc/\n├── entrypoints/     # cli.tsx · daemon.ts · control.ts · configure.tsx\n├── repl/            # Ink REPL — App, CommandMenu, MarkdownText,\n│                    # WorkingIndicator, forms/, inline-image\n├── agent/loop.ts    # tool-use loop with retry, abort, terminal-reason,\n│                    # rules, hooks, sub-agents, per-tool timeout,\n│                    # tool concurrency, context compaction\n├── agent/           # compaction.ts · file-history.ts · output-store.ts\n│                    # persistence.ts — conversation save/restore\n├── providers/       # ollama (default) · anthropic · errors (ProviderError)\n├── tools/           # bash · read · write · edit · grep · glob ·\n│                    # browser/ (Playwright) · webfetch · websearch ·\n│                    # tasks · subagent · planmode · worktree · notify ·\n│                    # monitor · ask · schedule · tool-search ·\n│                    # bash-safety · concurrency\n├── commands/        # slash command registry (visual flows)\n├── config/          # zod schema · loader · interactive wizard\n├── daemon/          # pidfile · logger · lifecycle · scheduler\n├── bots/            # adapter contract · telegram · whatsapp/{meta-cloud, web-js}\n├── mcp/             # client · manager (stdio + Streamable HTTP)\n├── hooks/runner.ts  # lifecycle hooks (before/after_tool, …)\n├── rules/loader.ts  # markdown rules → system prompt\n├── skills/          # bundled.ts (5) + loader (user/project SKILL.md)\n├── soul/loader.ts   # SOUL.md (user / per-chat / project) → system prompt\n├── agent/context.ts # per-session ALS — chatId scopes tasks/plan/soul/etc\n└── utils/           # retry · path\n```\n\nThe provider abstraction is provider-neutral: tools and the agent loop don't\nknow whether they're talking to Ollama or Anthropic. The same loop drives\nthe REPL and each per-chat conversation in the daemon.\n\n## Configuration reference\n\n`~/.asterisk/config.json`:\n\n```jsonc\n{\n  \"provider\": \"ollama\",                       // or \"anthropic\"\n  \"ollama\": {\n    \"baseUrl\": \"http://127.0.0.1:11434\",\n    \"model\": \"qwen3.5:9b-q8-max\",\n    \"contextWindow\": 131072\n  },\n  \"anthropic\": { \"model\": \"claude-3-5-haiku-latest\" },\n  \"bots\": {\n    \"telegram\": {\n      \"enabled\": false,\n      \"allowedUserIds\": [],\n      \"streamMode\": \"final\",                  // \"final\" | \"status\" | \"stream\"\n      \"streamThrottleMs\": 1000,               // min gap between editMessageText calls\n      \"parseMode\": \"html\"                     // \"html\" renders markdown · \"plain\" leaves it literal\n    },\n    \"whatsapp\": {\n      \"enabled\": false,\n      \"transport\": \"meta-cloud\",              // or \"web-js\"\n      \"metaCloud\": {\n        \"phoneNumberId\": \"\",\n        \"businessAccountId\": \"\",\n        \"webhookPath\": \"/whatsapp/webhook\",\n        \"webhookPort\": 8787\n      },\n      \"webJs\": { \"sessionDir\": \"\" }\n    }\n  },\n  \"daemon\": { \"logLevel\": \"info\", \"heartbeatSeconds\": 60 },\n  \"mcpServers\": [],\n  \"hooks\": []\n}\n```\n\n`~/.asterisk/secrets.env` (chmod 600):\n\n```bash\nANTHROPIC_API_KEY=\"...\"\nASTERISK_TELEGRAM_BOT_TOKEN=\"...\"\nASTERISK_WHATSAPP_META_TOKEN=\"...\"\nASTERISK_WHATSAPP_VERIFY_TOKEN=\"...\"\nASTERISK_NOTIFY_URL=\"...\"     # optional — used by PushNotification tool\n```\n\nOverride the config root with `ASTERISK_HOME=/path/to/dir`.\n\n## Reliability\n\nThe agent loop wraps every model call in retry logic with exponential\nbackoff + jitter, honours the `Retry-After` header, classifies HTTP errors\ninto kinds (`rate-limit`, `overloaded`, `server`, `network`, `auth`,\n`bad-request`, `context-overflow`, `aborted`), and threads `AbortSignal`\nend-to-end so Ctrl+C cleanly cancels the in-flight provider call, the\nsleep, and any running tool.\n\nEvery tool call is timeboxed (default 120s) by an inner `AbortController`\nthat ANDs the parent signal with the timeout — runaway shell commands\ncan't lock the loop. Press **ESC** in the REPL to abort the current turn\nand clear the message queue.\n\n**Agent loop hardening:**\n\n- **Tool concurrency** — concurrency-safe tools (Read, Grep, Glob,\n  WebFetch, WebSearch, …) run in parallel via `Promise.all` when the\n  model emits multiple in one turn.\n- **Context compaction** — when estimated tokens exceed 80k, old tool\n  results and long text blocks are truncated while keeping the 6 most\n  recent messages intact.\n- **Large result persistence** — tool outputs \u003e 8 KB are saved to\n  `~/.asterisk/outputs/` with a 500-char preview kept in context.\n- **Prompt caching** — Anthropic provider sends the system prompt with\n  `cache_control: { type: 'ephemeral' }` for cross-turn caching.\n- **Bash safety** — dangerous command patterns (rm -rf /, fork bombs,\n  curl|bash, secrets in args) are blocked before execution.\n- **File history** — Write/Edit tools snapshot files before overwriting;\n  stored in `~/.asterisk/file-history/`.\n- **Conversation persistence** — daemon saves per-chat history to\n  `~/.asterisk/conversations/` as JSON, restores on reconnect, 7-day\n  expiry.\n\n## Roadmap\n\nSee [ROADMAP.md](./ROADMAP.md) for the prioritised list of upcoming work\n— skill marketplace, token/cost tracking, image content blocks, multi-agent\ncoordinator, and others.\n\n## Limitations\n\n- Tasks, plan-mode, and worktree state live in memory; daemon restart\n  wipes them. Conversation history now persists across daemon restarts\n  (7-day expiry), but task lists do not.\n- No image content blocks back to the model, so it can't *see* the\n  screenshots it captures (tracked).\n\n## License\n\n[Apache 2.0](./LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fayvazyan10%2Fasterisk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fayvazyan10%2Fasterisk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fayvazyan10%2Fasterisk/lists"}