{"_id":"warelay","_rev":"11-25171be6b70597ce2341fd390f0737ba","name":"warelay","dist-tags":{"latest":"1.3.0"},"versions":{"0.1.0":{"name":"warelay","version":"0.1.0","keywords":[],"author":"","license":"MIT","_id":"warelay@0.1.0","maintainers":[{"name":"steipete","email":"steipete@gmail.com"}],"bin":{"wa":"dist/index.js","warely":"dist/index.js","warelay":"dist/index.js"},"dist":{"shasum":"a996df95fe6224fb1898c91481f688dc5e5829fe","tarball":"https://registry.npmjs.org/warelay/-/warelay-0.1.0.tgz","fileCount":140,"integrity":"sha512-ojmTHHbgLHfgBQdnymv9gcxUeAPrHvfYXx1tp5z8Bl+6umghYFpeJbrGWXWRbVqI0jmDHxKE8RPGpso+duktwQ==","signatures":[{"sig":"MEQCIGoU5eSoHc914HTySN595G7zM2ZExR5zoIYNva0kn9WvAiBswCNlmrH4ZekPsUeJQvsQ+9zUo4NSa6K6PrnKMrZROg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":362106},"main":"dist/index.js","type":"module","vitest":{"exclude":["dist/**"],"coverage":{"exclude":["src/**/*.test.ts"],"include":["src/**/*.ts"],"provider":"v8","reporter":["text","lcov"],"thresholds":{"lines":70,"branches":70,"functions":70,"statements":70}}},"engines":{"node":">=22.0.0"},"gitHead":"86b273657df48b976e695031e1ade42d93a7ca68","scripts":{"wa":"tsx src/index.ts","dev":"tsx src/index.ts","lint":"biome check src","test":"vitest","build":"tsc -p tsconfig.json","start":"tsx src/index.ts","format":"biome format src","warely":"tsx src/index.ts","warelay":"tsx src/index.ts","lint:fix":"biome check --write --unsafe src && biome format --write src","format:fix":"biome format src --write","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"steipete","email":"steipete@gmail.com"},"_npmVersion":"11.6.2","description":"WhatsApp relay CLI (send, monitor, webhook, auto-reply) using Twilio","directories":{},"_nodeVersion":"25.2.1","dependencies":{"zod":"^4.1.13","pino":"^10.1.0","chalk":"^5.6.2","json5":"^2.2.3","dotenv":"^17.2.3","twilio":"^5.10.6","express":"^5.1.0","commander":"^14.0.2","body-parser":"^2.2.1","qrcode-terminal":"^0.12.0","@whiskeysockets/baileys":"7.0.0-rc.9"},"_hasShrinkwrap":false,"packageManager":"pnpm@10.23.0","devDependencies":{"tsx":"^4.20.6","vitest":"^4.0.13","typescript":"^5.9.3","@types/node":"^24.10.1","@biomejs/biome":"^2.3.7","@types/express":"^5.0.5","@types/body-parser":"^1.19.6","@vitest/coverage-v8":"^4.0.13","@types/qrcode-terminal":"^0.12.2"},"_npmOperationalInternal":{"tmp":"tmp/warelay_0.1.0_1764073099075_0.3807893452289801","host":"s3://npm-registry-packages-npm-production"},"deprecated":"Deprecated: use clawdis instead."},"0.1.1":{"name":"warelay","version":"0.1.1","keywords":[],"author":"","license":"MIT","_id":"warelay@0.1.1","maintainers":[{"name":"steipete","email":"steipete@gmail.com"}],"bin":{"wa":"bin/warelay.js","warely":"bin/warelay.js","warelay":"bin/warelay.js"},"dist":{"shasum":"3960754898d37e3940d0fac557ee7772ffb45dcb","tarball":"https://registry.npmjs.org/warelay/-/warelay-0.1.1.tgz","fileCount":141,"integrity":"sha512-LXcNS2/7buYnfaGRJT99bQDCryW3OqPJ4SaGSoJ7K/QFTMpXm0ByHaCK4bQOrKsMpA07nOCSAQFyEazKq0Lvzg==","signatures":[{"sig":"MEUCIQCoZGLCyQpymlqKHaQ/fFc6LUzmwvlW0M1MrtMbXvIxcgIgTpAN8ai68amjfKoIybRl9ZpCyv2wKWYu3KxIres0z8c=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":367165},"main":"dist/index.js","type":"module","vitest":{"exclude":["dist/**"],"coverage":{"exclude":["src/**/*.test.ts"],"include":["src/**/*.ts"],"provider":"v8","reporter":["text","lcov"],"thresholds":{"lines":70,"branches":70,"functions":70,"statements":70}}},"engines":{"node":">=22.0.0"},"gitHead":"f083f4fcf9f6b264aab86cb8bfee0447328f0e66","scripts":{"wa":"tsx src/index.ts","dev":"tsx src/index.ts","lint":"biome check src","test":"vitest","build":"tsc -p tsconfig.json","start":"tsx src/index.ts","format":"biome format src","warely":"tsx src/index.ts","warelay":"tsx src/index.ts","lint:fix":"biome check --write --unsafe src && biome format --write src","format:fix":"biome format src --write","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"steipete","email":"steipete@gmail.com"},"_npmVersion":"11.6.2","description":"WhatsApp relay CLI (send, monitor, webhook, auto-reply) using Twilio","directories":{},"_nodeVersion":"25.2.1","dependencies":{"zod":"^4.1.13","pino":"^10.1.0","chalk":"^5.6.2","json5":"^2.2.3","dotenv":"^17.2.3","twilio":"^5.10.6","express":"^5.1.0","commander":"^14.0.2","body-parser":"^2.2.1","qrcode-terminal":"^0.12.0","@whiskeysockets/baileys":"7.0.0-rc.9"},"_hasShrinkwrap":false,"packageManager":"pnpm@10.23.0","devDependencies":{"tsx":"^4.20.6","vitest":"^4.0.13","typescript":"^5.9.3","@types/node":"^24.10.1","@biomejs/biome":"^2.3.7","@types/express":"^5.0.5","@types/body-parser":"^1.19.6","@vitest/coverage-v8":"^4.0.13","@types/qrcode-terminal":"^0.12.2"},"_npmOperationalInternal":{"tmp":"tmp/warelay_0.1.1_1764076452326_0.6222789435565399","host":"s3://npm-registry-packages-npm-production"},"deprecated":"Deprecated: use clawdis instead."},"0.1.2":{"name":"warelay","version":"0.1.2","keywords":[],"author":"","license":"MIT","_id":"warelay@0.1.2","maintainers":[{"name":"steipete","email":"steipete@gmail.com"}],"bin":{"wa":"bin/warelay.js","warely":"bin/warelay.js","warelay":"bin/warelay.js"},"dist":{"shasum":"e307d5edf5de707c248161fa83c87811218c683e","tarball":"https://registry.npmjs.org/warelay/-/warelay-0.1.2.tgz","fileCount":141,"integrity":"sha512-XhFHLCzCjXmWXwJW/5DFTzNzO/TxxsJUOoQk3lssAO6jxaXxId6xdW4nJrQD5h8Q/xT1cXtlk9MFP2sp2gEoPw==","signatures":[{"sig":"MEQCIGX4TMj7M43hi7kQgqfiSVIj8oo+GwGlbMFE5EOmFaWxAiBOKOArZ3oQvAR/WOfgtPDjvs0syN9MmkKeADvDGFf/9A==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":367442},"main":"dist/index.js","type":"module","vitest":{"exclude":["dist/**"],"coverage":{"exclude":["src/**/*.test.ts"],"include":["src/**/*.ts"],"provider":"v8","reporter":["text","lcov"],"thresholds":{"lines":70,"branches":70,"functions":70,"statements":70}}},"engines":{"node":">=22.0.0"},"gitHead":"38557f2b2b9213f8ccebe8dce1bfd8c196df3c15","scripts":{"wa":"tsx src/index.ts","dev":"tsx src/index.ts","lint":"biome check src","test":"vitest","build":"tsc -p tsconfig.json","start":"tsx src/index.ts","format":"biome format src","warely":"tsx src/index.ts","warelay":"tsx src/index.ts","lint:fix":"biome check --write --unsafe src && biome format --write src","format:fix":"biome format src --write","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"steipete","email":"steipete@gmail.com"},"_npmVersion":"11.6.2","description":"WhatsApp relay CLI (send, monitor, webhook, auto-reply) using Twilio","directories":{},"_nodeVersion":"25.2.1","dependencies":{"zod":"^4.1.13","pino":"^10.1.0","chalk":"^5.6.2","json5":"^2.2.3","dotenv":"^17.2.3","twilio":"^5.10.6","express":"^5.1.0","commander":"^14.0.2","body-parser":"^2.2.1","qrcode-terminal":"^0.12.0","@whiskeysockets/baileys":"7.0.0-rc.9"},"_hasShrinkwrap":false,"packageManager":"pnpm@10.23.0","devDependencies":{"tsx":"^4.20.6","vitest":"^4.0.13","typescript":"^5.9.3","@types/node":"^24.10.1","@biomejs/biome":"^2.3.7","@types/express":"^5.0.5","@types/body-parser":"^1.19.6","@vitest/coverage-v8":"^4.0.13","@types/qrcode-terminal":"^0.12.2"},"_npmOperationalInternal":{"tmp":"tmp/warelay_0.1.2_1764077251731_0.651745396288836","host":"s3://npm-registry-packages-npm-production"},"deprecated":"Deprecated: use clawdis instead."},"0.1.3":{"name":"warelay","version":"0.1.3","keywords":[],"author":"","license":"MIT","_id":"warelay@0.1.3","maintainers":[{"name":"steipete","email":"steipete@gmail.com"}],"bin":{"wa":"bin/warelay.js","warely":"bin/warelay.js","warelay":"bin/warelay.js"},"dist":{"shasum":"e4d063936dea232143809a382f2fa388ca040abd","tarball":"https://registry.npmjs.org/warelay/-/warelay-0.1.3.tgz","fileCount":144,"integrity":"sha512-zDoloBU9yYR9XUBZ6UYHjx+og7fOlz3bPCn90agdvDvj04U6H3dGtd1/FXPmoGl73nHorP9YDe9psNH9sT0zvQ==","signatures":[{"sig":"MEUCIQD43PeAJWIKEvpOba53fjwAjyXUADokYCaAG9RshYYm9QIgQdR6+bIaKHVQiezmonASZERjNduO8/OoejqICTV44PY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1795574},"main":"dist/index.js","type":"module","vitest":{"exclude":["dist/**"],"coverage":{"exclude":["src/**/*.test.ts"],"include":["src/**/*.ts"],"provider":"v8","reporter":["text","lcov"],"thresholds":{"lines":70,"branches":70,"functions":70,"statements":70}}},"engines":{"node":">=22.0.0"},"gitHead":"1f0e5ec59885995a0c094a8cdd49495a380c7ac4","scripts":{"wa":"tsx src/index.ts","dev":"tsx src/index.ts","lint":"biome check src","test":"vitest","build":"tsc -p tsconfig.json","start":"tsx src/index.ts","format":"biome format src","warely":"tsx src/index.ts","warelay":"tsx src/index.ts","lint:fix":"biome check --write --unsafe src && biome format --write src","format:fix":"biome format src --write","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"steipete","email":"steipete@gmail.com"},"_npmVersion":"11.6.2","description":"WhatsApp relay CLI (send, monitor, webhook, auto-reply) using Twilio","directories":{},"_nodeVersion":"25.2.1","dependencies":{"zod":"^4.1.13","pino":"^10.1.0","chalk":"^5.6.2","json5":"^2.2.3","dotenv":"^17.2.3","twilio":"^5.10.6","express":"^5.1.0","commander":"^14.0.2","body-parser":"^2.2.1","qrcode-terminal":"^0.12.0","@whiskeysockets/baileys":"7.0.0-rc.9"},"_hasShrinkwrap":false,"packageManager":"pnpm@10.23.0","devDependencies":{"tsx":"^4.20.6","vitest":"^4.0.13","typescript":"^5.9.3","@types/node":"^24.10.1","@biomejs/biome":"^2.3.7","@types/express":"^5.0.5","@types/body-parser":"^1.19.6","@vitest/coverage-v8":"^4.0.13","@types/qrcode-terminal":"^0.12.2"},"_npmOperationalInternal":{"tmp":"tmp/warelay_0.1.3_1764086044852_0.4668931793097719","host":"s3://npm-registry-packages-npm-production"},"deprecated":"Deprecated: use clawdis instead."},"1.0.4":{"name":"warelay","version":"1.0.4","keywords":[],"author":"","license":"MIT","_id":"warelay@1.0.4","maintainers":[{"name":"steipete","email":"steipete@gmail.com"}],"bin":{"wa":"bin/warelay.js","warely":"bin/warelay.js","warelay":"bin/warelay.js"},"dist":{"shasum":"270d09517a734d51ea400994182f24c222fbbb81","tarball":"https://registry.npmjs.org/warelay/-/warelay-1.0.4.tgz","fileCount":146,"integrity":"sha512-PgqxE6w/8z5fQkx96cMFdVrTh1f1brxelBQZCHdHXg3/82Gb6hx6VqkcDDK11NrOZiypoEYGxawXwGY6RCL3TQ==","signatures":[{"sig":"MEUCIQC3Dwk7khSrvvttDj4GwxY4E5h8r7H1be60BxDzi/VJMAIgdAxzeBECINuNsYXtMO09QUDaeGNhL2h5pLG4edmAeJg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1804916},"main":"dist/index.js","type":"module","_from":"file:warelay-1.0.4.tgz","vitest":{"exclude":["dist/**"],"coverage":{"exclude":["src/**/*.test.ts"],"include":["src/**/*.ts"],"provider":"v8","reporter":["text","lcov"],"thresholds":{"lines":70,"branches":70,"functions":70,"statements":70}}},"engines":{"node":">=22.0.0"},"scripts":{"wa":"tsx src/index.ts","dev":"tsx src/index.ts","lint":"biome check src","test":"vitest","build":"tsc -p tsconfig.json","start":"tsx src/index.ts","format":"biome format src","warely":"tsx src/index.ts","warelay":"tsx src/index.ts","lint:fix":"biome check --write --unsafe src && biome format --write src","format:fix":"biome format src --write","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"steipete","email":"steipete@gmail.com"},"_resolved":"/private/var/folders/qp/t4t5pw1n1279_1qckf4gqhyc0000gn/T/e44e589a392007ccc5e49cd2b3eda240/warelay-1.0.4.tgz","_integrity":"sha512-PgqxE6w/8z5fQkx96cMFdVrTh1f1brxelBQZCHdHXg3/82Gb6hx6VqkcDDK11NrOZiypoEYGxawXwGY6RCL3TQ==","_npmVersion":"11.6.2","description":"WhatsApp relay CLI (send, monitor, webhook, auto-reply) using Twilio","directories":{},"_nodeVersion":"25.2.1","dependencies":{"zod":"^4.1.13","pino":"^10.1.0","chalk":"^5.6.2","json5":"^2.2.3","dotenv":"^17.2.3","twilio":"^5.10.6","express":"^5.1.0","commander":"^14.0.2","body-parser":"^2.2.1","qrcode-terminal":"^0.12.0","@whiskeysockets/baileys":"7.0.0-rc.9"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.20.6","vitest":"^4.0.13","typescript":"^5.9.3","@types/node":"^24.10.1","@biomejs/biome":"^2.3.7","@types/express":"^5.0.5","@types/body-parser":"^1.19.6","@vitest/coverage-v8":"^4.0.13","@types/qrcode-terminal":"^0.12.2"},"_npmOperationalInternal":{"tmp":"tmp/warelay_1.0.4_1764090826112_0.8697524116746844","host":"s3://npm-registry-packages-npm-production"},"deprecated":"Deprecated: use clawdis instead."},"1.1.0":{"name":"warelay","version":"1.1.0","keywords":[],"author":"","license":"MIT","_id":"warelay@1.1.0","maintainers":[{"name":"steipete","email":"steipete@gmail.com"}],"bin":{"wa":"bin/warelay.js","warely":"bin/warelay.js","warelay":"bin/warelay.js"},"dist":{"shasum":"16357e1aa5239f1c7c9dc51bb9661abc8884f4cb","tarball":"https://registry.npmjs.org/warelay/-/warelay-1.1.0.tgz","fileCount":184,"integrity":"sha512-wTFQ7J6GmT7lxdwMo9arvzcAqYG4mqDJ7wroTB0y5nts359DJs1VVXHGwGROGAuH07dom9oW2RSKoL3TClZAAQ==","signatures":[{"sig":"MEUCIQCdBsduKKzz7pDXuzv19KQHct+YGFKYSsTf0pjFycar2QIgKST1serp5sCbP8a6dfNGAmWdRZpxdGyUOuAiUGHbSbk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1935536},"main":"dist/index.js","type":"module","vitest":{"exclude":["dist/**"],"coverage":{"exclude":["src/**/*.test.ts"],"include":["src/**/*.ts"],"provider":"v8","reporter":["text","lcov"],"thresholds":{"lines":70,"branches":70,"functions":70,"statements":70}}},"engines":{"node":">=22.0.0"},"gitHead":"e36a3e9f63c8186bf63eb26644204b90d4952e8d","scripts":{"wa":"tsx src/index.ts","dev":"tsx src/index.ts","lint":"biome check src","test":"vitest","build":"tsc -p tsconfig.json","start":"tsx src/index.ts","format":"biome format src","warely":"tsx src/index.ts","warelay":"tsx src/index.ts","lint:fix":"biome check --write --unsafe src && biome format --write src","format:fix":"biome format src --write","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"steipete","email":"steipete@gmail.com"},"_npmVersion":"11.6.2","description":"WhatsApp relay CLI (send, monitor, webhook, auto-reply) using Twilio","directories":{},"_nodeVersion":"25.2.1","dependencies":{"zod":"^4.1.13","pino":"^10.1.0","chalk":"^5.6.2","json5":"^2.2.3","sharp":"^0.33.5","dotenv":"^17.2.3","twilio":"^5.10.6","express":"^5.1.0","commander":"^14.0.2","body-parser":"^2.2.1","qrcode-terminal":"^0.12.0","@whiskeysockets/baileys":"7.0.0-rc.9"},"_hasShrinkwrap":false,"packageManager":"pnpm@10.23.0","devDependencies":{"tsx":"^4.20.6","vitest":"^4.0.13","typescript":"^5.9.3","@types/node":"^24.10.1","@biomejs/biome":"^2.3.7","@types/express":"^5.0.5","@types/body-parser":"^1.19.6","@vitest/coverage-v8":"^4.0.13","@types/qrcode-terminal":"^0.12.2"},"_npmOperationalInternal":{"tmp":"tmp/warelay_1.1.0_1764123500448_0.8090508013422295","host":"s3://npm-registry-packages-npm-production"},"deprecated":"Deprecated: use clawdis instead."},"1.2.0":{"name":"warelay","version":"1.2.0","keywords":[],"author":"","license":"MIT","_id":"warelay@1.2.0","maintainers":[{"name":"steipete","email":"steipete@gmail.com"}],"bin":{"wa":"bin/warelay.js","warely":"bin/warelay.js","warelay":"bin/warelay.js"},"dist":{"shasum":"e8c03584dd9f6abf2efda7d06f53771cee5b867b","tarball":"https://registry.npmjs.org/warelay/-/warelay-1.2.0.tgz","fileCount":187,"integrity":"sha512-1FJ7Ed7OfkZt9fB6p8mf+/X+8waG8B4Mvi+f1h+mMDzQy/MultESb6UiT1wNoLILvPjxxoJN71qqOq2SND6dTw==","signatures":[{"sig":"MEYCIQDyuAs+32p0FerIo27oa4CZd0s8ZtWHQcM3QQBrNsBemAIhAJ+wIJuJP7b3SGEu1xd3ZbinJI/NwNsCu4GspvBcIcL9","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2106093},"main":"dist/index.js","type":"module","vitest":{"exclude":["dist/**"],"coverage":{"exclude":["src/**/*.test.ts"],"include":["src/**/*.ts"],"provider":"v8","reporter":["text","lcov"],"thresholds":{"lines":70,"branches":70,"functions":70,"statements":70}}},"engines":{"node":">=22.0.0"},"gitHead":"6d7e620430d5fde50010e4b361bd19193dcb052f","scripts":{"wa":"tsx src/index.ts","dev":"tsx src/index.ts","lint":"biome check src","test":"vitest","build":"tsc -p tsconfig.json","start":"tsx src/index.ts","format":"biome format src","warely":"tsx src/index.ts","warelay":"tsx src/index.ts","lint:fix":"biome check --write --unsafe src && biome format --write src","format:fix":"biome format src --write","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"steipete","email":"steipete@gmail.com"},"_npmVersion":"11.6.2","description":"WhatsApp relay CLI (send, monitor, webhook, auto-reply) using Twilio","directories":{},"_nodeVersion":"25.2.1","dependencies":{"zod":"^4.1.13","pino":"^10.1.0","chalk":"^5.6.2","json5":"^2.2.3","sharp":"^0.33.5","dotenv":"^17.2.3","twilio":"^5.10.6","express":"^5.1.0","commander":"^14.0.2","body-parser":"^2.2.1","qrcode-terminal":"^0.12.0","@whiskeysockets/baileys":"7.0.0-rc.9"},"_hasShrinkwrap":false,"packageManager":"pnpm@10.23.0","devDependencies":{"tsx":"^4.20.6","vitest":"^4.0.13","typescript":"^5.9.3","@types/node":"^24.10.1","@biomejs/biome":"^2.3.7","@types/express":"^5.0.5","@types/body-parser":"^1.19.6","@vitest/coverage-v8":"^4.0.13","@types/qrcode-terminal":"^0.12.2"},"_npmOperationalInternal":{"tmp":"tmp/warelay_1.2.0_1764265974341_0.2695040219642515","host":"s3://npm-registry-packages-npm-production"},"deprecated":"Deprecated: use clawdis instead."},"1.2.1":{"name":"warelay","version":"1.2.1","keywords":[],"author":"","license":"MIT","_id":"warelay@1.2.1","maintainers":[{"name":"steipete","email":"steipete@gmail.com"}],"bin":{"wa":"bin/warelay.js","warely":"bin/warelay.js","warelay":"bin/warelay.js"},"dist":{"shasum":"84e4f0270a154123a5cec1e95b9e7835aa86b7d3","tarball":"https://registry.npmjs.org/warelay/-/warelay-1.2.1.tgz","fileCount":191,"integrity":"sha512-QijLWzBOs4dNCpDH4H5tH+62E4seDikkszO4ti+7Mh1qpjec5Zo80+tgWPu3ZsE/7zUl34FZqxDF7QC23PVgGQ==","signatures":[{"sig":"MEUCIQDIlotEo/yykIFGbZl4VTZYANBMiqYrMGTla5slk3f5WgIgUiqXqtr6gM0ze6Bb6YHbEDHEPM1neN871M6oy4ukLoQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2130560},"main":"dist/index.js","type":"module","vitest":{"exclude":["dist/**"],"coverage":{"exclude":["src/**/*.test.ts"],"include":["src/**/*.ts"],"provider":"v8","reporter":["text","lcov"],"thresholds":{"lines":70,"branches":70,"functions":70,"statements":70}}},"engines":{"node":">=22.0.0"},"gitHead":"c11abc11341b5896df78b05da4235c146f132800","scripts":{"wa":"tsx src/index.ts","dev":"tsx src/index.ts","lint":"biome check src","test":"vitest","build":"tsc -p tsconfig.json","start":"tsx src/index.ts","format":"biome format src","warely":"tsx src/index.ts","warelay":"tsx src/index.ts","lint:fix":"biome check --write --unsafe src && biome format --write src","format:fix":"biome format src --write","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"steipete","email":"steipete@gmail.com"},"_npmVersion":"11.6.2","description":"WhatsApp relay CLI (send, monitor, webhook, auto-reply) using Twilio","directories":{},"_nodeVersion":"25.2.1","dependencies":{"zod":"^4.1.13","pino":"^10.1.0","chalk":"^5.6.2","json5":"^2.2.3","sharp":"^0.33.5","dotenv":"^17.2.3","twilio":"^5.10.6","express":"^5.1.0","commander":"^14.0.2","body-parser":"^2.2.1","qrcode-terminal":"^0.12.0","@whiskeysockets/baileys":"7.0.0-rc.9"},"_hasShrinkwrap":false,"packageManager":"pnpm@10.23.0","devDependencies":{"tsx":"^4.20.6","vitest":"^4.0.13","typescript":"^5.9.3","@types/node":"^24.10.1","@biomejs/biome":"^2.3.7","@types/express":"^5.0.5","@types/body-parser":"^1.19.6","@vitest/coverage-v8":"^4.0.13","@types/qrcode-terminal":"^0.12.2"},"_npmOperationalInternal":{"tmp":"tmp/warelay_1.2.1_1764313883007_0.1972341059844327","host":"s3://npm-registry-packages-npm-production"},"deprecated":"Deprecated: use clawdis instead."},"1.2.2":{"name":"warelay","version":"1.2.2","keywords":[],"author":"","license":"MIT","_id":"warelay@1.2.2","maintainers":[{"name":"steipete","email":"steipete@gmail.com"}],"bin":{"wa":"bin/warelay.js","warely":"bin/warelay.js","warelay":"bin/warelay.js"},"dist":{"shasum":"2c05667199d87aed96adcf7665ab341f7cf8b953","tarball":"https://registry.npmjs.org/warelay/-/warelay-1.2.2.tgz","fileCount":193,"integrity":"sha512-re2LPs7g1UDOuitYtKE2LSDgSOFRdeZvWxmmlgwyDf5QUXEFGQOi4nXOTMMykhim0G4GgWctRI9VWncenlOZlQ==","signatures":[{"sig":"MEUCIF55Tq5dr68rUq9x/IzGqh7nXDHZRFTLYjU+weoTz3UFAiEAtmB/20OvgYTZj/Hhfk/QwKwSJ0p0dzGdTD66QK/m9Gs=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2138370},"main":"dist/index.js","type":"module","vitest":{"exclude":["dist/**"],"coverage":{"exclude":["src/**/*.test.ts"],"include":["src/**/*.ts"],"provider":"v8","reporter":["text","lcov"],"thresholds":{"lines":70,"branches":70,"functions":70,"statements":70}}},"engines":{"node":">=22.0.0"},"gitHead":"5bafe9483d11f96ea824c7d2b00f7507c1d6c7b9","scripts":{"wa":"tsx src/index.ts","dev":"tsx src/index.ts","lint":"biome check src","test":"vitest","build":"tsc -p tsconfig.json","start":"tsx src/index.ts","format":"biome format src","warely":"tsx src/index.ts","warelay":"tsx src/index.ts","lint:fix":"biome check --write --unsafe src && biome format --write src","format:fix":"biome format src --write","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"steipete","email":"steipete@gmail.com"},"_npmVersion":"11.6.2","description":"WhatsApp relay CLI (send, monitor, webhook, auto-reply) using Twilio","directories":{},"_nodeVersion":"25.2.1","dependencies":{"zod":"^4.1.13","pino":"^10.1.0","chalk":"^5.6.2","json5":"^2.2.3","sharp":"^0.33.5","dotenv":"^17.2.3","twilio":"^5.10.6","express":"^5.1.0","commander":"^14.0.2","body-parser":"^2.2.1","qrcode-terminal":"^0.12.0","@whiskeysockets/baileys":"7.0.0-rc.9"},"_hasShrinkwrap":false,"packageManager":"pnpm@10.23.0","devDependencies":{"tsx":"^4.20.6","vitest":"^4.0.13","typescript":"^5.9.3","@types/node":"^24.10.1","@biomejs/biome":"^2.3.7","@types/express":"^5.0.5","@types/body-parser":"^1.19.6","@vitest/coverage-v8":"^4.0.13","@types/qrcode-terminal":"^0.12.2"},"_npmOperationalInternal":{"tmp":"tmp/warelay_1.2.2_1764314264437_0.48322078443402505","host":"s3://npm-registry-packages-npm-production"},"deprecated":"Deprecated: use clawdis instead."},"1.3.0":{"name":"warelay","version":"1.3.0","keywords":[],"author":"","license":"MIT","_id":"warelay@1.3.0","maintainers":[{"name":"steipete","email":"steipete@gmail.com"}],"bin":{"wa":"bin/warelay.js","warely":"bin/warelay.js","warelay":"bin/warelay.js"},"dist":{"shasum":"466a9b039d26d72c18ccf13b624354f9fa7982b0","tarball":"https://registry.npmjs.org/warelay/-/warelay-1.3.0.tgz","fileCount":213,"integrity":"sha512-nazIHaAR5GsX6wCfo1iviDUzkzVyld3QU6i+e242xp4OgFiAIz/o+6grWF2H5LBtBM6Oa+lPJvRvn5PwEWbGHA==","signatures":[{"sig":"MEYCIQC/e9goZx9hIFwg1P+lFwd16zFJO2eTtWStmx1gBSkw3wIhAJI58HgW2Gox4Ty8nkZZoEvfHW+Y/ir5HOTg9xr1zSpR","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2260370},"main":"dist/index.js","type":"module","vitest":{"exclude":["dist/**"],"coverage":{"exclude":["src/**/*.test.ts"],"include":["src/**/*.ts"],"provider":"v8","reporter":["text","lcov"],"thresholds":{"lines":70,"branches":70,"functions":70,"statements":70}}},"engines":{"node":">=22.0.0"},"gitHead":"2b941ccc93d2cbc59d45b3408ee8baf441865e4f","scripts":{"wa":"tsx src/index.ts","dev":"tsx src/index.ts","lint":"biome check src","test":"vitest","build":"tsc -p tsconfig.json","start":"tsx src/index.ts","format":"biome format src","warely":"tsx src/index.ts","warelay":"tsx src/index.ts","lint:fix":"biome check --write --unsafe src && biome format --write src","format:fix":"biome format src --write","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"steipete","email":"steipete@gmail.com"},"_npmVersion":"11.6.2","description":"WhatsApp relay CLI (send, monitor, webhook, auto-reply) using Twilio","directories":{},"_nodeVersion":"25.2.1","dependencies":{"zod":"^4.1.13","pino":"^10.1.0","chalk":"^5.6.2","json5":"^2.2.3","sharp":"^0.33.5","dotenv":"^17.2.3","twilio":"^5.10.6","express":"^5.1.0","commander":"^14.0.2","body-parser":"^2.2.1","qrcode-terminal":"^0.12.0","@whiskeysockets/baileys":"7.0.0-rc.9"},"_hasShrinkwrap":false,"packageManager":"pnpm@10.23.0","devDependencies":{"tsx":"^4.20.6","vitest":"^4.0.13","typescript":"^5.9.3","@types/node":"^24.10.1","@biomejs/biome":"^2.3.7","@types/express":"^5.0.5","@types/body-parser":"^1.19.6","@vitest/coverage-v8":"^4.0.13","@types/qrcode-terminal":"^0.12.2"},"_npmOperationalInternal":{"tmp":"tmp/warelay_1.3.0_1764680209889_0.6466819293274473","host":"s3://npm-registry-packages-npm-production"},"deprecated":"Deprecated: use clawdis instead."}},"time":{"created":"2025-11-25T12:18:18.979Z","modified":"2025-12-19T17:33:59.897Z","0.1.0":"2025-11-25T12:18:19.283Z","0.1.1":"2025-11-25T13:14:12.515Z","0.1.2":"2025-11-25T13:27:31.912Z","0.1.3":"2025-11-25T15:54:05.091Z","1.0.4":"2025-11-25T17:13:46.351Z","1.1.0":"2025-11-26T02:18:20.695Z","1.2.0":"2025-11-27T17:52:54.561Z","1.2.1":"2025-11-28T07:11:23.285Z","1.2.2":"2025-11-28T07:17:44.683Z","1.3.0":"2025-12-02T12:56:50.114Z"},"license":"MIT","keywords":[],"description":"WhatsApp relay CLI (send, monitor, webhook, auto-reply) using Twilio","maintainers":[{"name":"steipete","email":"steipete@gmail.com"}],"readme":"# 📡 warelay — Send, receive, and auto-reply on WhatsApp.\n\n<p align=\"center\">\n  <img src=\"README-header.png\" alt=\"warelay header\" width=\"640\">\n</p>\n\n<p align=\"center\">\n  <a href=\"https://github.com/steipete/warelay/actions/workflows/ci.yml?branch=main\"><img src=\"https://img.shields.io/github/actions/workflow/status/steipete/warelay/ci.yml?branch=main&style=for-the-badge\" alt=\"CI status\"></a>\n  <a href=\"https://www.npmjs.com/package/warelay\"><img src=\"https://img.shields.io/npm/v/warelay.svg?style=for-the-badge\" alt=\"npm version\"></a>\n  <a href=\"LICENSE\"><img src=\"https://img.shields.io/badge/License-MIT-blue.svg?style=for-the-badge\" alt=\"MIT License\"></a>\n</p>\n\nSend, receive, auto-reply, and inspect WhatsApp messages over **Twilio** or your personal **WhatsApp Web** session. Ships with a one-command webhook setup (Tailscale Funnel + Twilio callback) and a configurable auto-reply engine (plain text or command/Claude driven).\n\n### Clawd (personal assistant)\nI'm using warelay to run my personal, pro-active assistant, **Clawd**. Follow me on Twitter: [@steipete](https://twitter.com/steipete). This project is brand-new and there's a lot to discover. See the exact Claude setup in [`docs/clawd.md`](https://github.com/steipete/warelay/blob/main/docs/clawd.md).\n\nI'm using warelay to run **my personal, pro-active assistant, Clawd**.\nFollow me on Twitter - @steipete, this project is brand-new and there's a lot to discover.\n\n## Quick Start (pick your engine)\nInstall from npm (global): `npm install -g warelay` (Node 22+). Then choose **one** path:\n\n**A) Personal WhatsApp Web (preferred: no Twilio creds, fastest setup)**\n1. Link your account: `warelay login` (scan the QR).\n2. Send a message: `warelay send --to +12345550000 --message \"Hi from warelay\"` (add `--provider web` if you want to force the web session).\n3. Stay online & auto-reply: `warelay relay --verbose` (uses Web when you're logged in; if you're not linked, start it with `--provider twilio`). When a Web session drops, the relay exits instead of silently falling back so you notice and re-login.\n\n**B) Twilio WhatsApp number (for delivery status + webhooks)**\n1. Copy `.env.example` → `.env`; set `TWILIO_ACCOUNT_SID`, `TWILIO_AUTH_TOKEN` **or** `TWILIO_API_KEY`/`TWILIO_API_SECRET`, and `TWILIO_WHATSAPP_FROM=whatsapp:+19995550123` (optional `TWILIO_SENDER_SID`).\n2. Send a message: `warelay send --to +12345550000 --message \"Hi from warelay\"`.\n3. Receive replies:\n   - Polling (no ingress): `warelay relay --provider twilio --interval 5 --lookback 10`\n   - Webhook + public URL via Tailscale Funnel: `warelay webhook --ingress tailscale --port 42873 --path /webhook/whatsapp --verbose`\n\n> Already developing locally? You can still run `pnpm install` and `pnpm warelay ...` from the repo, but end users only need the npm package.\n\n## Main Features\n- **Two providers:** Twilio (default) for reliable delivery + status; Web provider for quick personal sends/receives via QR login.\n- **Auto-replies:** Static templates or external commands (Claude-aware), with per-sender or global sessions and `/new` resets.\n- Claude setup guide: see `docs/claude-config.md` for the exact Claude CLI configuration we support.\n- **Webhook in one go:** `warelay webhook --ingress tailscale` enables Tailscale Funnel, runs the webhook server, and updates the Twilio sender callback URL.\n- **Polling fallback:** `relay` polls Twilio when webhooks aren’t available; works headless.\n- **Status + delivery tracking:** `status` shows recent inbound/outbound; `send` can wait for final Twilio status.\n\n## Command Cheat Sheet\n| Command | What it does | Core flags |\n| --- | --- | --- |\n| `warelay send` | Send a WhatsApp message (Twilio or Web) | `--to <e164>` `--message <text>` `--wait <sec>` `--poll <sec>` `--provider twilio\\|web` `--json` `--dry-run` `--verbose` |\n| `warelay relay` | Auto-reply loop (poll Twilio or listen on Web) | `--provider <auto\\|twilio\\|web>` `--interval <sec>` `--lookback <min>` `--verbose` |\n| `warelay status` | Show recent sent/received messages | `--limit <n>` `--lookback <min>` `--json` `--verbose` |\n| `warelay heartbeat` | Trigger one heartbeat poll (web) | `--provider <auto\\|web>` `--to <e164?>` `--session-id <uuid?>` `--all` `--verbose` |\n| `warelay relay:heartbeat` | Run relay with an immediate heartbeat (no tmux) | `--provider <auto\\|web>` `--verbose` |\n| `warelay relay:heartbeat:tmux` | Start relay in tmux and fire a heartbeat on start (web) | _no flags_ |\n| `warelay webhook` | Run inbound webhook (`ingress=tailscale` updates Twilio; `none` is local-only) | `--ingress tailscale\\|none` `--port <port>` `--path <path>` `--reply <text>` `--verbose` `--yes` `--dry-run` |\n| `warelay login` | Link personal WhatsApp Web via QR | `--verbose` |\n\n### Sending media\n- Twilio: `warelay send --to +1... --message \"Hi\" --media ./pic.jpg --serve-media` (needs `warelay webhook --ingress tailscale` or `--serve-media` to auto-host via Funnel; max 5 MB per file because of the built-in host).\n- Web: `warelay send --provider web --media ./pic.jpg --message \"Hi\"` (local path or URL; no hosting needed). Web auto-detects media kind: images (≤6 MB), audio/voice or video (≤16 MB), other docs (≤100 MB). Images are resized to max 2048px and JPEG recompressed when the cap would be exceeded.\n- Auto-replies can attach `mediaUrl` in `~/.warelay/warelay.json` (used alongside `text` when present). Web auto-replies honor `inbound.reply.mediaMaxMb` (default 5 MB) as a post-compression target but will never exceed the provider hard limits above.\n\n### Voice notes (optional transcription)\n- If you set `inbound.transcribeAudio.command`, warelay will run that CLI when inbound audio arrives (e.g., WhatsApp voice notes) and replace the Body with the transcript before templating/Claude.\n- Example using OpenAI Whisper CLI (requires `OPENAI_API_KEY`):\n  ```json5\n  {\n    inbound: {\n      transcribeAudio: {\n        command: [\n          \"openai\",\n          \"api\",\n          \"audio.transcriptions.create\",\n          \"-m\",\n          \"whisper-1\",\n          \"-f\",\n          \"{{MediaPath}}\",\n          \"--response-format\",\n          \"text\"\n        ],\n        timeoutSeconds: 45\n      },\n      reply: { mode: \"command\", command: [\"claude\", \"{{Body}}\"] }\n    }\n  }\n  ```\n- Works for Web and Twilio providers; verbose mode logs when transcription runs. The command prompt includes the original media path plus a `Transcript:` block so models see both. If transcription fails, the original Body is used.\n\n## Providers\n- **Twilio (default):** needs `.env` creds + WhatsApp-enabled number; supports delivery tracking, polling, webhooks, and auto-reply typing indicators.\n- **Web (`--provider web`):** uses your personal WhatsApp via Baileys; supports send/receive + auto-reply, but no delivery-status wait; cache lives in `~/.warelay/credentials/` (rerun `login` if logged out). If the Web socket closes, the relay exits instead of pivoting to Twilio.\n- **Auto-select (`relay` only):** `--provider auto` picks Web when a cache exists at start, otherwise Twilio polling. It will not swap from Web to Twilio mid-run if the Web session drops.\n\nBest practice: use a dedicated WhatsApp account (separate SIM/eSIM or business account) for automation instead of your primary personal account to avoid unexpected logouts or rate limits.\n\n### Same-phone mode (self-messaging)\nwarelay supports running on the same phone number you message from—you chat with yourself and an AI assistant replies in the same bubble. This requires:\n- Adding your own number to `allowFrom` in `warelay.json`\n- The `fromMe` filter is disabled; echo detection in `auto-reply.ts` prevents loops\n\n**Gotchas:**\n- Messages appear in the same chat bubble (WhatsApp \"Note to self\")\n- Echo detection relies on exact text matching; if the reply is identical to your input, it may be skipped\n- Works best with a dedicated WhatsApp account\n\n## Configuration\n\n### Environment (.env)\n| Variable | Required | Description |\n| --- | --- | --- |\n| `TWILIO_ACCOUNT_SID` | Yes (Twilio provider) | Twilio Account SID |\n| `TWILIO_AUTH_TOKEN` | Yes* | Auth token (or use API key/secret) |\n| `TWILIO_API_KEY` | Yes* | API key if not using auth token |\n| `TWILIO_API_SECRET` | Yes* | API secret paired with `TWILIO_API_KEY` |\n| `TWILIO_WHATSAPP_FROM` | Yes (Twilio provider) | WhatsApp-enabled sender, e.g. `whatsapp:+19995550123` |\n| `TWILIO_SENDER_SID` | Optional | Overrides auto-discovery of the sender SID |\n\n(*Provide either auth token OR api key/secret.)\n\n### Auto-reply config (`~/.warelay/warelay.json`, JSON5)\n- Controls who is allowed to trigger replies (`allowFrom`), reply mode (`text` or `command`), templates, and session behavior.\n- Example (Claude command):\n\n```json5\n{\n  inbound: {\n    allowFrom: [\"+12345550000\"],\n    reply: {\n      mode: \"command\",\n      bodyPrefix: \"You are a concise WhatsApp assistant.\\n\\n\",\n      command: [\"claude\", \"--dangerously-skip-permissions\", \"{{BodyStripped}}\"],\n      claudeOutputFormat: \"text\",\n      session: { scope: \"per-sender\", resetTriggers: [\"/new\"], idleMinutes: 60 },\n      heartbeatMinutes: 10 // optional; pings Claude every 10m with \"HEARTBEAT ultrathink\" and only sends if it omits HEARTBEAT_OK\n    }\n  }\n}\n```\n\n#### Abort trigger words\n- If an inbound body is exactly `stop`, `esc`, `abort`, `wait`, or `exit`, the command/agent run is skipped and the user immediately gets `Agent was aborted.`.\n- The session is tagged so the *next* prompt sent to the agent is prefixed with a short reminder that the previous run was aborted; the hint clears after that turn.\n\n#### Agent choices\n- `inbound.reply.agent.kind` can be `claude`, `opencode`, `pi`, `codex`, or `gemini`.\n- Gemini CLI supports `--output-format text|json|stream-json`; warelay auto-adds it when you set `agent.format`.\n- Session defaults: Claude uses `--session-id/--resume`, Codex/Opencode/Pi use `--session`, and Gemini defaults to `--resume` for session resumes (new sessions need no flag). Override via `sessionArgNew/sessionArgResume` if you prefer custom flags.\n- Reliability note: only Claude reliably returns a `session_id` that warelay can persist and reuse. Other harnesses currently don’t emit a stable session identifier, so multi-turn continuity may reset between runs for those agents (Pi does not auto-compact, but still doesn’t expose a session id).\n\n#### Heartbeat pings (command mode)\n- When `heartbeatMinutes` is set (default 10 for `mode: \"command\"`), the relay periodically runs your command/Claude session with a heartbeat prompt.\n- Heartbeat body is `HEARTBEAT ultrathink` (so the model can recognize the probe); if Claude replies exactly `HEARTBEAT_OK`, the message is suppressed; otherwise the reply (or media) is forwarded. Suppressions are still logged so you know the heartbeat ran.\n- Override session freshness for heartbeats with `session.heartbeatIdleMinutes` (defaults to `session.idleMinutes`). Heartbeat skips do **not** bump `updatedAt`, so sessions still expire normally.\n- Trigger one manually with `warelay heartbeat` (web provider only, `--verbose` prints session info). Use `--session-id <uuid>` to force resuming a specific Claude session, `--all` to ping every active session, `warelay relay:heartbeat` for a full relay run with an immediate heartbeat, or `--heartbeat-now` on `relay`/`relay:heartbeat:tmux`.\n- When multiple active sessions exist, `warelay heartbeat` requires `--to <E.164>` or `--all`; if `allowFrom` is just `\"*\"`, you must choose a target with one of those flags.\n\n### Logging (optional)\n- File logs are written to `/tmp/warelay/warelay.log` by default. Levels: `silent | fatal | error | warn | info | debug | trace` (CLI `--verbose` forces `debug`). Web-provider inbound/outbound entries include message bodies and auto-reply text for easier auditing.\n- Override in `~/.warelay/warelay.json`:\n\n```json5\n{\n  logging: {\n    level: \"warn\",\n    file: \"/tmp/warelay/custom.log\"\n  }\n}\n```\n\n### Claude CLI setup (how we run it)\n1) Install the official Claude CLI (e.g., `brew install anthropic-ai/cli/claude` or follow the Anthropic docs) and run `claude login` so it can read your API key.\n2) In `warelay.json`, set `reply.mode` to `\"command\"` and point `command[0]` to `\"claude\"`; set `claudeOutputFormat` to `\"text\"` (or `\"json\"`/`\"stream-json\"` if you want warelay to parse and trim the JSON output).\n3) (Optional) Add `bodyPrefix` to inject a system prompt and `session` settings to keep multi-turn context (`/new` resets by default). Set `sendSystemOnce: true` (plus an optional `sessionIntro`) to only send that prompt on the first turn of each session.\n4) Run `pnpm warelay relay --provider auto` (or `--provider web|twilio`) and send a WhatsApp message; warelay will queue the Claude call, stream typing indicators (Twilio provider), parse the result, and send back the text.\n\n### Auto-reply parameter table (compact)\n| Key | Type & default | Notes |\n| --- | --- | --- |\n| `inbound.allowFrom` | `string[]` (default: empty) | E.164 numbers allowed to trigger auto-reply (no `whatsapp:`); `\"*\"` allows any sender. |\n| `inbound.messagePrefix` | `string` (default: `\"[warelay]\"` if no allowFrom, else `\"\"`) | Prefix added to all inbound messages before passing to command. |\n| `inbound.responsePrefix` | `string` (default: —) | Prefix auto-added to all outbound replies (e.g., `\"🦞\"`). |\n| `inbound.timestampPrefix` | `boolean \\| string` (default: `true`) | Timestamp prefix: `true` (UTC), `false` (disabled), or IANA timezone like `\"Europe/Vienna\"`. |\n| `inbound.reply.mode` | `\"text\"` \\| `\"command\"` (default: —) | Reply style. |\n| `inbound.reply.text` | `string` (default: —) | Used when `mode=text`; templating supported. |\n| `inbound.reply.command` | `string[]` (default: —) | Argv for `mode=command`; each element templated. Stdout (trimmed) is sent. |\n| `inbound.reply.template` | `string` (default: —) | Injected as argv[1] (prompt prefix) before the body. |\n| `inbound.reply.bodyPrefix` | `string` (default: —) | Prepended to `Body` before templating (great for system prompts). |\n| `inbound.reply.timeoutSeconds` | `number` (default: `600`) | Command timeout. |\n| `inbound.reply.claudeOutputFormat` | `\"text\"`\\|`\"json\"`\\|`\"stream-json\"` (default: —) | When command starts with `claude`, auto-adds `--output-format` + `-p/--print` and trims reply text. |\n| `inbound.reply.session.scope` | `\"per-sender\"`\\|`\"global\"` (default: `per-sender`) | Session bucket for conversation memory. |\n| `inbound.reply.session.resetTriggers` | `string[]` (default: `[\"/new\"]`) | Exact match or prefix (`/new hi`) resets session. |\n| `inbound.reply.session.idleMinutes` | `number` (default: `60`) | Session expires after idle period. |\n| `inbound.reply.session.store` | `string` (default: `~/.warelay/sessions.json`) | Custom session store path. |\n| `inbound.reply.session.sendSystemOnce` | `boolean` (default: `false`) | If `true`, only include the system prompt/template on the first turn of a session. |\n| `inbound.reply.session.sessionIntro` | `string` | Optional intro text sent once per new session (prepended before the body when `sendSystemOnce` is used). |\n| `inbound.reply.typingIntervalSeconds` | `number` (default: `8` for command replies) | How often to refresh typing indicators while the command/Claude run is in flight. |\n| `inbound.reply.session.sessionArgNew` | `string[]` (default: `[\"--session-id\",\"{{SessionId}}\"]`) | Args injected for a new session run. |\n| `inbound.reply.session.sessionArgResume` | `string[]` (default: `[\"--resume\",\"{{SessionId}}\"]`) | Args for resumed sessions. |\n| `inbound.reply.session.sessionArgBeforeBody` | `boolean` (default: `true`) | Place session args before final body arg. |\n\nTemplating tokens: `{{Body}}`, `{{BodyStripped}}`, `{{From}}`, `{{To}}`, `{{MessageSid}}`, plus `{{SessionId}}` and `{{IsNewSession}}` when sessions are enabled.\n\n## Webhook & Tailscale Flow\n- `warelay webhook --ingress none` starts the local Express server on your chosen port/path; add `--reply \"Got it\"` for a static reply when no config file is present.\n- `warelay webhook --ingress tailscale` enables Tailscale Funnel, prints the public URL (`https://<tailnet-host><path>`), starts the webhook, discovers the WhatsApp sender SID, and updates Twilio callbacks to the Funnel URL.\n- If Funnel is not allowed on your tailnet, the CLI exits with guidance; you can still use `relay --provider twilio` to poll without webhooks.\n\n## Troubleshooting Tips\n- Send/receive issues: run `pnpm warelay status --limit 20 --lookback 240 --json` to inspect recent traffic.\n- Auto-reply not firing: ensure sender is in `allowFrom` (or unset), and confirm `.env` + `warelay.json` are loaded (reload shell after edits).\n- Web provider dropped: rerun `pnpm warelay login`; credentials live in `~/.warelay/credentials/`.\n- Tailscale Funnel errors: update tailscale/tailscaled; check admin console that Funnel is enabled for this device.\n\n### Maintainer notes (web provider internals)\n- Web logic lives under `src/web/`: `session.ts` (auth/cache + provider pick), `login.ts` (QR login/logout), `outbound.ts`/`inbound.ts` (send/receive plumbing), `auto-reply.ts` (relay loop + reconnect/backoff), `media.ts` (download/resize helpers), and `reconnect.ts` (shared retry math). `test-helpers.ts` provides fixtures.\n- The public surface remains the `src/provider-web.ts` barrel so existing imports keep working.\n- Reconnects are capped and logged; no Twilio fallback occurs after a Web disconnect—restart the relay after re-linking.\n\n## FAQ & Safety\n- Twilio errors: **63016 “permission to send an SMS has not been enabled”** → ensure your number is WhatsApp-enabled; **63007 template not approved** → send a free-form session message within 24h or use an approved template; **63112 policy violation** → adjust content, shorten to <1600 chars, avoid links that trigger spam filters. Re-run `pnpm warelay status` to see the exact Twilio response body.\n- Does this store my messages? warelay only writes `~/.warelay/warelay.json` (config), `~/.warelay/credentials/` (WhatsApp Web auth), and `~/.warelay/sessions.json` (session IDs + timestamps). It does **not** persist message bodies beyond the session store. Logs stream to stdout/stderr and also `/tmp/warelay/warelay.log` (configurable via `logging.file`).\n- Personal WhatsApp safety: Automation on personal accounts can be rate-limited or logged out by WhatsApp. Use `--provider web` sparingly, keep messages human-like, and re-run `login` if the session is dropped.\n- Limits to remember: WhatsApp text limit ~1600 chars; avoid rapid bursts—space sends by a few seconds; keep webhook replies under a couple seconds for good UX; command auto-replies time out after 600s by default.\n- Deploy / keep running: Use `tmux` or `screen` for ad-hoc (`tmux new -s warelay -- pnpm warelay relay --provider twilio`). For long-running hosts, wrap `pnpm warelay relay ...` or `pnpm warelay webhook --ingress tailscale ...` in a systemd service or macOS LaunchAgent; ensure environment variables are loaded in that context.\n- Rotating credentials: Update `.env` (Twilio keys), rerun your process; for Web provider, delete `~/.warelay/credentials/` and rerun `pnpm warelay login` to relink.\n","readmeFilename":"README.md"}