/cyrus-setup-endpoint
Configure the public webhook endpoint for Cyrus — ngrok, Cloudflare Tunnel, or custom URL.
$ npx -y skills add cyrusagents/cyrus --skill cyrus-setup-endpoint --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/cyrus-setup-endpoint
Context preview
The summary Claude sees to decide when to auto-load this skill.
Configure the public webhook endpoint for Cyrus — ngrok, Cloudflare Tunnel, or custom URL.
SKILL.md
cyrus-setup-endpoint.SKILL.mdname: cyrus-setup-endpoint
description: 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.**
Setup Endpoint
Configures a public URL so Linear (and other integrations) can send webhooks to your Cyrus instance.
Step 1: Check Existing Configuration
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 `CYRUS_BASE_URL` from `~/.cyrus/.env` and re-run this skill.
Skip to Step 4 (write port/webhooks if missing).
Step 2: Choose Endpoint Method
Ask the user:
> **How will you expose Cyrus to the internet for webhooks?** > > 1. **ngrok** (recommended — every free account includes one static domain that persists across restarts) > 2. **Cloudflare Tunnel** (permanent, requires Cloudflare account) > 3. **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.
Step 3: Configure Endpoint
Option 1: ngrok
3a. Check if ngrok is installed
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
3b. Guide ngrok domain setup
Instruct the user:
> ngrok provides a free static domain so your URL doesn't change between restarts. > > 1. Sign up or log in at https://dashboard.ngrok.com > 2. Go to https://dashboard.ngrok.com/domains > 3. Copy your free static domain (e.g., `your-name-here.ngrok-free.app`) > 4. Go to https://dashboard.ngrok.com/get-started/your-authtoken and copy your authtoken
Ask the user to provide:
- Their ngrok domain
- Their ngrok authtoken
**CRITICAL: The authtoken is a secret. Use clipboard-to-file commands.**
3c. Write ngrok configuration
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):
version: 3
agent:
authtoken: <token>
endpoints:
- name: cyrus
url: <domain>
upstream:
url: 3456For the authtoken, use a clipboard-to-file approach:
**macOS:**
# User copies authtoken, then runs:
NGROK_TOKEN=$(pbpaste) && cat > ~/.config/ngrok/ngrok.yml << EOF
version: 3
agent:
authtoken: $NGROK_TOKEN
endpoints:
- name: cyrus
url: <domain>
upstream:
url: 3456
EOF**Universal fallback:**
read -s -p "Paste your ngrok authtoken: " NGROK_TOKEN && cat > ~/.config/ngrok/ngrok.yml << EOF
version: 3
agent:
authtoken: $NGROK_TOKEN
endpoints:
- name: cyrus
url: <domain>
upstream:
url: 3456
EOF
echo " ✓ Saved"3d. Write CYRUS_BASE_URL
printf 'CYRUS_BASE_URL=https://%s\n' "<domain>" >> ~/.cyrus/.env
Where `<domain>` is the ngrok domain the user provided (e.g., `your-name-here.ngrok-free.app`).
Inform the user:
> To start ngrok, run: `ngrok start cyrus` > Run this in a separate terminal before starting Cyrus.
Option 2: Cloudflare Tunnel
Ask the user for:
- Their Cloudflare Tunnel token
- Their tunnel hostname (e.g., `cyrus.yourdomain.com`)
**Token is a secret — use clipboard-to-env:**
**macOS:**
printf 'CLOUDFLARE_TOKEN=%s\n' "$(pbpaste)" >> ~/.cyrus/.env
**Universal fallback:**
read -s -p "Paste your Cloudflare token: " val && printf 'CLOUDFLARE_TOKEN=%s\n' "$val" >> ~/.cyrus/.env && echo " ✓ Saved"
Then write the base URL (not a secret — agent can write directly):
printf 'CYRUS_BASE_URL=https://<hostname>\n' >> ~/.cyrus/.env
Option 3: Own URL
Ask the user for their URL. Validate it starts with `https://`.
printf 'CYRUS_BASE_URL=%s\n' "<url>" >> ~/.cyrus/.env
Step 4: Write Common Config
Ensure these are present in `~/.cyrus/.env` (add only if missing):
grep -q '^CYRUS_SERVER_PORT=' ~/.cyrus/.env 2>/dev/null || printf 'CYRUS_SERVER_PORT=3456\n' >> ~/.cyrus/.env
grep -q '^LINEAR_DIRECT_WEBHOOKS=' ~/.cyrus/.env 2>/dev/null || printf 'LINEAR_DIRECT_WEBHOOKS=true\n' >> ~/.cyrus/.env
grep -q '^CYRUS_HOST_EXTERNAL=' ~/.cyrus/.env 2>/dev/null || printf 'CYRUS_HOST_EXTERNAL=true\n' >> ~/.cyrus/.env
`LINEAR_DIRECT_WEBHOOKS=true` enables direct Linear webhook signature verification. `CYRUS_HOST_EXTERNAL=true` enables direct Slack and GitHub webhook signature verification. Both are required for self-hosted setups where webhooks come directly from the services (not forwarded through CYHOST).
Completion
> ✓ Webhook endpoint configured: `<CYRUS_BASE_URL>` > ✓ Server port: 3456 > ✓ Direct webhooks: enabled
Read more
name: cyrus-setup-endpoint description: 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.**
Setup Endpoint
Configures a public URL so Linear (and other integrations) can send webhooks to your Cyrus instance.
Step 1: Check Existing Configuration
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 `CYRUS_BASE_URL` from `~/.cyrus/.env` and re-run this skill.
Skip to Step 4 (write port/webhooks if missing).
Step 2: Choose Endpoint Method
Ask the user:
> **How will you expose Cyrus to the internet for webhooks?** > > 1. **ngrok** (recommended — every free account includes one static domain that persists across restarts) > 2. **Cloudflare Tunnel** (permanent, requires Cloudflare account) > 3. **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.
Step 3: Configure Endpoint
Option 1: ngrok
3a. Check if ngrok is installed
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
3b. Guide ngrok domain setup
Instruct the user:
> ngrok provides a free static domain so your URL doesn't change between restarts. > > 1. Sign up or log in at https://dashboard.ngrok.com > 2. Go to https://dashboard.ngrok.com/domains > 3. Copy your free static domain (e.g., `your-name-here.ngrok-free.app`) > 4. Go to https://dashboard.ngrok.com/get-started/your-authtoken and copy your authtoken
Ask the user to provide:
- Their ngrok domain
- Their ngrok authtoken
**CRITICAL: The authtoken is a secret. Use clipboard-to-file commands.**
3c. Write ngrok configuration
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):
version: 3
agent:
authtoken: <token>
endpoints:
- name: cyrus
url: <domain>
upstream:
url: 3456For the authtoken, use a clipboard-to-file approach:
**macOS:**
# User copies authtoken, then runs:
NGROK_TOKEN=$(pbpaste) && cat > ~/.config/ngrok/ngrok.yml << EOF
version: 3
agent:
authtoken: $NGROK_TOKEN
endpoints:
- name: cyrus
url: <domain>
upstream:
url: 3456
EOF**Universal fallback:**
read -s -p "Paste your ngrok authtoken: " NGROK_TOKEN && cat > ~/.config/ngrok/ngrok.yml << EOF
version: 3
agent:
authtoken: $NGROK_TOKEN
endpoints:
- name: cyrus
url: <domain>
upstream:
url: 3456
EOF
echo " ✓ Saved"3d. Write CYRUS_BASE_URL
printf 'CYRUS_BASE_URL=https://%s\n' "<domain>" >> ~/.cyrus/.env
Where `<domain>` is the ngrok domain the user provided (e.g., `your-name-here.ngrok-free.app`).
Inform the user:
> To start ngrok, run: `ngrok start cyrus` > Run this in a separate terminal before starting Cyrus.
Option 2: Cloudflare Tunnel
Ask the user for:
- Their Cloudflare Tunnel token
- Their tunnel hostname (e.g., `cyrus.yourdomain.com`)
**Token is a secret — use clipboard-to-env:**
**macOS:**
printf 'CLOUDFLARE_TOKEN=%s\n' "$(pbpaste)" >> ~/.cyrus/.env
**Universal fallback:**
read -s -p "Paste your Cloudflare token: " val && printf 'CLOUDFLARE_TOKEN=%s\n' "$val" >> ~/.cyrus/.env && echo " ✓ Saved"
Then write the base URL (not a secret — agent can write directly):
printf 'CYRUS_BASE_URL=https://<hostname>\n' >> ~/.cyrus/.env
Option 3: Own URL
Ask the user for their URL. Validate it starts with `https://`.
printf 'CYRUS_BASE_URL=%s\n' "<url>" >> ~/.cyrus/.env
Step 4: Write Common Config
Ensure these are present in `~/.cyrus/.env` (add only if missing):
grep -q '^CYRUS_SERVER_PORT=' ~/.cyrus/.env 2>/dev/null || printf 'CYRUS_SERVER_PORT=3456\n' >> ~/.cyrus/.env grep -q '^LINEAR_DIRECT_WEBHOOKS=' ~/.cyrus/.env 2>/dev/null || printf 'LINEAR_DIRECT_WEBHOOKS=true\n' >> ~/.cyrus/.env grep -q '^CYRUS_HOST_EXTERNAL=' ~/.cyrus/.env 2>/dev/null || printf 'CYRUS_HOST_EXTERNAL=true\n' >> ~/.cyrus/.env
`LINEAR_DIRECT_WEBHOOKS=true` enables direct Linear webhook signature verification. `CYRUS_HOST_EXTERNAL=true` enables direct Slack and GitHub webhook signature verification. Both are required for self-hosted setups where webhooks come directly from the services (not forwarded through CYHOST).
Completion
> ✓ Webhook endpoint configured: `<CYRUS_BASE_URL>` > ✓ Server port: 3456 > ✓ Direct webhooks: enabled
Your (Claude Code|Codex|Cursor|Gemini) powered (Linear|GitHub|GitLab|Slack) agent.
Repo: cyrusagents/cyrus
Other skills on cyrus.
- /google
Search the web for information. Use when you need to look something up, find current information, or research a topic.
Open skill - /release-core-test
Invoke when dev-testing a Cyrus change that spans CYPACK (edgeworker + CLI) and CYHOST (Vercel-hosted GUI) and the hosted GUI needs to point at an unreleased `cyrus-core` from this repo. Publishes `cyrus-core` (and `claude-runner` if needed) as a `-test.N` prerelease under the
Open skill - /cyrus-setup-claude-auth
Configure Claude Code authentication for Cyrus — API key, OAuth token, or third-party provider.
Open skill - /cyrus-setup-github
Configure GitHub for Cyrus — gh CLI login and git config for PRs, with optional webhook setup to enable @mention responses in PR comments, automated rebases and merges, and auto-fixing based on CI failures (coming soon).
Open skill - /cyrus-setup-gitlab
Configure GitLab authentication for Cyrus — glab CLI login and git config for creating merge requests.
Open skill - /cyrus-setup-launch
Print a summary of the Cyrus setup and offer to start the agent.
Open skill

