Signal Deploy logo

Signal Deploy

Organization
nightly-labs
signal-deploy

Check and deploy Signal (the `remote-api` service in `remote/`) to production from a release tag. Use when asked to deploy, redeploy, update or roll back Signal, to check that a Signal deployment has all its secrets and no regressions, or when a release tag changes `remote/` or `packages/contracts/src/signal-protocol`.

Overview

Publishernightly-labs
Repositoryopenbot
Skill namesignal-deploy
Stars
521
Forks
81
Bundled files
1
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • 1 bundled files

    Scripts, templates, and references the model can read while it works. Files are read-only and never executed.

  • Open source

    Published by nightly-labs on GitHub. Read the source before you install it.

Installation

Install the Signal Deploy AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
    https://github.com/nightly-labs/openbot/tree/main/.agents/skills/signal-deploy
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/nightly-labs/openbot.git /tmp/openbot
mkdir -p .claude/skills
cp -r /tmp/openbot/.agents/skills/signal-deploy .claude/skills/signal-deploy
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable Signal Deploy in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads Signal Deploy on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so Signal Deploy is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

Signal deploy

Signal runs on sui-alexandria in the Compose project openbot-remote (/opt/openbot/remote). It has no database: a restart closes the signalling WebSockets and empties the in-memory rooms, routes and resume-token cache. Active WebRTC data channels stay up. coturn is a separate container.

docs/remote-session-deployment.md is the source for the staging, build and rollback commands. This skill adds the checks before and after them.

When to deploy

CI and the release workflow do not deploy Signal. For each release, find the running commit (step 1). When git diff --quiet <running> <tag> -- remote packages/contracts/src/signal-protocol finds changes, deploy Signal from the local tag before the tag is pushed. Compare with the running commit, not with the previous tag: an earlier release can have left Signal behind. The push starts the release workflow, which does not wait for Signal (docs/RELEASING.md, preflight item 16). Example: #1661. The v0.33.0 clients sent webhookRoute, but production Signal was older than #1520. It had no /v1/webhooks route and refused webhook-only ingress sockets with authentication_required.

Rules

  • Deploy only a release tag, from a detached worktree: git worktree add --detach <dir> <tag>. Do not check out the tag in a checkout that another agent uses.
  • Deploy Signal only. Do not run remote:update or remote:up: they also recreate coturn and end relay sessions. Change coturn only when the developer asks.
  • Never print, copy off the host, or log an environment value, .env.keys, a container environment, a token, a ticket or raw connection logs. Compare secrets by key name, or by a hash on the host.
  • The deploy reads the host files /opt/openbot/remote/.env.production and .env.keys through symlinks, not the remote/.env.production of the tag. The two files can differ.
  • Get explicit approval from the developer before each production change: the deploy, a change to the host environment file, and a change to the host Nginx configuration.

1. Find the running version

First read commit from the public health route:

sh
curl -fsS https://signal.openbot.run/health/live

If commit is missing (a build from before this field) or unknown (built without OPENBOT_SOURCE_COMMIT), find the commit by checksum:

sh
ssh sui-alexandria 'docker inspect openbot-remote-remote-api-1 --format "{{.Image}} {{.Created}} {{.State.Health.Status}}"'
ssh sui-alexandria 'docker exec openbot-remote-remote-api-1 sh -c "cd /app/remote/api/src && sha256sum *.ts"'
ssh sui-alexandria 'ls -t /opt/openbot/releases'

Each release directory has the full commit SHA as its name. Compare the container checksums with git show "${commit}:remote/api/src/<file>" | shasum -a 256 for the newest release directories and tags. In zsh, write "${commit}:remote/...": $commit:r is a modifier. Record the running commit.

2. Check for regressions

Diff the running commit against the tag:

sh
git diff --stat <running> <tag> -- remote packages/contracts/src/signal-protocol
git merge-base --is-ancestor <running> <tag>

