{"id":51228909,"url":"https://github.com/berkayturanci/voicebridge","last_synced_at":"2026-06-28T14:01:41.048Z","repository":{"id":366573605,"uuid":"1268468951","full_name":"berkayturanci/voicebridge","owner":"berkayturanci","description":"Hands-free, two-way voice for your coding agent (Claude Code, Codex, Antigravity, Ollama) from your phone — free for noncommercial use, source-available, no ElevenLabs. Browser Web Speech + a tiny Node bridge over Tailscale HTTPS.","archived":false,"fork":false,"pushed_at":"2026-06-22T11:53:30.000Z","size":1942,"stargazers_count":0,"open_issues_count":29,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-22T13:08:21.179Z","etag":null,"topics":["ai-agent","claude","claude-code","codex","coding-agent","flutter","hands-free","nodejs","ollama","self-hosted","speech-to-text","tailscale","text-to-speech","voice-assistants","web-speech-api"],"latest_commit_sha":null,"homepage":"","language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/berkayturanci.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":"CITATION.cff","codeowners":".github/CODEOWNERS","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-06-13T15:13:02.000Z","updated_at":"2026-06-22T12:13:42.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/berkayturanci/voicebridge","commit_stats":null,"previous_names":["berkayturanci/voicebridge"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/berkayturanci/voicebridge","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/berkayturanci%2Fvoicebridge","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/berkayturanci%2Fvoicebridge/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/berkayturanci%2Fvoicebridge/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/berkayturanci%2Fvoicebridge/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/berkayturanci","download_url":"https://codeload.github.com/berkayturanci/voicebridge/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/berkayturanci%2Fvoicebridge/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34890795,"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-06-28T02:00:05.809Z","response_time":54,"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","claude","claude-code","codex","coding-agent","flutter","hands-free","nodejs","ollama","self-hosted","speech-to-text","tailscale","text-to-speech","voice-assistants","web-speech-api"],"created_at":"2026-06-28T14:01:35.729Z","updated_at":"2026-06-28T14:01:41.042Z","avatar_url":"https://github.com/berkayturanci.png","language":"Dart","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/hero.svg\" alt=\"voicebridge — hands-free, two-way voice for your coding agent, from your phone\" width=\"100%\" /\u003e\n\u003c/p\u003e\n\n# voicebridge\n\n[![CI](https://github.com/berkayturanci/speak-with-claude-code/actions/workflows/ci.yml/badge.svg)](https://github.com/berkayturanci/speak-with-claude-code/actions/workflows/ci.yml)\n[![Node ≥ 18](https://img.shields.io/badge/node-%E2%89%A518-3fb950)](package.json)\n[![License: PolyForm Noncommercial 1.0.0](https://img.shields.io/badge/license-PolyForm%20Noncommercial%201.0.0-1f6feb)](LICENSE)\n[![Agents: Claude · Codex · Antigravity · Ollama](https://img.shields.io/badge/agents-Claude%20%C2%B7%20Codex%20%C2%B7%20Antigravity%20%C2%B7%20Ollama-8b949e)](#agents-sessions--modes)\n\n**Hands-free, two-way voice for your coding agent from your phone — free, source-available, no ElevenLabs.**\n\nYou speak **or type** on your phone, a coding agent (running on your Mac/Linux\nbox) does the work, and the reply streams back as chat **and** spoken audio —\nlike a phone call with your agent, with a keyboard when you want one.\n\n\u003cp align=\"center\"\u003e\u003cimg src=\"docs/demo.svg\" alt=\"voicebridge phone UI — a chat with an agent, with a text box and a mic\" width=\"300\" /\u003e\u003c/p\u003e\n\u003cp align=\"center\"\u003e\u003cem\u003eType or speak; the agent replies in chat and aloud.\u003c/em\u003e\u003c/p\u003e\n\n- 🤖 **Multiple agents** — Claude Code, **Codex**, **Antigravity**, and **Ollama**\n  (a fully-local open-source model), selectable per session, each with autonomy\n  **modes** (ask → full-auto).\n- 🗂️ **Multiple sessions** — run several conversations in parallel (e.g. \"Claude on\n  repo A\", \"Codex on repo B\") and switch between them in the UI.\n- ⌨️🎙️ **Type or speak** — a Claude-Code-like chat with a text box *and* a mic;\n  replies render with code blocks and are read aloud.\n- 🎙️ **Speech-to-text** and 🔊 **text-to-speech** run in your phone's **browser**\n  (Web Speech API) — no per-minute cloud voice cost, no API keys.\n- ⚡ **Streaming** — the reply is spoken **sentence-by-sentence as it's generated**,\n  not after the whole turn finishes, with a **Stop** button to cut it off.\n- 🧩 A **tiny Node bridge** (one dependency: `qrcode-terminal`) relays the text to\n  the agent CLI on your machine and streams its reply back.\n- 🔒 Reached over **Tailscale** (your private network) with real HTTPS, with an\n  optional **shared access token** — your code never touches a third-party voice\n  service.\n- 🗣️ Optional **fully-local speech-to-text** via your own Whisper command\n  (`STT_MODE=whisper`), so even the transcription stays on your machine.\n\n\u003e Honest scope: for Claude/Codex/Antigravity the **model** runs in its vendor's\n\u003e cloud (that's how those CLIs work); with the **Ollama** backend the model runs\n\u003e fully locally. voicebridge just removes the *voice* middleman (ElevenLabs)\n\u003e and its limits. Speech recognition on iOS uses Apple's free dictation service;\n\u003e text-to-speech is fully on-device.\n\u003e\n\u003e Agent support: the **Claude** backend is fully implemented and tested. The\n\u003e **Codex** (`codex exec`) and **Antigravity** (`agy --print`) backends use the\n\u003e same invocations as [ai-jury](https://github.com/berkayturanci/ai-jury) and\n\u003e stream their plain-text stdout; verify them on your own machine. Conversation\n\u003e continuity is built-in for Claude (`--continue`) and opt-in for Codex /\n\u003e Antigravity via `CODEX_CONTINUE_ARGS` / `AGY_CONTINUE_ARGS` (see\n\u003e [docs/configuration.md](docs/configuration.md)).\n\n---\n\n## Quickstart\n\n```bash\ngit clone \u003cyour-repo-url\u003e voicebridge \u0026\u0026 cd voicebridge \u0026\u0026 npm install\ncp .env.example .env                                  # set PROJECT_DIR + ACCESS_TOKEN\nCLAUDE_BIN=$(which claude) npm start                  # prints a QR for your phone\ntailscale serve --bg --https=443 localhost:8787       # expose over HTTPS (separate terminal)\n```\n\nThen open the printed `https://…ts.net` URL in your phone's browser (Safari on\niOS) and tap 🎤 or just type. New to it? See [Requirements](#requirements),\n[Troubleshooting](#troubleshooting), and the step-by-step\n[mobile voice setup](docs/mobile-voice-setup.md) (why the mic needs HTTPS).\n\n## Requirements\n\n- A computer (macOS/Linux) with **Claude Code** installed and logged in\n  (`npm i -g @anthropic-ai/claude-code`, then `claude` → `/login`).\n- **Node.js ≥ 18** (`brew install node`).\n- **Tailscale** on both the computer and the phone (`brew install --cask tailscale`,\n  and the Tailscale app from the App Store). Free.\n- iPhone/iPad: open in **Safari** (do **not** \"Add to Home Screen\" — installed PWAs\n  can't use the microphone on iOS).\n\n## Setup\n\n### 1. On your computer\n\n```bash\ngit clone \u003cyour-repo-url\u003e voicebridge\ncd voicebridge\nnpm install            # qrcode-terminal (web-push is optional, for real push)\n\n# Configure with a .env file (or plain env vars):\ncp .env.example .env   # then edit: PROJECT_DIR, ACCESS_TOKEN, …\n\n# Start the bridge (binds to 127.0.0.1:8787 by default)\nnpm start\n```\n\nAny variable in `.env` is loaded at startup (real environment variables win).\n\nOn startup the bridge prints a **QR code** for the phone URL — scan it to open\nthe UI (and, when `ACCESS_TOKEN`/`PUBLIC_URL` are set, to authorize on open).\n\n### 2. Expose it to your phone over HTTPS (Tailscale)\n\nWeb Speech needs a secure context (HTTPS) — over plain `http://\u003clan-ip\u003e` a\nphone's browser disables the mic. Tailscale gives your machine a real HTTPS cert\nautomatically:\n\n```bash\ntailscale serve --bg --https=443 localhost:8787\ntailscale serve status     # shows the https://\u003cyour-machine\u003e.\u003ctailnet\u003e.ts.net URL\n```\n\nThe **first time** you run `tailscale serve`, you may have to enable the feature\nonce for your tailnet — it prints a `login.tailscale.com/f/serve?node=…` link;\nopen it and toggle Serve on. Full walkthrough (and the *why*) in\n[docs/mobile-voice-setup.md](docs/mobile-voice-setup.md).\n\n### 3. On your phone\n\n1. Make sure Tailscale is **connected** (same account).\n2. Open the `https://\u003cyour-machine\u003e.\u003ctailnet\u003e.ts.net` URL in **Safari**.\n3. Tap the 🎤 button, allow the microphone, and **speak**.\n4. Toggle **Eller serbest / Hands-free** for a continuous back-and-forth loop.\n\nThat's it — talk, and Claude Code talks back. 🎧\n\n---\n\n## Configuration\n\n| Env var        | Default              | Meaning                                            |\n|----------------|----------------------|----------------------------------------------------|\n| `PORT`         | `8787`               | Port the bridge listens on                         |\n| `HOST`         | `127.0.0.1`          | Bind address (keep local; expose via `tailscale serve`) |\n| `PUBLIC_URL`   | _(none)_             | Public URL shown in the startup QR (e.g. your Tailscale `https://…ts.net`). Falls back to `http://HOST:PORT`. |\n| `PROJECT_DIR`  | current directory    | Default working directory for new sessions         |\n| `AGENT`        | `claude`             | Default agent for the boot session (`claude`/`codex`/`antigravity`) |\n| `CLAUDE_BIN`   | `claude`             | Path to the `claude` executable                    |\n| `CODEX_BIN`    | `codex`              | Path to the `codex` executable                     |\n| `AGY_BIN`      | `agy`                | Path to the Antigravity executable                 |\n| `ACCESS_TOKEN` | _(none)_             | If set, `/api/*` requires `Authorization: Bearer \u003ctoken\u003e`. The page prompts for it once and stores it. |\n| `STT_MODE`     | `browser`            | `browser` (Web Speech) or `whisper` (local, server-side) |\n| `STT_CMD`      | _(none)_             | Whisper mode: shell command; `{file}` → recorded audio path; must print the transcript to stdout |\n\n### Optional: a shared access token\n\n```bash\nexport ACCESS_TOKEN=\"$(openssl rand -hex 16)\"\necho \"$ACCESS_TOKEN\"   # type this into the phone once when prompted\nnpm start\n```\n\n### Optional: fully-local speech-to-text (Whisper)\n\nKeeps transcription on your machine too (nothing goes to Apple). Needs `ffmpeg`\nand a Whisper CLI (e.g. `whisper.cpp`'s `whisper-cli`):\n\n```bash\nexport STT_MODE=whisper\nexport STT_CMD='ffmpeg -nostdin -i {file} -ar 16000 -ac 1 -f wav - 2\u003e/dev/null | whisper-cli -m ~/models/ggml-base.bin -nt -f - 2\u003e/dev/null'\nnpm start\n```\n\nIn whisper mode the mic button is **tap-to-start / tap-to-stop** (record, then it\ntranscribes). Hands-free loop is browser-mode only.\n\n## Agents, sessions \u0026 modes\n\n- **Session list home**: the app opens to a list of conversations (mobile\n  Claude-Code style) — each card shows the name, agent · mode · runner badges,\n  and a last-message preview. Tap a card to open it; **←** returns to the list.\n- Create a session with **＋ Yeni**: pick an **agent** (Claude / Codex /\n  Antigravity / **Ollama**), a **mode**, a **project folder**, and a name. The\n  folder field has a **📁 Browse** tree browser (no typing long paths); save\n  frequent projects as **favorites** (★) (or seed them with `FAVORITES`).\n- **Conversation history persists**: each session keeps its own transcript,\n  restored on reload — come back and the conversation is still there.\n- **Type or speak**: the composer sends on Enter (Shift+Enter for a newline) or\n  tap ➤; the 🎤 button does voice. The **🎤 → ⏹** button becomes a Stop control\n  while the agent answers or speaks.\n- **Talking mode** (📞): a continuous, hands-free voice conversation — speak, it\n  auto-sends on a pause, the reply is read aloud, then it listens again. A minimal\n  voice screen shows *listening / thinking / speaking*; the orb **grows and glows\n  as it hears you**. Tap the orb while it's speaking to **interrupt** (barge-in),\n  or the **🎙️ (top-left)** to **mute** the mic and pause without leaving — tap\n  again to resume. Backgrounding the tab (e.g. opening the camera) frees the mic\n  automatically. (Needs HTTPS for the mic.)\n- **Command palette** (⌘): pick from the project's own commands — `.claude/commands`\n  slash commands (e.g. `/keel:ship`) and `package.json` npm scripts — searchable;\n  selecting one prefills the composer.\n- **Settings sheet** (⚙): theme, **chat font size**, language, mode, hands-free,\n  audio cues, voice-friendly, notifications, TTS voice + rate, and session\n  rename / delete / new-chat — all in one tidy place, so the chat area stays big.\n- **Local or cloud runner**: each session runs the agent **locally** (CLI on your\n  machine) or, when `CLOUD_RUNNER_URL` is set, on a **cloud** runner — same UI,\n  same NDJSON protocol, and the folder picker browses the runner host. See\n  [docs/configuration.md](docs/configuration.md#runners-local-vs-cloud).\n- **Eyes-free audio cues**: optional earcons signal *listening*, *reply done*, and\n  *error* — so you can run or cycle without looking at the screen.\n- **Quick commands**: one-tap chips send canned prompts (\"What changed?\", \"Tests\",\n  \"Commit \u0026 push\", …) to the active session — handy one-handed.\n- **Voice-friendly replies**: a \"Brief voice\" toggle asks the agent to answer\n  concisely for text-to-speech (no long code dumps, ending with a one-line\n  summary) — the full text still shows in chat.\n- **Notifications**: opt-in \"Notify\" raises a notification when a reply\n  finishes in the background or ends with a question — so a hands-free task\n  pulls you back when it needs you. With VAPID keys configured it uses **real\n  Web Push** (works even when the app is closed); otherwise in-page notifications.\n- **Rich replies**: full markdown (headings, lists, http(s)-only links) with\n  code blocks (copy button) and **diff coloring** for ` ```diff ` blocks.\n- **Activity trail \u0026 collapsible output**: tool use shows a subtle running log\n  (e.g. `⚙︎ Edit server.js`), and long output blocks (npm logs, etc.) collapse by\n  default with a show-more toggle so the conversation stays readable.\n- **Installable PWA**: a web manifest, icon, and service worker make it\n  installable and cache the app shell; notifications go through the service\n  worker. (On iOS, use the Safari **tab** for voice — installed PWAs can't use\n  the microphone there.)\n- **Native app (Flutter)**: an optional iOS/Android client lives in\n  [`app/`](app/) — same bridge backend, but **native mic + TTS** so voice works\n  even as an installed app (no Safari-tab caveat). The same code also runs as a\n  **desktop client** (macOS/Windows/Linux). The PWA stays the zero-install option.\n- **Desktop app (Electron)**: [`desktop/`](desktop/) packages the bridge itself\n  into a **Mac `.dmg` / Windows / Linux** app with a control panel + tray —\n  run the server with no terminal.\n\n### Modes (autonomy)\n\nEach agent exposes modes that map to its CLI's approval/sandbox flags — pick a\nfuller-auto mode for true hands-free use (cycling, running), with the obvious\ncaveat that the agent then edits/runs without asking.\n\n| Agent | Modes (flag) |\n|-------|--------------|\n| Claude | `ask` (none) · `autoEdit` (`--permission-mode acceptEdits`) · `full` (`--dangerously-skip-permissions`) |\n| Codex | `safe` (`-s read-only`) · `auto` (`--full-auto`) · `full` (`--dangerously-bypass-approvals-and-sandbox`) |\n| Antigravity | `safe` (`--sandbox`) · `full` (`--yolo`) |\n\n\u003e ⚠️ Full-auto modes let the agent change files and run commands without\n\u003e prompting. Use them only on trusted projects over your private tailnet.\n\n## How it works\n\n```\n[ iPhone Safari ]                         [ your Mac ]\n  mic ─Web Speech STT─▶ text ──https/Tailscale──▶ voicebridge ──spawn──▶ claude / codex / agy\n  speaker ◀─speechSynthesis── reply ◀──────────── reply  ◀──────────────  (coding agent CLI)\n```\n\n- Each session maps to one agent + project dir. Claude keeps a rolling\n  conversation (`--continue`); **Yeni sohbet** resets it.\n- For Claude the prompt is passed as a separate argv (no shell); for Codex and\n  Antigravity it's piped on **stdin** — both injection-safe.\n\n## Development\n\n```bash\nnpm test       # zero-dependency test suite (node:test): adapters, parser,\n               # session registry, streaming, modes, runners, push, and auth.\nnpm run smoke  # end-to-end HTTP smoke test against a stub agent (no real CLI)\n```\n\n### Try it locally without a real agent\n\nYou don't need an agent CLI to see the bridge work end to end — point a `*_BIN`\nenv var at a stub that emits the expected output:\n\n```bash\nprintf '#!/usr/bin/env node\\nprocess.stdout.write(JSON.stringify({type:\"assistant\",message:{content:[{type:\"text\",text:\"hello from the stub.\"}]}})+\"\\\\n\");\\n' \u003e /tmp/claude\nchmod +x /tmp/claude\nCLAUDE_BIN=/tmp/claude npm start   # open the printed URL, type or speak\n```\n\n## Security notes\n\n- The server binds to `127.0.0.1` and is only reachable through your **Tailscale**\n  tailnet — it is not exposed to the public internet.\n- iOS speech **recognition** streams audio to Apple for transcription (free, but\n  not local). Speech **synthesis** is fully on-device. If you need fully-local\n  STT too, swap the browser recognizer for a local Whisper endpoint (see ideas\n  below).\n- Anyone on your tailnet who opens the URL can drive an agent in a session's\n  project directory (and create sessions pointing at other directories). Keep\n  your tailnet private and set `ACCESS_TOKEN`.\n\n## Troubleshooting\n\n| Symptom | Fix |\n|---------|-----|\n| Mic does nothing / \"https required\" | Web Speech needs HTTPS — open the `tailscale serve` URL, not `http://…`. |\n| Mic button is **greyed out / disabled** on mobile | You're on a non-HTTPS origin (e.g. `http://\u003clan-ip\u003e`). Open the `https://…ts.net` URL instead. See [mobile voice setup](docs/mobile-voice-setup.md). |\n| `Serve is not enabled on your tailnet` | One-time: open the printed `login.tailscale.com/f/serve?node=…` link and enable Serve in the admin console. |\n| iOS mic doesn't work | Use the Safari **tab**, not an installed PWA (iOS blocks the mic in installed PWAs). |\n| \"Could not find 'claude'…\" | Set `CLAUDE_BIN` to the agent's path (`which claude`) and make sure it's logged in. |\n| 401 / keeps asking for a token | `ACCESS_TOKEN` is set — enter it once on the phone, or scan the QR (it carries the token). |\n| Replies don't speak | TTS is unlocked on your first tap (mic/send) — interact once, then replies speak. Still silent? Check the voice/rate options and that the device isn't on silent. |\n| Mic indicator stays on when idle | The recognizer is released on pause/mute/exit, when hands-free is off, and when the tab is backgrounded. iOS may show the dot for a second after release; if it persists, turn **Eller serbest** off (it listens between turns by design). |\n| No notifications | Enable **Bildirim** and allow the permission; real push needs VAPID keys (see configuration). |\n\n## Security checklist\n\n- [ ] Reach the bridge only over **Tailscale** (keep `HOST=127.0.0.1`); never expose it publicly.\n- [ ] Set `ACCESS_TOKEN` (required if it's reachable beyond localhost — the bridge warns otherwise).\n- [ ] Use read-only / ask **modes** on unfamiliar repos; reserve full-auto for trusted projects.\n- [ ] Keep your tailnet private; anyone on it who has the URL + token can drive an agent.\n\nDetails in [docs/security.md](docs/security.md).\n\n## Documentation\n\n- [docs/mobile-voice-setup.md](docs/mobile-voice-setup.md) — get the mic working on your phone (HTTPS + Tailscale, step by step).\n- [docs/architecture.md](docs/architecture.md) — components, request flow, and the agent-adapter design.\n- [docs/configuration.md](docs/configuration.md) — full env-var reference, agents, and modes.\n- [docs/security.md](docs/security.md) — threat model, the access token, Tailscale, and full-auto risks.\n- [CONTRIBUTING.md](CONTRIBUTING.md) — dev setup, tests, and how to add an agent.\n- [CHANGELOG.md](CHANGELOG.md) — release notes.\n\n## Roadmap\n\n- Fully-local STT: stream mic audio over WebSocket to a local `whisper.cpp`\n  server instead of the browser recognizer.\n- Per-agent conversation continuity for Codex / Antigravity (resume support).\n- A real screen recording to sit beside the UI illustration.\n- ✅ Streaming replies, a Stop button, multiple agents, multiple sessions, a\n  type-or-speak chat UI, per-agent autonomy modes, and a startup QR code.\n\n## License\n\n**[PolyForm Noncommercial License 1.0.0](LICENSE)** — free to use, modify, and\nshare for any **noncommercial** purpose (personal, research, education,\nnonprofit). **Commercial use is not permitted**, and the required copyright\nnotice (`Copyright (c) 2026 Berkay Turancı`) must be kept on copies. Want to use\nvoicebridge commercially? Contact the author for a separate license.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fberkayturanci%2Fvoicebridge","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fberkayturanci%2Fvoicebridge","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fberkayturanci%2Fvoicebridge/lists"}