signing
Message signing and verification — SIP-018 structured Clarity data signing (on-chain verifiable), Stacks plain-text message signing (SIWS-compatible), Bitcoin message signing (BIP-137 for legacy/wrapped-SegWit, BIP-322 for native SegWit bc1q and Taproot bc1p), BIP-340 Schnorr signing for Taproot multisig, and Nostr event signing using NIP-06 key derivation. All signing requires an unlocked wallet; hash and verify operations do not.
What this skill does
# Signing Skill
Provides cryptographic message signing for the Stacks and Bitcoin ecosystems. Four signing standards are supported:
- **SIP-018** — Structured Clarity data signing. Signatures are verifiable both off-chain and by on-chain smart contracts via `secp256k1-recover?`.
- **Stacks messages** — SIWS-compatible plain-text signing. Used for wallet authentication and proving address ownership.
- **Bitcoin messages** — BIP-137/BIP-322 hybrid. BIP-137 for legacy (1...) and wrapped SegWit (3...) addresses; BIP-322 "simple" for native SegWit (bc1q) and Taproot (bc1p) addresses. Compatible with Electrum, Bitcoin Core, and modern wallets.
- **Schnorr (BIP-340)** — Taproot-native signing over raw 32-byte digests. Used for Taproot script-path spending, multisig coordination, and OP_CHECKSIGADD witness assembly.
- **Nostr events (NIP-06)** — Sign Nostr event objects using the NIP-06 derived key (`m/44'/1237'/0'/0/0`) by default, or from a wallet key path via `keySource`.
## Usage
```
bun run signing/signing.ts <subcommand> [options]
```
## Subcommands
### sip018-sign
Sign structured Clarity data using the SIP-018 standard. The domain binding (name + version + chain-id) prevents cross-app and cross-chain replay attacks. Requires an unlocked wallet.
```
bun run signing/signing.ts sip018-sign \
--message '{"amount":{"type":"uint","value":100}}' \
--domain-name "My App" \
--domain-version "1.0.0"
```
Options:
- `--message` (required) — Structured data as a JSON string. Use type hints for explicit Clarity types:
- `{"type":"uint","value":100}` → `uint`
- `{"type":"int","value":-50}` → `int`
- `{"type":"principal","value":"SP..."}` → `principal`
- `{"type":"ascii","value":"hello"}` → `string-ascii`
- `{"type":"utf8","value":"hello"}` → `string-utf8`
- `{"type":"buff","value":"0x1234"}` → `buff`
- `{"type":"bool","value":true}` → `bool`
- `{"type":"none"}` → `none`
- `{"type":"some","value":...}` → `(some ...)`
- `{"type":"list","value":[...]}` → `list`
- `{"type":"tuple","value":{...}}` → `tuple`
- Implicit: `string → string-utf8`, `number → int`, `boolean → bool`, `null → none`
- `--domain-name` + `--domain-version` (required together) — Flat CLI domain fields
- `--domain` (alternative) — MCP-style JSON object: `{"name":"My App","version":"1.0.0"}` (optional `chainId`)
Output:
```json
{
"success": true,
"signature": "abc123...",
"signatureFormat": "RSV (65 bytes hex)",
"signer": "SP...",
"network": "testnet",
"chainId": 2147483648,
"hashes": {
"message": "...",
"domain": "...",
"encoded": "...",
"verification": "...",
"prefix": "0x534950303138"
},
"domain": { "name": "My App", "version": "1.0.0", "chainId": 2147483648 },
"verificationNote": "Use sip018-verify with the 'verification' hash..."
}
```
### sip018-verify
Verify a SIP-018 signature and recover the signer's Stacks address. Provide the `verification` hash from `sip018-sign` or `sip018-hash`.
```
bun run signing/signing.ts sip018-verify \
--message-hash <verificationHash> \
--signature <rsv65BytesHex> \
[--expected-signer <address>]
```
Options:
- `--message-hash` (required) — The SIP-018 verification hash (from `sip018-sign`/`sip018-hash`)
- `--signature` (required) — Signature in RSV format (65 bytes hex)
- `--expected-signer` (optional) — Expected signer address to verify against
Output:
```json
{
"success": true,
"recoveredPublicKey": "03...",
"recoveredAddress": "SP...",
"network": "testnet",
"verification": {
"expectedSigner": "SP...",
"isValid": true,
"message": "Signature is valid for the expected signer"
}
}
```
### sip018-hash
Compute the SIP-018 message hash without signing. Returns all hash components needed for off-chain or on-chain verification. Does not require an unlocked wallet.
```
bun run signing/signing.ts sip018-hash \
--message '{"amount":{"type":"uint","value":100}}' \
--domain-name "My App" \
--domain-version "1.0.0" \
[--chain-id <id>]
```
Options:
- `--message` (required) — Structured data as a JSON string (same format as sip018-sign)
- `--domain-name` + `--domain-version` (required together) — Flat CLI domain fields
- `--domain` (alternative) — MCP-style JSON object: `{"name":"My App","version":"1.0.0"}` (optional `chainId`)
- `--chain-id` (optional) — Chain ID override (takes precedence over `domain.chainId`)
Output:
```json
{
"success": true,
"hashes": {
"message": "...",
"domain": "...",
"encoded": "...",
"verification": "..."
},
"hashConstruction": {
"prefix": "0x534950303138",
"formula": "verification = sha256(prefix || domainHash || messageHash)"
},
"domain": { "name": "My App", "version": "1.0.0", "chainId": 2147483648 },
"clarityVerification": {
"example": "(secp256k1-recover? (sha256 encoded-data) signature)"
}
}
```
### stacks-sign
Sign a plain text message using the Stacks message signing format. The message is prefixed with `\x17Stacks Signed Message:\n` before hashing (SIWS-compatible). Requires an unlocked wallet.
```
bun run signing/signing.ts stacks-sign --message "Hello, Stacks!"
```
Options:
- `--message` (required) — Plain text message to sign
Output:
```json
{
"success": true,
"signature": "abc123...",
"signatureFormat": "RSV (65 bytes hex)",
"signer": "SP...",
"network": "testnet",
"message": {
"original": "Hello, Stacks!",
"prefix": "\u0017Stacks Signed Message:\n",
"prefixHex": "...",
"hash": "..."
},
"verificationNote": "Use stacks-verify with the original message and signature to verify."
}
```
### stacks-verify
Verify a Stacks message signature and recover the signer's Stacks address. Compatible with SIWS authentication flows.
```
bun run signing/signing.ts stacks-verify \
--message "Hello, Stacks!" \
--signature <rsv65BytesHex> \
[--expected-signer <address>]
```
Options:
- `--message` (required) — The original plain text message that was signed
- `--signature` (required) — Signature in RSV format (65 bytes hex)
- `--expected-signer` (optional) — Expected signer Stacks address
Output:
```json
{
"success": true,
"signatureValid": true,
"recoveredPublicKey": "03...",
"recoveredAddress": "SP...",
"network": "testnet",
"message": {
"original": "Hello, Stacks!",
"prefix": "\u0017Stacks Signed Message:\n",
"hash": "..."
},
"verification": {
"expectedSigner": "SP...",
"signerMatches": true,
"isFullyValid": true,
"message": "Signature is valid and matches expected signer"
}
}
```
### btc-sign
Sign a plain text message using Bitcoin message signing. Automatically selects the signing format based on address type: BIP-137 (65-byte compact signature) for legacy (1...) and wrapped SegWit (3...) addresses; BIP-322 "simple" (witness-serialized) for native SegWit (bc1q) and Taproot (bc1p) addresses. Compatible with Electrum, Bitcoin Core, and modern wallets. Requires an unlocked wallet with Bitcoin keys.
```
bun run signing/signing.ts btc-sign --message "Hello, Bitcoin!"
```
Options:
- `--message` (required) — Plain text message to sign
Output:
```json
{
"success": true,
"signature": "abc123...",
"signatureBase64": "...",
"signatureFormat": "BIP-137 (65 bytes: 1 header + 32 r + 32 s)",
"signer": "bc1q...",
"network": "mainnet",
"addressType": "P2WPKH (native SegWit)",
"message": {
"original": "Hello, Bitcoin!",
"prefix": "\u0018Bitcoin Signed Message:\n",
"prefixHex": "...",
"formattedHex": "...",
"hash": "..."
},
"header": { "value": 39, "recoveryId": 0, "addressType": "P2WPKH (native SegWit)" },
"verificationNote": "Use btc-verify with the original message and signature to verify."
}
```
### btc-verify
Verify a Bitcoin message signature (BIP-137 or BIP-322) and recover the signer's Bitcoin address. Automatically detects the format: BIP-137 (65-byte compact, hex 130 chars or base64 88 chars) for legacy/wrapped-SegWit addresses, and BIP-322 "simple" (wiRelated in Data & Analytics
clawarr-suite
IncludedComprehensive management for self-hosted media stacks (Sonarr, Radarr, Lidarr, Readarr, Prowlarr, Bazarr, Overseerr, Plex, Tautulli, SABnzbd, Recyclarr, Unpackerr, Notifiarr, Maintainerr, Kometa, FlareSolverr). Deep library exploration, analytics, dashboard generation, content management, request handling, subtitle management, indexer control, download monitoring, quality profile sync, library cleanup automation, notification routing, collection/overlay management, and media tracker integration (Trakt, Letterboxd, Simkl).
querying-soql
IncludedSOQL query generation, optimization, and analysis with 100-point scoring. Use this skill when the user needs SOQL/SOSL authoring or optimization: natural-language-to-query generation, relationship queries, aggregates, query-plan analysis, and performance or safety improvements for Salesforce queries. TRIGGER when: user writes, optimizes, or debugs SOQL/SOSL queries, touches .soql files, or asks about relationship queries, aggregates, or query performance. DO NOT TRIGGER when: bulk data operations (use handling-sf-data), Apex DML logic (use generating-apex), or report/dashboard queries.
app-store-optimization
IncludedApp Store Optimization (ASO) toolkit for researching keywords, analyzing competitor rankings, generating metadata suggestions, and improving app visibility on Apple App Store and Google Play Store. Use when the user asks about ASO, app store rankings, app metadata, app titles and descriptions, app store listings, app visibility, or mobile app marketing on iOS or Android. Supports keyword research and scoring, competitor keyword analysis, metadata optimization, A/B test planning, launch checklists, and tracking ranking changes.
habit-flow
IncludedAI-powered atomic habit tracker with natural language logging, streak tracking, smart reminders, and coaching. Use for creating habits, logging completions naturally ("I meditated today"), viewing progress, and getting personalized coaching.
app-store-optimization
IncludedApp Store Optimization (ASO) toolkit for researching keywords, analyzing competitor rankings, generating metadata suggestions, and improving app visibility on Apple App Store and Google Play Store. Use when the user asks about ASO, app store rankings, app metadata, app titles and descriptions, app store listings, app visibility, or mobile app marketing on iOS or Android. Supports keyword research and scoring, competitor keyword analysis, metadata optimization, A/B test planning, launch checklists, and tracking ranking changes.
visualizing-data
IncludedBuilds dashboards, reports, and data-driven interfaces requiring charts, graphs, or visual analytics. Provides systematic framework for selecting appropriate visualizations based on data characteristics and analytical purpose. Includes 24+ visualization types organized by purpose (trends, comparisons, distributions, relationships, flows, hierarchies, geospatial), accessibility patterns (WCAG 2.1 AA compliance), colorblind-safe palettes, and performance optimization strategies. Use when creating visualizations, choosing chart types, displaying data graphically, or designing data interfaces.