If the running commit is not an ancestor of the tag, stop and report: the deploy would remove changes that are live now.

  • Protocol. In packages/contracts/src/signal-protocol, released messages and auth events must stay compatible. New message types and optional fields are safe; a removed or renamed field is not. A new hello field or a new public route that released clients use needs this Signal before those clients ship.
  • Account service. A new Signal call to the Worker (for example /v2/remote/<x>-route/...) must exist in the deployed Worker. An unauthenticated POST https://api.openbot.run/<path> gives 401 when the route exists and 404 when it does not.
  • remote/compose.yaml. A new variable with :? stops the start when the host file lacks it.
  • remote/api/Dockerfile. A new workspace package must be copied before bun install.
  • remote/nginx/signal.openbot.run.conf. The host uses its own copy at /etc/nginx/conf.d/openbot-remote.conf. A new location in the repository needs the same change on the host, after a backup, nginx -t and systemctl reload nginx. Without it, the request goes through location /, which has the default 1 MB body limit and writes the path to the access log.
  • Tests. In the tag worktree: bun install --frozen-lockfile, then bun run --cwd remote/api test.

3. Check the secrets

  1. Compare key names. Required keys are those that remote/compose.yaml marks with :?; optional keys turn a feature off when they are empty (Slack, Discord, Telegram).

    sh
    git show <tag>:remote/.env.production | grep -vE '^#|^$' | cut -d= -f1 | sort
    ssh sui-alexandria "grep -vE '^#|^$' /opt/openbot/remote/.env.production | cut -d= -f1 | sort"
  2. Make sure that DOTENV_PUBLIC_KEY_PRODUCTION is the same in both files. Then the host .env.keys decrypts the encrypted values of the tag file.

  3. For keys in both files, compare values by hash on the host: copy the encrypted tag file to a umask 077 temporary file, run bin/dotenvx get -f <file> -fk .env.keys for each file, and print only <key> same|DIFFERENT|only-in-tag|only-on-host. Delete the temporary files.

  4. Report each key that is only in the tag or that is different. The developer decides which value goes live. To add a key, copy its encrypted line from the tag file into the host file after cp .env.production .env.production.bak-<date>-<reason>. Do not replace the whole host file.

4. Deploy

Report the results of steps 1 to 3 and get approval. Then follow "Deployment procedure" in docs/remote-session-deployment.md with these changes:

  • Use git archive <tag> and the release directory /opt/openbot/releases/$(git rev-parse <tag>^{commit}). If the directory exists, do not write into it again.
  • Tag the running image as openbot-remote-api:before-<tag> before the build.
  • Build from the release directory. The document's build command passes its name, the tag commit, as --build-arg OPENBOT_SOURCE_COMMIT, and stops when the name is not a full commit SHA.
  • Run the Compose commands with -p openbot-remote, and build and start only remote-api.

5. Verify

  • docker inspect openbot-remote-remote-api-1 --format '{{.Image}} {{.State.Health.Status}}' shows the new image and healthy.
  • curl --fail https://signal.openbot.run/health/ready succeeds.
  • curl --fail https://signal.openbot.run/health/live shows commit equal to the tag commit (tags from before this field show no commit; use the checksums then).
  • The container sha256sum of /app/remote/api/src/*.ts matches the tag.
  • docker logs --since <deploy time> openbot-remote-remote-api-1 2>&1 | grep -iE 'error|disabled|off|telegram|discord|slack' shows no start errors, and shows each enabled feature. Do not print other log lines.
  • Unauthenticated probes of each public route that the diff adds give 401 or 403, not 404 or 502. For example, POST /v1/webhooks/x with content-type: application/json gives 401.

If a check fails, use the rollback commands of the deployment document with the before-<tag> image. Keep that image until the developer confirms the device checks of the deployment document.

Report

One table: running commit before and after (from /health/live, or from checksums), image IDs, each secret key status, each regression area, health, test result, and the checks that need a device or the developer.

Bundled files

The model reads these on demand while the skill is loaded. They are exposed as readable files and are never executed.

Frequently asked questions

What does the Signal Deploy AI skill do?

Check and deploy Signal (the `remote-api` service in `remote/`) to production from a release tag. Use when asked to deploy, redeploy, update or roll back Signal, to check that a Signal deployment has all its secrets and no regressions, or when a release tag changes `remote/` or `packages/contracts/src/signal-protocol`.

Why use Signal Deploy on TypingMind?

Because you install it once and use it with any model. Signal Deploy is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install Signal Deploy in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/nightly-labs/openbot/tree/main/.agents/skills/signal-deploy. TypingMind reads its SKILL.md and bundles its files and installs it as a skill you can enable per chat.

Which AI models can use Signal Deploy?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with Signal Deploy?

As many as you like. As long as a model supports skills, you can use Signal Deploy with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the Signal Deploy AI skill free?

It is published on GitHub by nightly-labs. Check the repository for licensing terms. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