Configure the public webhook endpoint for Cyrus — ngrok, Cloudflare Tunnel, or custom URL.
CRITICAL: Never use Read, Edit, or Write tools on ~/.cyrus/.env or any file inside ~/.cyrus/. Use only Bash commands (grep, printf >>, etc.) to interact with env files — secrets must never be read into the conversation context.
Configures a public URL so Linear (and other integrations) can send webhooks to your Cyrus instance.
grep -E '^CYRUS_BASE_URL=' ~/.cyrus/.env 2>/dev/null
If CYRUS_BASE_URL is already set, inform the user:
Webhook endpoint already configured:
<value>To reconfigure, remove from and re-run this skill.
CYRUS_BASE_URL~/.cyrus/.envSkip to Step 4 (write port/webhooks if missing).
Ask the user:
How will you expose Cyrus to the internet for webhooks?
- ngrok (recommended — every free account includes one static domain that persists across restarts)
- Cloudflare Tunnel (permanent, requires Cloudflare account)
- Own URL (you already have a public URL/domain)
Important: ngrok's free tier includes a permanent static domain — do NOT tell the user this is a paid feature or that URLs change on restart. Every free ngrok account gets one static domain at https://dashboard.ngrok.com/domains.
which ngrok
If not installed, provide install instructions:
macOS:
brew install ngrok
Linux:
curl -sSL https://ngrok-agent.s3.amazonaws.com/ngrok-v3-stable-linux-amd64.tgz | sudo tar xvz -C /usr/local/bin
Instruct the user:
ngrok provides a free static domain so your URL doesn't change between restarts.
- Sign up or log in at https://dashboard.ngrok.com
- Go to https://dashboard.ngrok.com/domains
- Copy your free static domain (e.g.,
your-name-here.ngrok-free.app)- Go to https://dashboard.ngrok.com/get-started/your-authtoken and copy your authtoken
Ask the user to provide:
CRITICAL: The authtoken is a secret. Use clipboard-to-file commands.
Write the ngrok config so it can be started with ngrok start cyrus:
mkdir -p ~/.config/ngrok
Then write ~/.config/ngrok/ngrok.yml (merge with existing if present):