{"_id":"claude-slack-channel-bots","_rev":"32-d7f8f814552b5687bb1b3ad486e6c3c5","name":"claude-slack-channel-bots","dist-tags":{"latest":"0.10.0"},"versions":{"0.0.1":{"name":"claude-slack-channel-bots","version":"0.0.1","author":{"name":"Gabe Mahoney"},"license":"MIT","_id":"claude-slack-channel-bots@0.0.1","maintainers":[{"name":"gabemahoney","email":"gmahoney@gmail.com"}],"homepage":"https://github.com/gabemahoney/claude-slack-channel-bots#readme","bugs":{"url":"https://github.com/gabemahoney/claude-slack-channel-bots/issues"},"bin":{"claude-slack-channel-bots":"src/cli.ts"},"dist":{"shasum":"3a88a8b47274a70be93cbeffb5255602dd1a573b","tarball":"https://registry.npmjs.org/claude-slack-channel-bots/-/claude-slack-channel-bots-0.0.1.tgz","fileCount":20,"integrity":"sha512-GRiFGuLMW8ZH+pNnw3o9FysnQvc2YDk3wQPRXDlqzJE1DIhOHmCAIFYiG890OSbrbTymXrZtCXMKddVkXqW4hg==","signatures":[{"sig":"MEUCIQCDU7F7Cny+XTybE4KNHy84zVAz+HDVwfJjGHWVfnsEZQIgCgOOJsgDMJAipH3MWT/eQa1ST11ixBgaM0QPx8hnPDI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":160332},"type":"module","engines":{"bun":">=1.0.0"},"gitHead":"7503d04aa585f3aacf180f069b26fc7fe1693025","scripts":{"test":"bun test","start":"bun install --no-summary && bun src/server.ts","typecheck":"tsc --noEmit","postinstall":"bun src/postinstall.ts"},"_npmUser":{"name":"gabemahoney","email":"gmahoney@gmail.com"},"repository":{"url":"git+https://github.com/gabemahoney/claude-slack-channel-bots.git","type":"git"},"_npmVersion":"10.9.4","description":"Multi-session Slack-to-Claude bridge — run multiple Claude Code bots across Slack channels via Socket Mode","directories":{},"_nodeVersion":"22.22.1","dependencies":{"@slack/web-api":"^7.0.0","@slack/socket-mode":"^2.0.0","@modelcontextprotocol/sdk":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"@types/bun":"^1.0.0","typescript":"^5.4.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-slack-channel-bots_0.0.1_1774752763524_0.6736760095985634","host":"s3://npm-registry-packages-npm-production"}},"0.0.2":{"name":"claude-slack-channel-bots","version":"0.0.2","author":{"name":"Gabe Mahoney"},"license":"MIT","_id":"claude-slack-channel-bots@0.0.2","maintainers":[{"name":"gabemahoney","email":"gmahoney@gmail.com"}],"homepage":"https://github.com/gabemahoney/claude-slack-channel-bots#readme","bugs":{"url":"https://github.com/gabemahoney/claude-slack-channel-bots/issues"},"bin":{"claude-slack-channel-bots":"src/cli.ts"},"dist":{"shasum":"bfee6243ecc1a3d8f0269a6fb64366065e25429f","tarball":"https://registry.npmjs.org/claude-slack-channel-bots/-/claude-slack-channel-bots-0.0.2.tgz","fileCount":21,"integrity":"sha512-6hHyzAR62+5VL9wvru3zEiu3O1hl0IU3Hhku5s+a+GqIXAbFRwg6GPVGqcCL+q6yO5x0EUSmr1ENCMxgf1zFpg==","signatures":[{"sig":"MEQCIBILbBJCOsE0Dl3IIPgZ7FzyXdZaIX163gdgQV1tSuqCAiBbpMEIyd5ZO09c87DPzjbbaWZ0lq10PXa/uAJhAqvzJA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":163688},"type":"module","engines":{"bun":">=1.0.0"},"gitHead":"824982816437019ba47da9cdfa98891126e02b71","scripts":{"test":"bun test","start":"bun install --no-summary && bun src/server.ts","typecheck":"tsc --noEmit","postinstall":"bun src/postinstall.ts"},"_npmUser":{"name":"gabemahoney","email":"gmahoney@gmail.com"},"repository":{"url":"git+https://github.com/gabemahoney/claude-slack-channel-bots.git","type":"git"},"_npmVersion":"10.9.4","description":"Multi-session Slack-to-Claude bridge — run multiple Claude Code bots across Slack channels via Socket Mode","directories":{},"_nodeVersion":"22.22.1","dependencies":{"@slack/web-api":"^7.0.0","@slack/socket-mode":"^2.0.0","@modelcontextprotocol/sdk":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"@types/bun":"^1.0.0","typescript":"^5.4.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-slack-channel-bots_0.0.2_1774759229160_0.4723066895490722","host":"s3://npm-registry-packages-npm-production"}},"0.0.3":{"name":"claude-slack-channel-bots","version":"0.0.3","author":{"name":"Gabe Mahoney"},"license":"MIT","_id":"claude-slack-channel-bots@0.0.3","maintainers":[{"name":"gabemahoney","email":"gmahoney@gmail.com"}],"homepage":"https://github.com/gabemahoney/claude-slack-channel-bots#readme","bugs":{"url":"https://github.com/gabemahoney/claude-slack-channel-bots/issues"},"bin":{"claude-slack-channel-bots":"src/cli.ts"},"dist":{"shasum":"8494861f6b08acf82a7ae0b643e31536ac5eedc3","tarball":"https://registry.npmjs.org/claude-slack-channel-bots/-/claude-slack-channel-bots-0.0.3.tgz","fileCount":21,"integrity":"sha512-W9CR9X/I7Op8EqaDCK7lEsGj8dX6CfFGxYaYgRJ8FZYgFBGZkCYpwBi+vLV+KDDppx+nDWro1ZpeaS3YIzd2dA==","signatures":[{"sig":"MEUCIQCBELt69LU0nY2aZ4h2uAvh8SO5rOI86K5yCHe4Q8sotAIgbf3PzHwqpwZonfa3mC3O3YsQIrWEAF9UOiaf+ov7IAM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":164439},"type":"module","engines":{"bun":">=1.0.0"},"gitHead":"15f09fd0a5d6b5fbea97c5719b74681e415cc27a","scripts":{"test":"bun test","start":"bun install --no-summary && bun src/server.ts","typecheck":"tsc --noEmit","postinstall":"bun src/postinstall.ts"},"_npmUser":{"name":"gabemahoney","email":"gmahoney@gmail.com"},"repository":{"url":"git+https://github.com/gabemahoney/claude-slack-channel-bots.git","type":"git"},"_npmVersion":"10.9.4","description":"Multi-session Slack-to-Claude bridge — run multiple Claude Code bots across Slack channels via Socket Mode","directories":{},"_nodeVersion":"22.22.1","dependencies":{"@slack/web-api":"^7.0.0","@slack/socket-mode":"^2.0.0","@modelcontextprotocol/sdk":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"@types/bun":"^1.0.0","typescript":"^5.4.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-slack-channel-bots_0.0.3_1774761399847_0.3193965492287203","host":"s3://npm-registry-packages-npm-production"}},"0.0.4":{"name":"claude-slack-channel-bots","version":"0.0.4","author":{"name":"Gabe Mahoney"},"license":"MIT","_id":"claude-slack-channel-bots@0.0.4","maintainers":[{"name":"gabemahoney","email":"gmahoney@gmail.com"}],"homepage":"https://github.com/gabemahoney/claude-slack-channel-bots#readme","bugs":{"url":"https://github.com/gabemahoney/claude-slack-channel-bots/issues"},"bin":{"claude-slack-channel-bots":"src/cli.ts"},"dist":{"shasum":"44acc40dfaf5280b2bd56bd7024ac2219ea257cc","tarball":"https://registry.npmjs.org/claude-slack-channel-bots/-/claude-slack-channel-bots-0.0.4.tgz","fileCount":21,"integrity":"sha512-RE5YqoQkQ3IOWHeyFr2KBGz1LRN4aV0QdJZJRqG6V65h9tfmxaAby9qF1Zc0E5S7QRUZCZyHt4vpvD6YJVQW0Q==","signatures":[{"sig":"MEUCIQDolEOLGTFdo0yJBgsaxVpESQhzxTcI8gkZdb0QnubmdgIgWQM83sgup5g7vwaFhnjX+6ZGIhvo3V3AZAaldrRlFgQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":164652},"type":"module","engines":{"bun":">=1.0.0"},"gitHead":"1b8fc30afa4a11524e2e185b924ea24c5c77d34f","scripts":{"test":"bun test","start":"bun install --no-summary && bun src/server.ts","typecheck":"tsc --noEmit","postinstall":"bun src/postinstall.ts"},"_npmUser":{"name":"gabemahoney","email":"gmahoney@gmail.com"},"repository":{"url":"git+https://github.com/gabemahoney/claude-slack-channel-bots.git","type":"git"},"_npmVersion":"10.9.4","description":"Multi-session Slack-to-Claude bridge — run multiple Claude Code bots across Slack channels via Socket Mode","directories":{},"_nodeVersion":"22.22.1","dependencies":{"@slack/web-api":"^7.0.0","@slack/socket-mode":"^2.0.0","@modelcontextprotocol/sdk":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"@types/bun":"^1.0.0","typescript":"^5.4.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-slack-channel-bots_0.0.4_1774850258853_0.8997792318860367","host":"s3://npm-registry-packages-npm-production"}},"0.1.0":{"name":"claude-slack-channel-bots","version":"0.1.0","author":{"name":"Gabe Mahoney"},"license":"MIT","_id":"claude-slack-channel-bots@0.1.0","maintainers":[{"name":"gabemahoney","email":"gmahoney@gmail.com"}],"homepage":"https://github.com/gabemahoney/claude-slack-channel-bots#readme","bugs":{"url":"https://github.com/gabemahoney/claude-slack-channel-bots/issues"},"bin":{"claude-slack-channel-bots":"src/cli.ts"},"dist":{"shasum":"222f3bb861405464af11e87a7d2269d0b773f1e4","tarball":"https://registry.npmjs.org/claude-slack-channel-bots/-/claude-slack-channel-bots-0.1.0.tgz","fileCount":21,"integrity":"sha512-cN8F84n89LJ7wwbPMT2SIpm2ZPwudRpwm5NuCOzZd7UL0HY0ftF+EwYr0vAfgiTDyk9mYxlVkuV92CuRk1LloA==","signatures":[{"sig":"MEUCIBCk3VyXjzWFAWBrX4czExQs0v2xsh/bNXFM1A1dDqp+AiEAighsIL3Su34T7qmNiqhyxSSEYaLtJ5V2i/LqPcvDHzU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":171227},"type":"module","engines":{"bun":">=1.0.0"},"gitHead":"7049436901e3878d43a39374817ff8e826db0849","scripts":{"test":"bun test","start":"bun install --no-summary && bun src/server.ts","typecheck":"tsc --noEmit","postinstall":"bun src/postinstall.ts"},"_npmUser":{"name":"gabemahoney","email":"gmahoney@gmail.com"},"repository":{"url":"git+https://github.com/gabemahoney/claude-slack-channel-bots.git","type":"git"},"_npmVersion":"10.9.4","description":"Multi-session Slack-to-Claude bridge — run multiple Claude Code bots across Slack channels via Socket Mode","directories":{},"_nodeVersion":"22.22.1","dependencies":{"@slack/web-api":"^7.0.0","@slack/socket-mode":"^2.0.0","@modelcontextprotocol/sdk":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"@types/bun":"^1.0.0","typescript":"^5.4.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-slack-channel-bots_0.1.0_1774911893291_0.7962238097316994","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"claude-slack-channel-bots","version":"0.1.1","author":{"name":"Gabe Mahoney"},"license":"MIT","_id":"claude-slack-channel-bots@0.1.1","maintainers":[{"name":"gabemahoney","email":"gmahoney@gmail.com"}],"homepage":"https://github.com/gabemahoney/claude-slack-channel-bots#readme","bugs":{"url":"https://github.com/gabemahoney/claude-slack-channel-bots/issues"},"bin":{"claude-slack-channel-bots":"src/cli.ts"},"dist":{"shasum":"cf915f2131390d6323b2ff0acf47bd6ea06946e8","tarball":"https://registry.npmjs.org/claude-slack-channel-bots/-/claude-slack-channel-bots-0.1.1.tgz","fileCount":22,"integrity":"sha512-eZmvd5axrXPo49nAx+XQ4yDixhTq3Pic5fy46hXoe1MZLgcO5AjEXjWpGIM+ljfVETBkYyS3hT7JqIVpH+dOdw==","signatures":[{"sig":"MEYCIQDyGtR+ZWdKOFI2T9F9J/nDJyxLBQ03AIToZs4zSR9X4QIhAPDtDv/j0Uxu85DNy2RlKOQMSzXmGRK6IOAHxILxxORu","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":175185},"type":"module","engines":{"bun":">=1.0.0"},"gitHead":"32dd0f40cdf870e06519935c7c0ca14f29d4a1df","scripts":{"test":"bun test","start":"bun install --no-summary && bun src/server.ts","typecheck":"tsc --noEmit","postinstall":"bun src/postinstall.ts"},"_npmUser":{"name":"gabemahoney","email":"gmahoney@gmail.com"},"repository":{"url":"git+https://github.com/gabemahoney/claude-slack-channel-bots.git","type":"git"},"_npmVersion":"10.9.4","description":"Multi-session Slack-to-Claude bridge — run multiple Claude Code bots across Slack channels via Socket Mode","directories":{},"_nodeVersion":"22.22.1","dependencies":{"@slack/web-api":"^7.0.0","@slack/socket-mode":"^2.0.0","@modelcontextprotocol/sdk":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"@types/bun":"^1.0.0","typescript":"^5.4.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-slack-channel-bots_0.1.1_1774929496969_0.6086420283858722","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"claude-slack-channel-bots","version":"0.1.2","author":{"name":"Gabe Mahoney"},"license":"MIT","_id":"claude-slack-channel-bots@0.1.2","maintainers":[{"name":"gabemahoney","email":"gmahoney@gmail.com"}],"homepage":"https://github.com/gabemahoney/claude-slack-channel-bots#readme","bugs":{"url":"https://github.com/gabemahoney/claude-slack-channel-bots/issues"},"bin":{"claude-slack-channel-bots":"src/cli.ts"},"dist":{"shasum":"5bf1cfdd628e80b3c85720644ba6383a2016c40e","tarball":"https://registry.npmjs.org/claude-slack-channel-bots/-/claude-slack-channel-bots-0.1.2.tgz","fileCount":23,"integrity":"sha512-f4vP2WPH9sek0Om/gOJH7TGqkk/OGzZWNjvfBFzNofJsXilgpsqD8CeCrQPdvG9DEE5ETRnMIBLxrhvjg2/zgQ==","signatures":[{"sig":"MEQCIEHH+ql2EV5zo82zeCWZCMFW8H5tPLXdh0CtOChPnIF2AiALMdFebd00qhLtK58LsykmJaYQn76wQiigsIm0BX3wNQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":180917},"type":"module","engines":{"bun":">=1.0.0"},"gitHead":"f6a3b0595baa7b60c36dbd4fce55e1b64a7fb2be","scripts":{"test":"bun test","start":"bun install --no-summary && bun src/server.ts","typecheck":"tsc --noEmit","postinstall":"bun src/postinstall.ts"},"_npmUser":{"name":"gabemahoney","email":"gmahoney@gmail.com"},"repository":{"url":"git+https://github.com/gabemahoney/claude-slack-channel-bots.git","type":"git"},"_npmVersion":"10.9.4","description":"Multi-session Slack-to-Claude bridge — run multiple Claude Code bots across Slack channels via Socket Mode","directories":{},"_nodeVersion":"22.22.1","dependencies":{"@slack/web-api":"^7.0.0","@slack/socket-mode":"^2.0.0","@modelcontextprotocol/sdk":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"@types/bun":"^1.0.0","typescript":"^5.4.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-slack-channel-bots_0.1.2_1774989133397_0.8800975225358307","host":"s3://npm-registry-packages-npm-production"}},"0.1.3":{"name":"claude-slack-channel-bots","version":"0.1.3","author":{"name":"Gabe Mahoney"},"license":"MIT","_id":"claude-slack-channel-bots@0.1.3","maintainers":[{"name":"gabemahoney","email":"gmahoney@gmail.com"}],"homepage":"https://github.com/gabemahoney/claude-slack-channel-bots#readme","bugs":{"url":"https://github.com/gabemahoney/claude-slack-channel-bots/issues"},"bin":{"claude-slack-channel-bots":"src/cli.ts"},"dist":{"shasum":"5765c74f522530b57c0b377e439b3ee578a805b7","tarball":"https://registry.npmjs.org/claude-slack-channel-bots/-/claude-slack-channel-bots-0.1.3.tgz","fileCount":23,"integrity":"sha512-4xmO1Eq78FREDwAF8oGmevelfO/1TPS7x17OJu1c3ItUO8HGJs8R+dbK8U84PyaQbFv0ocPGUJZpw7tcXs2cug==","signatures":[{"sig":"MEQCIFedzQbPBgrmUlx9CFLNSV2R0gRjXQ2pCzPkANMBWqqYAiAQeGRMcWKdL/1fP/oJklpzSnauVYt3cMCeSUsXpR2F9g==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":181481},"type":"module","engines":{"bun":">=1.0.0"},"gitHead":"2a96ba59c911f69f26e0f5aa963f699de0a9a8b6","scripts":{"test":"bun test","start":"bun install --no-summary && bun src/server.ts","typecheck":"tsc --noEmit","postinstall":"bun src/postinstall.ts"},"_npmUser":{"name":"gabemahoney","email":"gmahoney@gmail.com"},"repository":{"url":"git+https://github.com/gabemahoney/claude-slack-channel-bots.git","type":"git"},"_npmVersion":"10.9.4","description":"Multi-session Slack-to-Claude bridge — run multiple Claude Code bots across Slack channels via Socket Mode","directories":{},"_nodeVersion":"22.22.1","dependencies":{"@slack/web-api":"^7.0.0","@slack/socket-mode":"^2.0.0","@modelcontextprotocol/sdk":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"@types/bun":"^1.0.0","typescript":"^5.4.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-slack-channel-bots_0.1.3_1774992736910_0.829141399740404","host":"s3://npm-registry-packages-npm-production"}},"0.1.4":{"name":"claude-slack-channel-bots","version":"0.1.4","author":{"name":"Gabe Mahoney"},"license":"MIT","_id":"claude-slack-channel-bots@0.1.4","maintainers":[{"name":"gabemahoney","email":"gmahoney@gmail.com"}],"homepage":"https://github.com/gabemahoney/claude-slack-channel-bots#readme","bugs":{"url":"https://github.com/gabemahoney/claude-slack-channel-bots/issues"},"bin":{"claude-slack-channel-bots":"src/cli.ts"},"dist":{"shasum":"bf61950c8c94cce95f1b342f276a07bffcf2f701","tarball":"https://registry.npmjs.org/claude-slack-channel-bots/-/claude-slack-channel-bots-0.1.4.tgz","fileCount":23,"integrity":"sha512-YD5UPqv3C1OCaJVsLOjUzOsHsGbCSo4yDTBtIqmq1OIIkGm3eWNwCMatKZkoOi+7PIvOl0EVASOK1UiVnCKDbA==","signatures":[{"sig":"MEUCIGIjifrNZPqL1Bt7Wlt440HGZ5qZXG3QVoAF+EFJkZUTAiEAlkmhhx2P9Zm0deHFqCGdAWt2spLqDwYo1ytYNWYP65Q=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":187669},"type":"module","engines":{"bun":">=1.0.0"},"gitHead":"9f87b06f1f5bdf9aa6bbfd48cb906a2568593b71","scripts":{"test":"bun test","start":"bun install --no-summary && bun src/server.ts","typecheck":"tsc --noEmit","postinstall":"bun src/postinstall.ts"},"_npmUser":{"name":"gabemahoney","email":"gmahoney@gmail.com"},"repository":{"url":"git+https://github.com/gabemahoney/claude-slack-channel-bots.git","type":"git"},"_npmVersion":"10.9.4","description":"Multi-session Slack-to-Claude bridge — run multiple Claude Code bots across Slack channels via Socket Mode","directories":{},"_nodeVersion":"22.22.1","dependencies":{"@slack/web-api":"^7.0.0","@slack/socket-mode":"^2.0.0","@modelcontextprotocol/sdk":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"@types/bun":"^1.0.0","typescript":"^5.4.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-slack-channel-bots_0.1.4_1775059906534_0.016203905611480218","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"claude-slack-channel-bots","version":"0.2.0","author":{"name":"Gabe Mahoney"},"license":"MIT","_id":"claude-slack-channel-bots@0.2.0","maintainers":[{"name":"gabemahoney","email":"gmahoney@gmail.com"}],"homepage":"https://github.com/gabemahoney/claude-slack-channel-bots#readme","bugs":{"url":"https://github.com/gabemahoney/claude-slack-channel-bots/issues"},"bin":{"claude-slack-channel-bots":"src/cli.ts"},"dist":{"shasum":"554ee39bcbdb5b15589a70245ed42406880a23e7","tarball":"https://registry.npmjs.org/claude-slack-channel-bots/-/claude-slack-channel-bots-0.2.0.tgz","fileCount":24,"integrity":"sha512-9C0gIf+vw4ncAyaZjMIvRfPObwpOTLeDUdSIDFReIwe5bQABXFvhj40vT8KUZWq9iZ6gkLRdHPBBoYlRCMbsRA==","signatures":[{"sig":"MEUCIFl19hVdAq+IAs3e60BiIKI3nLaJVuMvpPKFrvYEGpQ9AiEA19N8S+sWvj96GnibdM2u9Zt/9q0ovvLE/Hm25dVaJ3E=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":200100},"type":"module","engines":{"bun":">=1.0.0"},"gitHead":"4fc0eba649579a99c5c9b01d01c401b28ccf02fe","scripts":{"test":"bun test","start":"bun install --no-summary && bun src/server.ts","typecheck":"tsc --noEmit","postinstall":"bun src/postinstall.ts"},"_npmUser":{"name":"gabemahoney","email":"gmahoney@gmail.com"},"repository":{"url":"git+https://github.com/gabemahoney/claude-slack-channel-bots.git","type":"git"},"_npmVersion":"10.9.7","description":"Multi-session Slack-to-Claude bridge — run multiple Claude Code bots across Slack channels via Socket Mode","directories":{},"_nodeVersion":"22.22.2","dependencies":{"@slack/web-api":"^7.0.0","@slack/socket-mode":"^2.0.0","@modelcontextprotocol/sdk":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"@types/bun":"^1.0.0","typescript":"^5.4.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-slack-channel-bots_0.2.0_1775195921705_0.9853402558953972","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"claude-slack-channel-bots","version":"0.2.1","author":{"name":"Gabe Mahoney"},"license":"MIT","_id":"claude-slack-channel-bots@0.2.1","maintainers":[{"name":"gabemahoney","email":"gmahoney@gmail.com"}],"homepage":"https://github.com/gabemahoney/claude-slack-channel-bots#readme","bugs":{"url":"https://github.com/gabemahoney/claude-slack-channel-bots/issues"},"bin":{"claude-slack-channel-bots":"src/cli.ts"},"dist":{"shasum":"1e6da6de465cd384d6b676fefd42045f064a0921","tarball":"https://registry.npmjs.org/claude-slack-channel-bots/-/claude-slack-channel-bots-0.2.1.tgz","fileCount":24,"integrity":"sha512-ohxAZzHh7tbaSsrqrOo1zUQHWIBl6eDo0m0rDDTZoNVzFX0muqLhy4cvlUhLg6zLiLgW0wz1hAk3DeiiyRkQdw==","signatures":[{"sig":"MEUCIDfQjSX0B4O5wBB8R4CkuN28nZPOfjcT57NOXYld2oCjAiEA55SXwSPcNPclUC2n7Pvxxo8uSAq5PRGZ4PxM489/y2c=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":200102},"type":"module","engines":{"bun":">=1.0.0"},"gitHead":"2be8a6159ca6cd14a650d45ddc325de04263ba94","scripts":{"test":"bun test","start":"bun install --no-summary && bun src/server.ts","typecheck":"tsc --noEmit","postinstall":"bun src/postinstall.ts"},"_npmUser":{"name":"gabemahoney","email":"gmahoney@gmail.com"},"repository":{"url":"git+https://github.com/gabemahoney/claude-slack-channel-bots.git","type":"git"},"_npmVersion":"10.9.7","description":"Multi-session Slack-to-Claude bridge — run multiple Claude Code bots across Slack channels via Socket Mode","directories":{},"_nodeVersion":"22.22.2","dependencies":{"@slack/web-api":"^7.0.0","@slack/socket-mode":"^2.0.0","@modelcontextprotocol/sdk":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"@types/bun":"^1.0.0","typescript":"^5.4.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-slack-channel-bots_0.2.1_1775195978714_0.8529461564387766","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"claude-slack-channel-bots","version":"0.3.0","author":{"name":"Gabe Mahoney"},"license":"MIT","_id":"claude-slack-channel-bots@0.3.0","maintainers":[{"name":"gabemahoney","email":"gmahoney@gmail.com"}],"homepage":"https://github.com/gabemahoney/claude-slack-channel-bots#readme","bugs":{"url":"https://github.com/gabemahoney/claude-slack-channel-bots/issues"},"bin":{"claude-slack-channel-bots":"src/cli.ts"},"dist":{"shasum":"c25e1a9d426ecdade0826465894bee2ecfcb60aa","tarball":"https://registry.npmjs.org/claude-slack-channel-bots/-/claude-slack-channel-bots-0.3.0.tgz","fileCount":25,"integrity":"sha512-9j5hHwMloX8leA6WkigJACavy3KYa43U00hhnWzR67OJ0k9SqAiaCCjXQBx49fM8+H3NwFSvD15trM5w5/1Vdg==","signatures":[{"sig":"MEUCIQDxapV7nvK2NzSZtdmyfx+gWBiWongUUaR9ddxnU29UrwIgNij9i7y71dxK/IKoHtVsonYBfBe/wjAmMBFKN1loX9E=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":207502},"type":"module","engines":{"bun":">=1.0.0"},"gitHead":"6e24687b3ff469355336f896281e0dbc5fe22991","scripts":{"test":"bun test","start":"bun install --no-summary && bun src/server.ts","typecheck":"tsc --noEmit","postinstall":"bun src/postinstall.ts"},"_npmUser":{"name":"gabemahoney","email":"gmahoney@gmail.com"},"repository":{"url":"git+https://github.com/gabemahoney/claude-slack-channel-bots.git","type":"git"},"_npmVersion":"10.9.7","description":"Multi-session Slack-to-Claude bridge — run multiple Claude Code bots across Slack channels via Socket Mode","directories":{},"_nodeVersion":"22.22.2","dependencies":{"@slack/web-api":"^7.0.0","@slack/socket-mode":"^2.0.0","@modelcontextprotocol/sdk":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"@types/bun":"^1.0.0","typescript":"^5.4.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-slack-channel-bots_0.3.0_1775314486599_0.6798399854372099","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"name":"claude-slack-channel-bots","version":"0.4.0","author":{"name":"Gabe Mahoney"},"license":"MIT","_id":"claude-slack-channel-bots@0.4.0","maintainers":[{"name":"gabemahoney","email":"gmahoney@gmail.com"}],"homepage":"https://github.com/gabemahoney/claude-slack-channel-bots#readme","bugs":{"url":"https://github.com/gabemahoney/claude-slack-channel-bots/issues"},"bin":{"claude-slack-channel-bots":"src/cli.ts"},"dist":{"shasum":"86128be158ae4f0107019017314145ebc8491102","tarball":"https://registry.npmjs.org/claude-slack-channel-bots/-/claude-slack-channel-bots-0.4.0.tgz","fileCount":26,"integrity":"sha512-3C2BSpTxVE1MCZFUdsfINKZ+HmhyFC6dkw1TqVwYz/MwhodRmgw6VN1YXQKpHv9Ok+oiEqLQqd+WxFL6L45Vjg==","signatures":[{"sig":"MEUCIQDRpu5muKN+oO9qKsXsaby/vf8TW40cQ2AvBHjdXykEwgIgM18LaqdhbqdMJDg9rJV6hTYrxe0c3AhRf9f657YvGy4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":214189},"type":"module","engines":{"bun":">=1.0.0"},"gitHead":"3ac251271e4080bf8e0421a4e03020d69f7561de","scripts":{"test":"bun test","start":"bun install --no-summary && bun src/server.ts","typecheck":"tsc --noEmit","postinstall":"bun src/postinstall.ts"},"_npmUser":{"name":"gabemahoney","email":"gmahoney@gmail.com"},"repository":{"url":"git+https://github.com/gabemahoney/claude-slack-channel-bots.git","type":"git"},"_npmVersion":"10.9.7","description":"Multi-session Slack-to-Claude bridge — run multiple Claude Code bots across Slack channels via Socket Mode","directories":{},"_nodeVersion":"22.22.2","dependencies":{"@slack/web-api":"^7.0.0","@slack/socket-mode":"^2.0.0","@modelcontextprotocol/sdk":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"@types/bun":"^1.0.0","typescript":"^5.4.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-slack-channel-bots_0.4.0_1775318834864_0.04894836235214739","host":"s3://npm-registry-packages-npm-production"}},"0.4.1":{"name":"claude-slack-channel-bots","version":"0.4.1","author":{"name":"Gabe Mahoney"},"license":"MIT","_id":"claude-slack-channel-bots@0.4.1","maintainers":[{"name":"gabemahoney","email":"gmahoney@gmail.com"}],"homepage":"https://github.com/gabemahoney/claude-slack-channel-bots#readme","bugs":{"url":"https://github.com/gabemahoney/claude-slack-channel-bots/issues"},"bin":{"claude-slack-channel-bots":"src/cli.ts"},"dist":{"shasum":"efb3f4c3c89d386a20978e4abfa5a9e4af1514e5","tarball":"https://registry.npmjs.org/claude-slack-channel-bots/-/claude-slack-channel-bots-0.4.1.tgz","fileCount":26,"integrity":"sha512-lo96xGqypTyoi4dNmiKznOSrrvdc3i93gsuwZP5IwoIEeoftaLaAOUAXFb4jw165z+ewaiPGAPI5qcYaCaNdEA==","signatures":[{"sig":"MEUCIQCqYo8AcU6xtKldj8fRVihaVbLvZddn8lcQ9bEpju3DYgIgRlNNQYKEJTdehANbcaTA4LQ6XVzJatBz8rrTRESjaXk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":217338},"type":"module","engines":{"bun":">=1.0.0"},"gitHead":"3a8f5486905defa91d410365f17c7e79dce98112","scripts":{"test":"bun test","start":"bun install --no-summary && bun src/server.ts","typecheck":"tsc --noEmit","postinstall":"bun src/postinstall.ts"},"_npmUser":{"name":"gabemahoney","email":"gmahoney@gmail.com"},"repository":{"url":"git+https://github.com/gabemahoney/claude-slack-channel-bots.git","type":"git"},"_npmVersion":"10.9.7","description":"Multi-session Slack-to-Claude bridge — run multiple Claude Code bots across Slack channels via Socket Mode","directories":{},"_nodeVersion":"22.22.2","dependencies":{"@slack/web-api":"^7.0.0","@slack/socket-mode":"^2.0.0","@modelcontextprotocol/sdk":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"@types/bun":"^1.0.0","typescript":"^5.4.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-slack-channel-bots_0.4.1_1775339788376_0.457644903366923","host":"s3://npm-registry-packages-npm-production"}},"0.4.2":{"name":"claude-slack-channel-bots","version":"0.4.2","author":{"name":"Gabe Mahoney"},"license":"MIT","_id":"claude-slack-channel-bots@0.4.2","maintainers":[{"name":"gabemahoney","email":"gmahoney@gmail.com"}],"homepage":"https://github.com/gabemahoney/claude-slack-channel-bots#readme","bugs":{"url":"https://github.com/gabemahoney/claude-slack-channel-bots/issues"},"bin":{"claude-slack-channel-bots":"src/cli.ts"},"dist":{"shasum":"96cc58ab1484984984889a844369ed18ae34f3e4","tarball":"https://registry.npmjs.org/claude-slack-channel-bots/-/claude-slack-channel-bots-0.4.2.tgz","fileCount":26,"integrity":"sha512-a34ADuqQ+eFtuQzmRkrSK9HFa6CPPb60ltxw24vv2+QlZIxvk6pERnAZTu2OyDj1f9Btgr1enIunNcfvgWry7g==","signatures":[{"sig":"MEYCIQCahRRtNN2PcBW+kdx7RiPfqyEoS82wiU9WMe3LIkdAiQIhAIjCnAjp9l6WkrapPaUJb03gEibVNkGN2nR0RCiByufa","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":218378},"type":"module","engines":{"bun":">=1.0.0"},"gitHead":"2ad48ff181a4ab2591c06d88f63837db0ee52745","scripts":{"test":"bun test","start":"bun install --no-summary && bun src/server.ts","typecheck":"tsc --noEmit","postinstall":"bun src/postinstall.ts"},"_npmUser":{"name":"gabemahoney","email":"gmahoney@gmail.com"},"repository":{"url":"git+https://github.com/gabemahoney/claude-slack-channel-bots.git","type":"git"},"_npmVersion":"10.9.7","description":"Multi-session Slack-to-Claude bridge — run multiple Claude Code bots across Slack channels via Socket Mode","directories":{},"_nodeVersion":"22.22.2","dependencies":{"@slack/web-api":"^7.0.0","@slack/socket-mode":"^2.0.0","@modelcontextprotocol/sdk":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"@types/bun":"^1.0.0","typescript":"^5.4.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-slack-channel-bots_0.4.2_1775346796075_0.6817883039155541","host":"s3://npm-registry-packages-npm-production"}},"0.5.0":{"name":"claude-slack-channel-bots","version":"0.5.0","author":{"name":"Gabe Mahoney"},"license":"MIT","_id":"claude-slack-channel-bots@0.5.0","maintainers":[{"name":"gabemahoney","email":"gmahoney@gmail.com"}],"homepage":"https://github.com/gabemahoney/claude-slack-channel-bots#readme","bugs":{"url":"https://github.com/gabemahoney/claude-slack-channel-bots/issues"},"bin":{"claude-slack-channel-bots":"src/cli.ts"},"dist":{"shasum":"de402bd58ff0254dae4b19333b4db641625cbde6","tarball":"https://registry.npmjs.org/claude-slack-channel-bots/-/claude-slack-channel-bots-0.5.0.tgz","fileCount":26,"integrity":"sha512-+zpPXCd6ZxnYTtsZa4IecpyMrWEXio0fG23TKPJviM/z/6drvsGpH9U521cQ5SS+uBPEyNrG7sVcbFbk1Kv9Kw==","signatures":[{"sig":"MEYCIQCoKg5wOkO3ySxDLi1z59kmBwEDbtpKa5Qkzle07X6sjAIhAKkgsuhqVYbOIWHxWXYf99UNRIrD9xFy9zjQNaHZxe0T","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":223383},"type":"module","engines":{"bun":">=1.0.0"},"gitHead":"949fab2cc6f8efb33573608e607feb63f644a020","scripts":{"test":"bun test","start":"bun install --no-summary && bun src/server.ts","typecheck":"tsc --noEmit","postinstall":"bun src/postinstall.ts"},"_npmUser":{"name":"gabemahoney","email":"gmahoney@gmail.com"},"repository":{"url":"git+https://github.com/gabemahoney/claude-slack-channel-bots.git","type":"git"},"_npmVersion":"10.9.7","description":"Multi-session Slack-to-Claude bridge — run multiple Claude Code bots across Slack channels via Socket Mode","directories":{},"_nodeVersion":"22.22.2","dependencies":{"@slack/web-api":"^7.0.0","@slack/socket-mode":"^2.0.0","@modelcontextprotocol/sdk":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"@types/bun":"^1.0.0","typescript":"^5.4.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-slack-channel-bots_0.5.0_1775439439446_0.5973293360728593","host":"s3://npm-registry-packages-npm-production"}},"0.5.1":{"name":"claude-slack-channel-bots","version":"0.5.1","author":{"name":"Gabe Mahoney"},"license":"MIT","_id":"claude-slack-channel-bots@0.5.1","maintainers":[{"name":"gabemahoney","email":"gmahoney@gmail.com"}],"bin":{"claude-slack-channel-bots":"src/cli.ts"},"dist":{"shasum":"127c4725e5eeb88965114c466e7e5a63d5c5592e","tarball":"https://registry.npmjs.org/claude-slack-channel-bots/-/claude-slack-channel-bots-0.5.1.tgz","fileCount":27,"integrity":"sha512-Ca4yVzlRIB1HdqbjN8SOFt8y7DkzYkbNMLrIyCAKBCaXZCH6vhBPtZ2UqkwS4wlnWsRVT9BDQsUubkq0mxkFOw==","signatures":[{"sig":"MEUCIDyLeT8kMysLggcW0MB0Yinnc8pVvBvmfeiWhwOR7actAiEAnmodhoud1yOPKQyGu1ZaMH5aGti/HlJ8kcZUGqZcHng=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":249077},"type":"module","shasum":"127c4725e5eeb88965114c466e7e5a63d5c5592e","engines":{"bun":">=1.0.0"},"scripts":{"test":"bun test","start":"bun install --no-summary && bun src/server.ts","typecheck":"tsc --noEmit","postinstall":"bun src/postinstall.ts"},"_npmUser":{"name":"gabemahoney","email":"gmahoney@gmail.com"},"_integrity":"sha512-Ca4yVzlRIB1HdqbjN8SOFt8y7DkzYkbNMLrIyCAKBCaXZCH6vhBPtZ2UqkwS4wlnWsRVT9BDQsUubkq0mxkFOw==","repository":{"url":"git+https://github.com/gabemahoney/claude-slack-channel-bots.git","type":"git"},"_npmVersion":"10.8.3","description":"Multi-session Slack-to-Claude bridge — run multiple Claude Code bots across Slack channels via Socket Mode","directories":{},"_nodeVersion":"24.3.0","dependencies":{"@slack/web-api":"^7.0.0","@slack/socket-mode":"^2.0.0","@modelcontextprotocol/sdk":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"@types/bun":"^1.0.0","typescript":"^5.4.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-slack-channel-bots_0.5.1_1779596977194_0.3412284027119237","host":"s3://npm-registry-packages-npm-production"}},"0.6.0":{"name":"claude-slack-channel-bots","version":"0.6.0","author":{"name":"Gabe Mahoney"},"license":"MIT","_id":"claude-slack-channel-bots@0.6.0","maintainers":[{"name":"gabemahoney","email":"gmahoney@gmail.com"}],"bin":{"claude-slack-channel-bots":"src/cli.ts"},"dist":{"shasum":"5f275ff688fd066abba317be8642d76800977d1d","tarball":"https://registry.npmjs.org/claude-slack-channel-bots/-/claude-slack-channel-bots-0.6.0.tgz","fileCount":31,"integrity":"sha512-VPa3YWFQdD+cc0pzmaE01zWVTtecOGx6bXyL7ewJYoYQBYRaIRx9rTK5TmV4s/0/k3xu92PHPSr+WYeEIX5VqA==","signatures":[{"sig":"MEQCIFKli2ivGQOnpmzsGlJYPa4HyxtRNtgcjjqfgKz3h1sJAiBmFeAbaQTEH5Ngc5MXCegxGL5hsAc1VhjN5GS8MQFqSQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":281810},"type":"module","shasum":"5f275ff688fd066abba317be8642d76800977d1d","engines":{"bun":">=1.0.0"},"scripts":{"test":"bun test","start":"bun install --no-summary && bun src/server.ts","pretest":"bun scripts/fixup-bun-cache.ts && bun scripts/check-no-toplevel-mock-module.ts","typecheck":"tsc --noEmit","check:mocks":"bun scripts/check-no-toplevel-mock-module.ts","postinstall":"bun src/postinstall.ts && bun scripts/fixup-bun-cache.ts"},"_npmUser":{"name":"gabemahoney","email":"gmahoney@gmail.com"},"_integrity":"sha512-VPa3YWFQdD+cc0pzmaE01zWVTtecOGx6bXyL7ewJYoYQBYRaIRx9rTK5TmV4s/0/k3xu92PHPSr+WYeEIX5VqA==","repository":{"url":"git+https://github.com/gabemahoney/claude-slack-channel-bots.git","type":"git"},"_npmVersion":"10.8.3","description":"Multi-session Slack-to-Claude bridge — run multiple Claude Code bots across Slack channels via Socket Mode","directories":{},"_nodeVersion":"24.3.0","dependencies":{"@slack/web-api":"^7.0.0","agent-director":"^0.5.1","@slack/socket-mode":"^2.0.0","@modelcontextprotocol/sdk":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"@types/bun":"^1.0.0","typescript":"^5.4.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-slack-channel-bots_0.6.0_1779757703610_0.31718264332007995","host":"s3://npm-registry-packages-npm-production"}},"0.6.1":{"name":"claude-slack-channel-bots","version":"0.6.1","author":{"name":"Gabe Mahoney"},"license":"MIT","_id":"claude-slack-channel-bots@0.6.1","maintainers":[{"name":"gabemahoney","email":"gmahoney@gmail.com"}],"homepage":"https://github.com/gabemahoney/claude-slack-channel-bots#readme","bugs":{"url":"https://github.com/gabemahoney/claude-slack-channel-bots/issues"},"bin":{"claude-slack-channel-bots":"src/cli.ts"},"dist":{"shasum":"1ea332d80d334043e87af507c65b630e2e289713","tarball":"https://registry.npmjs.org/claude-slack-channel-bots/-/claude-slack-channel-bots-0.6.1.tgz","fileCount":31,"integrity":"sha512-asqrjYMziRYkQZ+LJkneItfqWRapX7rw7GfG22RtKQPq5Eme16Db1HhPvzyL4EsAYBA+dqP0iSk7mddvcOuMxg==","signatures":[{"sig":"MEQCIEF+VSJIsl4DFn0ymrtZTC9hsNmWriypIQ0gQgAtrk+3AiBT39bRH+TipksyitOw2g6uNS5/PyssA4dBAkYdpSTFKQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":306105},"type":"module","_from":"file:/home/horde/projects/claude-slack-channel-bots-project/claude-slack-channel-bots-main/claude-slack-channel-bots-0.6.1.tgz","engines":{"bun":">=1.0.0"},"scripts":{"test":"bun test","start":"bun install --no-summary && bun src/server.ts","pretest":"bun scripts/fixup-bun-cache.ts && bun scripts/check-no-toplevel-mock-module.ts","typecheck":"tsc --noEmit","check:mocks":"bun scripts/check-no-toplevel-mock-module.ts","postinstall":"bun src/postinstall.ts && bun scripts/fixup-bun-cache.ts"},"_npmUser":{"name":"gabemahoney","email":"gmahoney@gmail.com"},"_resolved":"/home/horde/projects/claude-slack-channel-bots-project/claude-slack-channel-bots-main/claude-slack-channel-bots-0.6.1.tgz","_integrity":"sha512-asqrjYMziRYkQZ+LJkneItfqWRapX7rw7GfG22RtKQPq5Eme16Db1HhPvzyL4EsAYBA+dqP0iSk7mddvcOuMxg==","repository":{"url":"git+https://github.com/gabemahoney/claude-slack-channel-bots.git","type":"git"},"_npmVersion":"10.8.2","description":"Multi-session Slack-to-Claude bridge — run multiple Claude Code bots across Slack channels via Socket Mode","directories":{},"_nodeVersion":"20.20.2","dependencies":{"@slack/web-api":"^7.0.0","agent-director":"^0.5.5","@slack/socket-mode":"^2.0.0","@modelcontextprotocol/sdk":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"@types/bun":"^1.0.0","typescript":"^5.4.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-slack-channel-bots_0.6.1_1780101657664_0.23037205709959085","host":"s3://npm-registry-packages-npm-production"}},"0.6.2":{"name":"claude-slack-channel-bots","version":"0.6.2","author":{"name":"Gabe Mahoney"},"license":"MIT","_id":"claude-slack-channel-bots@0.6.2","maintainers":[{"name":"gabemahoney","email":"gmahoney@gmail.com"}],"homepage":"https://github.com/gabemahoney/claude-slack-channel-bots#readme","bugs":{"url":"https://github.com/gabemahoney/claude-slack-channel-bots/issues"},"bin":{"claude-slack-channel-bots":"src/cli.ts"},"dist":{"shasum":"fe7f9a87e63054224d9fbcc8a91df57129cf8b35","tarball":"https://registry.npmjs.org/claude-slack-channel-bots/-/claude-slack-channel-bots-0.6.2.tgz","fileCount":31,"integrity":"sha512-18JDYx4MwvjO4rCUbeoNmtNrSoTzRDTK+Dt577rDqXULWalMzLk0rLVnG66LNG1L5ACYejknc47oQkSU2UmkGg==","signatures":[{"sig":"MEUCICOJ/XTzvesxTTUqbHwYDOHe+6XCGJ1LpG0xwx9pU8yYAiEA2pa32wcbg7uiE8uaoV30XDBEn4c7zUr3dSGXeNoMw1A=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":306105},"type":"module","_from":"file:/home/horde/projects/claude-slack-channel-bots-project/claude-slack-channel-bots-main/claude-slack-channel-bots-0.6.2.tgz","engines":{"bun":">=1.0.0"},"scripts":{"test":"bun test","start":"bun install --no-summary && bun src/server.ts","pretest":"bun scripts/fixup-bun-cache.ts && bun scripts/check-no-toplevel-mock-module.ts","typecheck":"tsc --noEmit","check:mocks":"bun scripts/check-no-toplevel-mock-module.ts","postinstall":"bun src/postinstall.ts && bun scripts/fixup-bun-cache.ts"},"_npmUser":{"name":"gabemahoney","email":"gmahoney@gmail.com"},"_resolved":"/home/horde/projects/claude-slack-channel-bots-project/claude-slack-channel-bots-main/claude-slack-channel-bots-0.6.2.tgz","_integrity":"sha512-18JDYx4MwvjO4rCUbeoNmtNrSoTzRDTK+Dt577rDqXULWalMzLk0rLVnG66LNG1L5ACYejknc47oQkSU2UmkGg==","repository":{"url":"git+https://github.com/gabemahoney/claude-slack-channel-bots.git","type":"git"},"_npmVersion":"10.8.2","description":"Multi-session Slack-to-Claude bridge — run multiple Claude Code bots across Slack channels via Socket Mode","directories":{},"_nodeVersion":"20.20.2","dependencies":{"@slack/web-api":"^7.0.0","agent-director":"^0.5.5","@slack/socket-mode":"^2.0.0","@modelcontextprotocol/sdk":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"@types/bun":"^1.0.0","typescript":"^5.4.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-slack-channel-bots_0.6.2_1780112538223_0.016619120542085586","host":"s3://npm-registry-packages-npm-production"}},"0.6.3":{"name":"claude-slack-channel-bots","version":"0.6.3","author":{"name":"Gabe Mahoney"},"license":"MIT","_id":"claude-slack-channel-bots@0.6.3","maintainers":[{"name":"gabemahoney","email":"gmahoney@gmail.com"}],"homepage":"https://github.com/gabemahoney/claude-slack-channel-bots#readme","bugs":{"url":"https://github.com/gabemahoney/claude-slack-channel-bots/issues"},"bin":{"claude-slack-channel-bots":"src/cli.ts"},"dist":{"shasum":"bb8983d47189500cb16ed548aaa5b8ff3f6c1fdd","tarball":"https://registry.npmjs.org/claude-slack-channel-bots/-/claude-slack-channel-bots-0.6.3.tgz","fileCount":31,"integrity":"sha512-BbBddFg2laoQYib1FQLm7icjXOwTQfNsJ24fHbWIC0jtemc11v8NJ32B2LVmoFYx705CKEhnVAwmR0cPdnA2CA==","signatures":[{"sig":"MEUCIEB5H78MilEWnbnnKa46Y4Y5LRA63VhFKQsk4aqKFo6kAiEAlzy4vqYmyRDtLno74rJjd5kti8/f4ttrOJIrs2/m9iQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":306904},"type":"module","_from":"file:/home/horde/projects/claude-slack-channel-bots-project/claude-slack-channel-bots-main/claude-slack-channel-bots-0.6.3.tgz","engines":{"bun":">=1.0.0"},"scripts":{"test":"bun test","start":"bun install --no-summary && bun src/server.ts","pretest":"bun scripts/fixup-bun-cache.ts && bun scripts/check-no-toplevel-mock-module.ts","typecheck":"tsc --noEmit","check:mocks":"bun scripts/check-no-toplevel-mock-module.ts","postinstall":"bun src/postinstall.ts && bun scripts/fixup-bun-cache.ts"},"_npmUser":{"name":"gabemahoney","email":"gmahoney@gmail.com"},"_resolved":"/home/horde/projects/claude-slack-channel-bots-project/claude-slack-channel-bots-main/claude-slack-channel-bots-0.6.3.tgz","_integrity":"sha512-BbBddFg2laoQYib1FQLm7icjXOwTQfNsJ24fHbWIC0jtemc11v8NJ32B2LVmoFYx705CKEhnVAwmR0cPdnA2CA==","repository":{"url":"git+https://github.com/gabemahoney/claude-slack-channel-bots.git","type":"git"},"_npmVersion":"10.8.2","description":"Multi-session Slack-to-Claude bridge — run multiple Claude Code bots across Slack channels via Socket Mode","directories":{},"_nodeVersion":"20.20.2","dependencies":{"@slack/web-api":"^7.0.0","agent-director":"^0.5.5","@slack/socket-mode":"^2.0.0","@modelcontextprotocol/sdk":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"semver":"^7.6.0","@types/bun":"^1.0.0","typescript":"^5.4.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-slack-channel-bots_0.6.3_1780115157187_0.2089233492220519","host":"s3://npm-registry-packages-npm-production"}},"0.6.4":{"name":"claude-slack-channel-bots","version":"0.6.4","author":{"name":"Gabe Mahoney"},"license":"MIT","_id":"claude-slack-channel-bots@0.6.4","maintainers":[{"name":"gabemahoney","email":"gmahoney@gmail.com"}],"homepage":"https://github.com/gabemahoney/claude-slack-channel-bots#readme","bugs":{"url":"https://github.com/gabemahoney/claude-slack-channel-bots/issues"},"bin":{"claude-slack-channel-bots":"src/cli.ts"},"dist":{"shasum":"dcdc49c9da08df93bdaa4bc45730ce89eabcbe52","tarball":"https://registry.npmjs.org/claude-slack-channel-bots/-/claude-slack-channel-bots-0.6.4.tgz","fileCount":31,"integrity":"sha512-KpewKvFCDmO4dp7LzQtH43OiVDhRi8+nNU1txrdKfxXNgdo4FkK5ypqzIwhr9HNyl37NjF2GiF/i+IRkKK8ASQ==","signatures":[{"sig":"MEYCIQDMZYW0Y8xGmR2HzEWerKZbGKTAzT1MekS0+zLWpywg2AIhAPMmfGyn0CklTN1zuQoyWAZT7JbHniKdY5ngu5bT10We","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":306904},"type":"module","_from":"file:/home/horde/projects/claude-slack-channel-bots-project/claude-slack-channel-bots-main/claude-slack-channel-bots-0.6.4.tgz","engines":{"bun":">=1.0.0"},"scripts":{"test":"bun test","start":"bun install --no-summary && bun src/server.ts","pretest":"bun scripts/fixup-bun-cache.ts && bun scripts/check-no-toplevel-mock-module.ts","typecheck":"tsc --noEmit","check:mocks":"bun scripts/check-no-toplevel-mock-module.ts","postinstall":"bun src/postinstall.ts && bun scripts/fixup-bun-cache.ts"},"_npmUser":{"name":"gabemahoney","email":"gmahoney@gmail.com"},"_resolved":"/home/horde/projects/claude-slack-channel-bots-project/claude-slack-channel-bots-main/claude-slack-channel-bots-0.6.4.tgz","_integrity":"sha512-KpewKvFCDmO4dp7LzQtH43OiVDhRi8+nNU1txrdKfxXNgdo4FkK5ypqzIwhr9HNyl37NjF2GiF/i+IRkKK8ASQ==","repository":{"url":"git+https://github.com/gabemahoney/claude-slack-channel-bots.git","type":"git"},"_npmVersion":"10.8.2","description":"Multi-session Slack-to-Claude bridge — run multiple Claude Code bots across Slack channels via Socket Mode","directories":{},"_nodeVersion":"20.20.2","dependencies":{"@slack/web-api":"^7.0.0","agent-director":"^0.5.5","@slack/socket-mode":"^2.0.0","@modelcontextprotocol/sdk":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"semver":"^7.6.0","@types/bun":"^1.0.0","typescript":"^5.4.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-slack-channel-bots_0.6.4_1780117305710_0.16401017097562365","host":"s3://npm-registry-packages-npm-production"}},"0.6.5":{"name":"claude-slack-channel-bots","version":"0.6.5","author":{"name":"Gabe Mahoney"},"license":"MIT","_id":"claude-slack-channel-bots@0.6.5","maintainers":[{"name":"gabemahoney","email":"gmahoney@gmail.com"}],"homepage":"https://github.com/gabemahoney/claude-slack-channel-bots#readme","bugs":{"url":"https://github.com/gabemahoney/claude-slack-channel-bots/issues"},"bin":{"claude-slack-channel-bots":"src/cli.ts"},"dist":{"shasum":"67d9f97e381b26dd8c154d0c4aed63029b9df005","tarball":"https://registry.npmjs.org/claude-slack-channel-bots/-/claude-slack-channel-bots-0.6.5.tgz","fileCount":31,"integrity":"sha512-T5ubOjmGvI9NJtJFHa2s4XhjYiNRWJ4AAaVImzoMDOv0MrdS0whDYvu6n7wNBiLMvuhiJL/iylwhlIQwqnt9jA==","signatures":[{"sig":"MEYCIQDyTryIkKZxHqfDmsWZF+HcBZU4rYnNpwb3f7t9zwciWwIhAJcl6SPKgY3YDTH44YY+FFQtVgRe5sDAVVMS+9qMsLf4","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":307027},"type":"module","_from":"file:/home/horde/projects/claude-slack-channel-bots-project/claude-slack-channel-bots-main/claude-slack-channel-bots-0.6.5.tgz","engines":{"bun":">=1.0.0"},"scripts":{"test":"bun test","start":"bun install --no-summary && bun src/server.ts","pretest":"bun scripts/fixup-bun-cache.ts && bun scripts/check-no-toplevel-mock-module.ts","typecheck":"tsc --noEmit","check:mocks":"bun scripts/check-no-toplevel-mock-module.ts","postinstall":"bun src/postinstall.ts && bun scripts/fixup-bun-cache.ts"},"_npmUser":{"name":"gabemahoney","email":"gmahoney@gmail.com"},"_resolved":"/home/horde/projects/claude-slack-channel-bots-project/claude-slack-channel-bots-main/claude-slack-channel-bots-0.6.5.tgz","_integrity":"sha512-T5ubOjmGvI9NJtJFHa2s4XhjYiNRWJ4AAaVImzoMDOv0MrdS0whDYvu6n7wNBiLMvuhiJL/iylwhlIQwqnt9jA==","repository":{"url":"git+https://github.com/gabemahoney/claude-slack-channel-bots.git","type":"git"},"_npmVersion":"10.8.2","description":"Multi-session Slack-to-Claude bridge — run multiple Claude Code bots across Slack channels via Socket Mode","directories":{},"_nodeVersion":"20.20.2","dependencies":{"@slack/web-api":"^7.0.0","agent-director":"^0.5.5","@slack/socket-mode":"^2.0.0","@modelcontextprotocol/sdk":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"semver":"^7.6.0","@types/bun":"^1.0.0","typescript":"^5.4.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-slack-channel-bots_0.6.5_1780118859200_0.2686031571031504","host":"s3://npm-registry-packages-npm-production"}},"0.6.6":{"name":"claude-slack-channel-bots","version":"0.6.6","author":{"name":"Gabe Mahoney"},"license":"MIT","_id":"claude-slack-channel-bots@0.6.6","maintainers":[{"name":"gabemahoney","email":"gmahoney@gmail.com"}],"homepage":"https://github.com/gabemahoney/claude-slack-channel-bots#readme","bugs":{"url":"https://github.com/gabemahoney/claude-slack-channel-bots/issues"},"bin":{"claude-slack-channel-bots":"src/cli.ts"},"dist":{"shasum":"864dec037794fc8d7fd50c77094babaeba8ab111","tarball":"https://registry.npmjs.org/claude-slack-channel-bots/-/claude-slack-channel-bots-0.6.6.tgz","fileCount":31,"integrity":"sha512-zfQb0+8SBmwpVqaAW8TtCUbdcCYaWugeFunsLfSw/54IziD0yL8Zm2C091xwWAWRPKDGlF8NvIYurEVCHENoTg==","signatures":[{"sig":"MEUCIHN+MVFEppvbN9KPDNPy7B39wa82PJULKGazGJb6HR7YAiEAk6O28JNFG0Va1jU9zNmPfE53lYUdJDArD7NNbKACzSc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":307027},"type":"module","_from":"file:/home/horde/projects/claude-slack-channel-bots-project/claude-slack-channel-bots-main/claude-slack-channel-bots-0.6.6.tgz","engines":{"bun":">=1.0.0"},"scripts":{"test":"bun test","start":"bun install --no-summary && bun src/server.ts","pretest":"bun scripts/fixup-bun-cache.ts && bun scripts/check-no-toplevel-mock-module.ts","typecheck":"tsc --noEmit","check:mocks":"bun scripts/check-no-toplevel-mock-module.ts","postinstall":"bun src/postinstall.ts && bun scripts/fixup-bun-cache.ts"},"_npmUser":{"name":"gabemahoney","email":"gmahoney@gmail.com"},"_resolved":"/home/horde/projects/claude-slack-channel-bots-project/claude-slack-channel-bots-main/claude-slack-channel-bots-0.6.6.tgz","_integrity":"sha512-zfQb0+8SBmwpVqaAW8TtCUbdcCYaWugeFunsLfSw/54IziD0yL8Zm2C091xwWAWRPKDGlF8NvIYurEVCHENoTg==","repository":{"url":"git+https://github.com/gabemahoney/claude-slack-channel-bots.git","type":"git"},"_npmVersion":"10.8.2","description":"Multi-session Slack-to-Claude bridge — run multiple Claude Code bots across Slack channels via Socket Mode","directories":{},"_nodeVersion":"20.20.2","dependencies":{"@slack/web-api":"^7.0.0","agent-director":"^0.5.5","@slack/socket-mode":"^2.0.0","@modelcontextprotocol/sdk":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"semver":"^7.6.0","@types/bun":"^1.0.0","typescript":"^5.4.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-slack-channel-bots_0.6.6_1780122084781_0.26893706289691766","host":"s3://npm-registry-packages-npm-production"}},"0.6.7":{"name":"claude-slack-channel-bots","version":"0.6.7","author":{"name":"Gabe Mahoney"},"license":"MIT","_id":"claude-slack-channel-bots@0.6.7","maintainers":[{"name":"gabemahoney","email":"gmahoney@gmail.com"}],"homepage":"https://github.com/gabemahoney/claude-slack-channel-bots#readme","bugs":{"url":"https://github.com/gabemahoney/claude-slack-channel-bots/issues"},"bin":{"claude-slack-channel-bots":"src/cli.ts"},"dist":{"shasum":"1ccac49433430716bf5680b46fde1a4a153da01d","tarball":"https://registry.npmjs.org/claude-slack-channel-bots/-/claude-slack-channel-bots-0.6.7.tgz","fileCount":32,"integrity":"sha512-q5V7ezMa2lmtT9XRuESrvx2Il4peobH2Mt9oCO089rYn3LBuuGYc/j/aFZfh32K4HGSE9ObPyx45kXcN2svanw==","signatures":[{"sig":"MEUCIQCIkghABz1XBSpuFfwfCRC28poBnpiLTTVum3hcnLJ/CAIgLB167p2dUtTFODWW54+SAFGbDR8yLS0ggg8opHLv0ig=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":336845},"type":"module","engines":{"bun":">=1.0.0"},"gitHead":"b6110168b306d4d6943944b0c972a441b5343550","scripts":{"test":"bun test","start":"bun install --no-summary && bun src/server.ts","pretest":"bun scripts/fixup-bun-cache.ts && bun scripts/check-no-toplevel-mock-module.ts","typecheck":"tsc --noEmit","check:mocks":"bun scripts/check-no-toplevel-mock-module.ts","postinstall":"bun src/postinstall.ts && bun scripts/fixup-bun-cache.ts"},"_npmUser":{"name":"gabemahoney","email":"gmahoney@gmail.com"},"repository":{"url":"git+https://github.com/gabemahoney/claude-slack-channel-bots.git","type":"git"},"_npmVersion":"10.8.2","description":"Multi-session Slack-to-Claude bridge — run multiple Claude Code bots across Slack channels via Socket Mode","directories":{},"_nodeVersion":"20.20.2","dependencies":{"@slack/web-api":"^7.0.0","agent-director":"^0.6.3","@slack/socket-mode":"^2.0.0","@modelcontextprotocol/sdk":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"semver":"^7.6.0","@types/bun":"^1.0.0","typescript":"^5.4.0"},"_npmOperationalInternal":{"tmp":"tmp/claude-slack-channel-bots_0.6.7_1780381252322_0.30705268287935006","host":"s3://npm-registry-packages-npm-production"}},"0.7.0":{"name":"claude-slack-channel-bots","version":"0.7.0","author":{"name":"Gabe Mahoney"},"license":"MIT","_id":"claude-slack-channel-bots@0.7.0","maintainers":[{"name":"gabemahoney","email":"gmahoney@gmail.com"}],"homepage":"https://github.com/gabemahoney/claude-slack-channel-bots#readme","bugs":{"url":"https://github.com/gabemahoney/claude-slack-channel-bots/issues"},"bin":{"claude-slack-channel-bots":"src/cli.ts"},"dist":{"shasum":"6c0435c8bd234e167b34de4a7666bf5dd1088931","tarball":"https://registry.npmjs.org/claude-slack-channel-bots/-/claude-slack-channel-bots-0.7.0.tgz","fileCount":35,"integrity":"sha512-V3bHREiB+BT9GaG02Z1OaC9OGVxzPnQi4nnORfRQ2b9Edg8yhVxSKpg+uDzMSKUEfHpP6B8zwTBffIRsgjU5Lw==","signatures":[{"sig":"MEQCIHOjJko+IR8OEr2XyVKHJjOnp6INjdWyQiDN4RROnRoGAiAQ/hGRzQ7OXtW6jVcKyQwY6Omb77/WDJFESmJf4tgYdw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":361402},"type":"module","_from":"file:/home/horde/projects/claude-slack-channel-bots-project/claude-slack-channel-bots-main/claude-slack-channel-bots-0.7.0.tgz","engines":{"bun":">=1.0.0"},"scripts":{"test":"bun test","start":"bun install --no-summary && bun src/server.ts","pretest":"bun scripts/fixup-bun-cache.ts && bun scripts/check-no-toplevel-mock-module.ts","typecheck":"tsc --noEmit","check:mocks":"bun scripts/check-no-toplevel-mock-module.ts","postinstall":"bun src/postinstall.ts && bun scripts/fixup-bun-cache.ts","install-check":"bun scripts/install-check.ts"},"_npmUser":{"name":"gabemahoney","email":"gmahoney@gmail.com"},"_resolved":"/home/horde/projects/claude-slack-channel-bots-project/claude-slack-channel-bots-main/claude-slack-channel-bots-0.7.0.tgz","_integrity":"sha512-V3bHREiB+BT9GaG02Z1OaC9OGVxzPnQi4nnORfRQ2b9Edg8yhVxSKpg+uDzMSKUEfHpP6B8zwTBffIRsgjU5Lw==","repository":{"url":"git+https://github.com/gabemahoney/claude-slack-channel-bots.git","type":"git"},"_npmVersion":"10.8.2","description":"Multi-session Slack-to-Claude bridge — run multiple Claude Code bots across Slack channels via Socket Mode","directories":{},"_nodeVersion":"20.20.2","dependencies":{"semver":"^7.6.0","@slack/web-api":"^7.0.0","agent-director":"^0.7.0","@slack/socket-mode":"^2.0.0","@modelcontextprotocol/sdk":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"@types/bun":"^1.0.0","typescript":"^5.4.0","@types/semver":"^7.7.1"},"_npmOperationalInternal":{"tmp":"tmp/claude-slack-channel-bots_0.7.0_1780515401469_0.6486344212727972","host":"s3://npm-registry-packages-npm-production"}},"0.7.1":{"name":"claude-slack-channel-bots","version":"0.7.1","author":{"name":"Gabe Mahoney"},"license":"MIT","_id":"claude-slack-channel-bots@0.7.1","maintainers":[{"name":"gabemahoney","email":"gmahoney@gmail.com"}],"homepage":"https://github.com/gabemahoney/claude-slack-channel-bots#readme","bugs":{"url":"https://github.com/gabemahoney/claude-slack-channel-bots/issues"},"bin":{"claude-slack-channel-bots":"src/cli.ts"},"dist":{"shasum":"18946e2b2a041a26cd1de5673a6491f56961cd71","tarball":"https://registry.npmjs.org/claude-slack-channel-bots/-/claude-slack-channel-bots-0.7.1.tgz","fileCount":36,"integrity":"sha512-3GsL1xKlqJ19Z48A6xVfX0VN0mnFXn7uTWYHDaLMvdiK2h0RS89lOuGl8j4uYEvgqcFmMY+ywkaz1IX2oKNBjA==","signatures":[{"sig":"MEQCH2QgRyjaeawubIeVXOMox7965LiICVx4xhKF/F0xeA4CIQDAHiL8gdXlElzGKxNU/YQAnkyi4AQsPgUDU7QFUTsADw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":363712},"type":"module","_from":"file:/home/horde/projects/claude-slack-channel-bots-project/claude-slack-channel-bots-main/claude-slack-channel-bots-0.7.1.tgz","engines":{"bun":">=1.0.0"},"scripts":{"test":"bun test","start":"bun install --no-summary && bun src/server.ts","pretest":"bun scripts/fixup-bun-cache.ts && bun scripts/check-no-toplevel-mock-module.ts","typecheck":"tsc --noEmit","check:mocks":"bun scripts/check-no-toplevel-mock-module.ts","postinstall":"bun src/postinstall.ts && bun scripts/fixup-bun-cache.ts","install-check":"bun scripts/install-check.ts"},"_npmUser":{"name":"gabemahoney","email":"gmahoney@gmail.com"},"_resolved":"/home/horde/projects/claude-slack-channel-bots-project/claude-slack-channel-bots-main/claude-slack-channel-bots-0.7.1.tgz","_integrity":"sha512-3GsL1xKlqJ19Z48A6xVfX0VN0mnFXn7uTWYHDaLMvdiK2h0RS89lOuGl8j4uYEvgqcFmMY+ywkaz1IX2oKNBjA==","repository":{"url":"git+https://github.com/gabemahoney/claude-slack-channel-bots.git","type":"git"},"_npmVersion":"10.8.2","description":"Multi-session Slack-to-Claude bridge — run multiple Claude Code bots across Slack channels via Socket Mode","directories":{},"_nodeVersion":"20.20.2","dependencies":{"semver":"^7.6.0","@slack/web-api":"^7.0.0","agent-director":"^0.7.0","@slack/socket-mode":"^2.0.0","@modelcontextprotocol/sdk":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"@types/bun":"^1.0.0","typescript":"^5.4.0","@types/semver":"^7.7.1"},"_npmOperationalInternal":{"tmp":"tmp/claude-slack-channel-bots_0.7.1_1780545258254_0.12552457652697857","host":"s3://npm-registry-packages-npm-production"}},"0.7.2":{"name":"claude-slack-channel-bots","version":"0.7.2","author":{"name":"Gabe Mahoney"},"license":"MIT","_id":"claude-slack-channel-bots@0.7.2","maintainers":[{"name":"gabemahoney","email":"gmahoney@gmail.com"}],"homepage":"https://github.com/gabemahoney/claude-slack-channel-bots#readme","bugs":{"url":"https://github.com/gabemahoney/claude-slack-channel-bots/issues"},"bin":{"claude-slack-channel-bots":"src/cli.ts"},"dist":{"shasum":"8bf4692e94873960141919afe15cbb4b8a1dc2bf","tarball":"https://registry.npmjs.org/claude-slack-channel-bots/-/claude-slack-channel-bots-0.7.2.tgz","fileCount":37,"integrity":"sha512-i2KclQHvX3lgxG0V5h8FqDIZJtQVlvyyEq6eYERGuiUQ/6TcEteTlkbGOrj6UDxGjyNHjQWIaDT8kzG1LXJUVQ==","signatures":[{"sig":"MEUCIA6zAVR1iLfwC0bTS2uzS39dk/pe/d97EbCb9Qj9n5iHAiEAtjY3gCf1pLD765DSL7a2FL2mXXUF4uX2nSvVIN9t00w=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":384245},"type":"module","_from":"file:/home/horde/projects/claude-slack-channel-bots-project/claude-slack-channel-bots-main/claude-slack-channel-bots-0.7.2.tgz","engines":{"bun":">=1.0.0"},"scripts":{"test":"bun test","start":"bun install --no-summary && bun src/server.ts","pretest":"bun scripts/fixup-bun-cache.ts && bun scripts/check-no-toplevel-mock-module.ts","typecheck":"tsc --noEmit","check:mocks":"bun scripts/check-no-toplevel-mock-module.ts","postinstall":"bun src/postinstall.ts && bun scripts/fixup-bun-cache.ts","install-check":"bun scripts/install-check.ts"},"_npmUser":{"name":"gabemahoney","email":"gmahoney@gmail.com"},"_resolved":"/home/horde/projects/claude-slack-channel-bots-project/claude-slack-channel-bots-main/claude-slack-channel-bots-0.7.2.tgz","_integrity":"sha512-i2KclQHvX3lgxG0V5h8FqDIZJtQVlvyyEq6eYERGuiUQ/6TcEteTlkbGOrj6UDxGjyNHjQWIaDT8kzG1LXJUVQ==","repository":{"url":"git+https://github.com/gabemahoney/claude-slack-channel-bots.git","type":"git"},"_npmVersion":"10.8.2","description":"Multi-session Slack-to-Claude bridge — run multiple Claude Code bots across Slack channels via Socket Mode","directories":{},"_nodeVersion":"20.20.2","dependencies":{"semver":"^7.6.0","@slack/web-api":"^7.0.0","agent-director":"^0.7.0","@slack/socket-mode":"^2.0.0","@modelcontextprotocol/sdk":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"@types/bun":"^1.0.0","typescript":"^5.4.0","@types/semver":"^7.7.1"},"_npmOperationalInternal":{"tmp":"tmp/claude-slack-channel-bots_0.7.2_1780773337840_0.7149665742481532","host":"s3://npm-registry-packages-npm-production"}},"0.8.0":{"name":"claude-slack-channel-bots","version":"0.8.0","author":{"name":"Gabe Mahoney"},"license":"MIT","_id":"claude-slack-channel-bots@0.8.0","maintainers":[{"name":"gabemahoney","email":"gmahoney@gmail.com"}],"homepage":"https://github.com/gabemahoney/claude-slack-channel-bots#readme","bugs":{"url":"https://github.com/gabemahoney/claude-slack-channel-bots/issues"},"bin":{"claude-slack-channel-bots":"src/cli.ts"},"dist":{"shasum":"6eda2996b0919e09b7c13a2b2cf3819aed96f34d","tarball":"https://registry.npmjs.org/claude-slack-channel-bots/-/claude-slack-channel-bots-0.8.0.tgz","fileCount":38,"integrity":"sha512-hzBYSyg2OtXtKB/1WbWtjo9cayVUDk08fmjumQY1YNgszcJGaNjD0FiWMVnIP4UZIhr+ZdGRvFsUaiueOGmeBg==","signatures":[{"sig":"MEQCIBINFMOtnJrLgjb0uxpOnC50g5vdH6TK/rXNP1QcOeIQAiBrZf3ktUj1Vqnf0UQBz1363fA5gQm36J5wmkskHpYEnA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":406068},"type":"module","_from":"file:/home/horde/projects/claude-slack-channel-bots-project/claude-slack-channel-bots-main/claude-slack-channel-bots-0.8.0.tgz","engines":{"bun":">=1.0.0"},"scripts":{"test":"bun test","start":"bun install --no-summary && bun src/server.ts","pretest":"bun scripts/fixup-bun-cache.ts && bun scripts/check-no-toplevel-mock-module.ts","typecheck":"tsc --noEmit","check:mocks":"bun scripts/check-no-toplevel-mock-module.ts","postinstall":"bun src/postinstall.ts && bun scripts/fixup-bun-cache.ts","install-check":"bun scripts/install-check.ts"},"_npmUser":{"name":"gabemahoney","email":"gmahoney@gmail.com"},"_resolved":"/home/horde/projects/claude-slack-channel-bots-project/claude-slack-channel-bots-main/claude-slack-channel-bots-0.8.0.tgz","_integrity":"sha512-hzBYSyg2OtXtKB/1WbWtjo9cayVUDk08fmjumQY1YNgszcJGaNjD0FiWMVnIP4UZIhr+ZdGRvFsUaiueOGmeBg==","repository":{"url":"git+https://github.com/gabemahoney/claude-slack-channel-bots.git","type":"git"},"_npmVersion":"10.8.2","description":"Multi-session Slack-to-Claude bridge — run multiple Claude Code bots across Slack channels via Socket Mode","directories":{},"_nodeVersion":"20.20.2","dependencies":{"semver":"^7.6.0","@slack/web-api":"^7.0.0","agent-director":"^0.7.8","@slack/socket-mode":"^2.0.0","@modelcontextprotocol/sdk":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"@types/bun":"^1.0.0","typescript":"^5.4.0","@types/semver":"^7.7.1"},"_npmOperationalInternal":{"tmp":"tmp/claude-slack-channel-bots_0.8.0_1780894426804_0.27112174775904063","host":"s3://npm-registry-packages-npm-production"}},"0.8.1":{"name":"claude-slack-channel-bots","version":"0.8.1","author":{"name":"Gabe Mahoney"},"license":"MIT","_id":"claude-slack-channel-bots@0.8.1","maintainers":[{"name":"gabemahoney","email":"gmahoney@gmail.com"}],"homepage":"https://github.com/gabemahoney/claude-slack-channel-bots#readme","bugs":{"url":"https://github.com/gabemahoney/claude-slack-channel-bots/issues"},"bin":{"claude-slack-channel-bots":"src/cli.ts"},"dist":{"shasum":"173083233c0fdeabd9a34d9683b8898cab8e9287","tarball":"https://registry.npmjs.org/claude-slack-channel-bots/-/claude-slack-channel-bots-0.8.1.tgz","fileCount":38,"integrity":"sha512-dWBQDXb7hTJqTdk4M/3Sb10cuw0P9pDvwwISdx/tzdXipLDCAZjyupObNrilHMHavWLq+XFPHEPFgiaeicun9g==","signatures":[{"sig":"MEYCIQDAkD6Ngg9ae2NzXjrSLoVNLuqVRcwXVwmN84SRXuE6WwIhAJUPq+jsgW9a/eoHSjrA3DcTIU5mf8kQ4gxaCD0p3wOW","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCIHV42RaJyek1SZLChy2rj2knCkeEWpu2CiXSxgoOc9VNAiBeYvnEh6syRNRyRNQAEYZspA79WNxHfFratSZ017ol8A==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":416906},"type":"module","_from":"file:/Users/gmahoney/projects/claude-slack-channel-bots/claude-slack-channel-bots-0.8.1.tgz","engines":{"bun":">=1.0.0"},"scripts":{"test":"bun test","start":"bun install --no-summary && bun src/server.ts","pretest":"bun scripts/fixup-bun-cache.ts && bun scripts/check-no-toplevel-mock-module.ts","typecheck":"tsc --noEmit","check:mocks":"bun scripts/check-no-toplevel-mock-module.ts","postinstall":"bun src/postinstall.ts && bun scripts/fixup-bun-cache.ts","install-check":"bun scripts/install-check.ts"},"_npmUser":{"name":"gabemahoney","email":"gmahoney@gmail.com"},"_resolved":"/Users/gmahoney/projects/claude-slack-channel-bots/claude-slack-channel-bots-0.8.1.tgz","_integrity":"sha512-dWBQDXb7hTJqTdk4M/3Sb10cuw0P9pDvwwISdx/tzdXipLDCAZjyupObNrilHMHavWLq+XFPHEPFgiaeicun9g==","repository":{"url":"git+https://github.com/gabemahoney/claude-slack-channel-bots.git","type":"git"},"_npmVersion":"10.9.2","description":"Multi-session Slack-to-Claude bridge — run multiple Claude Code bots across Slack channels via Socket Mode","directories":{},"_nodeVersion":"23.9.0","dependencies":{"semver":"^7.6.0","@slack/web-api":"^7.0.0","agent-director":"^0.7.8","@slack/socket-mode":"^2.0.0","@modelcontextprotocol/sdk":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"@types/bun":"^1.0.0","typescript":"^5.4.0","@types/semver":"^7.7.1"},"_npmOperationalInternal":{"tmp":"tmp/claude-slack-channel-bots_0.8.1_1789703999983_0.9921991878736938","host":"s3://npm-registry-packages-npm-production"}},"0.8.2":{"name":"claude-slack-channel-bots","version":"0.8.2","author":{"name":"Gabe Mahoney"},"license":"MIT","_id":"claude-slack-channel-bots@0.8.2","maintainers":[{"name":"gabemahoney","email":"gmahoney@gmail.com"}],"homepage":"https://github.com/gabemahoney/claude-slack-channel-bots#readme","bugs":{"url":"https://github.com/gabemahoney/claude-slack-channel-bots/issues"},"bin":{"claude-slack-channel-bots":"src/cli.ts"},"dist":{"shasum":"d594e1b67bc8155301bb5715734740dd56fe2269","tarball":"https://registry.npmjs.org/claude-slack-channel-bots/-/claude-slack-channel-bots-0.8.2.tgz","fileCount":38,"integrity":"sha512-NRfFJzHVLFDdatUTr6sYgF42PGDlfHGDPxraXt3eO4oaYj1+YkCyTrCbBVrNPblUD9afDJFl43ZikfVsjtEqZA==","signatures":[{"sig":"MEUCIH0q0nNJoo/cVWH5p1zo/CQo/kwjtNkizcycHHbJ3FL5AiEAisOL+xBDC08CqEqUCUJbdryANcd6QYBaLciRrUeRXkQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQD5N1EgZJouvdXYLKWxw9hhYQ2ob7HqhrqEZWBEjLR/OwIgGuui1fyl1XmpoSmPAvK/zJnathi+J2lCq8+UxEexSec=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":420527},"type":"module","_from":"file:/home/gmahoney/projects/claude_slack_channel_bots_project/claude-slack-channel-bots/claude-slack-channel-bots-0.8.2.tgz","engines":{"bun":">=1.0.0"},"scripts":{"test":"bun test","start":"bun install --no-summary && bun src/server.ts","pretest":"bun scripts/fixup-bun-cache.ts && bun scripts/check-no-toplevel-mock-module.ts","typecheck":"tsc --noEmit","check:mocks":"bun scripts/check-no-toplevel-mock-module.ts","postinstall":"bun src/postinstall.ts && bun scripts/fixup-bun-cache.ts","install-check":"bun scripts/install-check.ts"},"_npmUser":{"name":"gabemahoney","email":"gmahoney@gmail.com"},"_resolved":"/home/gmahoney/projects/claude_slack_channel_bots_project/claude-slack-channel-bots/claude-slack-channel-bots-0.8.2.tgz","_integrity":"sha512-NRfFJzHVLFDdatUTr6sYgF42PGDlfHGDPxraXt3eO4oaYj1+YkCyTrCbBVrNPblUD9afDJFl43ZikfVsjtEqZA==","repository":{"url":"git+https://github.com/gabemahoney/claude-slack-channel-bots.git","type":"git"},"_npmVersion":"11.12.1","description":"Multi-session Slack-to-Claude bridge — run multiple Claude Code bots across Slack channels via Socket Mode","directories":{},"_nodeVersion":"24.15.0","dependencies":{"semver":"^7.6.0","@slack/web-api":"^7.0.0","agent-director":"^0.7.8","@slack/socket-mode":"^2.0.0","@modelcontextprotocol/sdk":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"@types/bun":"^1.0.0","typescript":"^5.4.0","@types/semver":"^7.7.1"},"_npmOperationalInternal":{"tmp":"tmp/claude-slack-channel-bots_0.8.2_1789758771935_0.33070729223253514","host":"s3://npm-registry-packages-npm-production"}},"0.10.0":{"_id":"claude-slack-channel-bots@0.10.0","bin":{"claude-slack-channel-bots":"src/cli.ts"},"bugs":{"url":"https://github.com/gabemahoney/claude-slack-channel-bots/issues"},"dist":{"shasum":"6705bf1ac501c8dcd5b917f3f1d0c075bc3557e8","tarball":"https://registry.npmjs.org/claude-slack-channel-bots/-/claude-slack-channel-bots-0.10.0.tgz","fileCount":48,"integrity":"sha512-lkYunlaVR/ZUtkbHOoxp5Rcf0nnfJhh1K9entM4pQEJdKOGyI2hDeG7vG0mk9/mnhJD2dI1GkL4OhzPyGeu8Fw==","signatures":[{"sig":"MEYCIQCNRGanle5nGTwOzHrv4U3Djfphnx3Y75Ruc7oETo5gSQIhAJSTYN/YDDcEhMfNJljwAq4TswXCYIMkz5kCVo1tODbL","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIAblRGUXpFzyEA27YAW/YTJIRtQr0PrZCBBAyQkB3kKiAiBaZwPq+20AI9WenCNZpWr5tLIGHSxjZTO8AYA4mGM+KA=="}],"unpackedSize":679186},"name":"claude-slack-channel-bots","type":"module","_from":"file:/home/horde/projects/claude-slack-channel-bots-project/claude-slack-channel-bots-main/claude-slack-channel-bots-0.10.0.tgz","author":{"name":"Gabe Mahoney"},"engines":{"bun":">=1.0.21"},"license":"MIT","scripts":{"test":"bun test","start":"bun install --no-summary && bun src/server.ts","pretest":"bun scripts/fixup-bun-cache.ts && bun scripts/check-no-toplevel-mock-module.ts","typecheck":"tsc --noEmit","check:mocks":"bun scripts/check-no-toplevel-mock-module.ts","postinstall":"bun src/postinstall.ts && bun scripts/fixup-bun-cache.ts","install-check":"bun scripts/install-check.ts"},"version":"0.10.0","_npmUser":{"name":"gabemahoney","email":"gmahoney@gmail.com"},"homepage":"https://github.com/gabemahoney/claude-slack-channel-bots#readme","_resolved":"/home/horde/projects/claude-slack-channel-bots-project/claude-slack-channel-bots-main/claude-slack-channel-bots-0.10.0.tgz","_integrity":"sha512-lkYunlaVR/ZUtkbHOoxp5Rcf0nnfJhh1K9entM4pQEJdKOGyI2hDeG7vG0mk9/mnhJD2dI1GkL4OhzPyGeu8Fw==","repository":{"url":"git+https://github.com/gabemahoney/claude-slack-channel-bots.git","type":"git"},"_npmVersion":"10.8.2","description":"Multi-session Slack-to-Claude bridge — run multiple Claude Code bots across Slack channels via Socket Mode","directories":{},"maintainers":[{"name":"gabemahoney","email":"gmahoney@gmail.com"}],"_nodeVersion":"20.20.2","dependencies":{"croner":"^10.0.1","semver":"^7.6.0","@slack/web-api":"^7.0.0","agent-director":"^0.10.0","@slack/socket-mode":"^2.0.0","@modelcontextprotocol/sdk":"^1.0.0"},"_hasShrinkwrap":false,"devDependencies":{"@types/bun":"^1.0.0","typescript":"^5.4.0","@types/semver":"^7.7.1"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/claude-slack-channel-bots_0.10.0_1790024028780_0.9391325831208908"}}},"time":{"created":"2026-03-29T02:52:43.523Z","modified":"2026-09-21T20:53:49.060Z","0.0.1":"2026-03-29T02:52:43.669Z","0.0.2":"2026-03-29T04:40:29.297Z","0.0.3":"2026-03-29T05:16:39.985Z","0.0.4":"2026-03-30T05:57:39.009Z","0.1.0":"2026-03-30T23:04:53.499Z","0.1.1":"2026-03-31T03:58:17.124Z","0.1.2":"2026-03-31T20:32:13.553Z","0.1.3":"2026-03-31T21:32:17.049Z","0.1.4":"2026-04-01T16:11:46.691Z","0.2.0":"2026-04-03T05:58:41.856Z","0.2.1":"2026-04-03T05:59:38.873Z","0.3.0":"2026-04-04T14:54:46.744Z","0.4.0":"2026-04-04T16:07:15.039Z","0.4.1":"2026-04-04T21:56:28.502Z","0.4.2":"2026-04-04T23:53:16.210Z","0.5.0":"2026-04-06T01:37:19.620Z","0.5.1":"2026-05-24T04:29:37.340Z","0.6.0":"2026-05-26T01:08:23.885Z","0.6.1":"2026-05-30T00:40:57.823Z","0.6.2":"2026-05-30T03:42:18.377Z","0.6.3":"2026-05-30T04:25:57.347Z","0.6.4":"2026-05-30T05:01:45.896Z","0.6.5":"2026-05-30T05:27:39.363Z","0.6.6":"2026-05-30T06:21:24.937Z","0.6.7":"2026-06-02T06:20:52.465Z","0.7.0":"2026-06-03T19:36:41.734Z","0.7.1":"2026-06-04T03:54:18.428Z","0.7.2":"2026-06-06T19:15:37.985Z","0.8.0":"2026-06-08T04:53:46.977Z","0.8.1":"2026-09-18T04:00:00.100Z","0.8.2":"2026-09-18T19:12:52.047Z","0.10.0":"2026-09-21T20:53:48.881Z"},"bugs":{"url":"https://github.com/gabemahoney/claude-slack-channel-bots/issues"},"author":{"name":"Gabe Mahoney"},"license":"MIT","homepage":"https://github.com/gabemahoney/claude-slack-channel-bots#readme","repository":{"url":"git+https://github.com/gabemahoney/claude-slack-channel-bots.git","type":"git"},"description":"Multi-session Slack-to-Claude bridge — run multiple Claude Code bots across Slack channels via Socket Mode","maintainers":[{"name":"gabemahoney","email":"gmahoney@gmail.com"}],"readme":"# Claude Slack Channel Bots\n\nA single HTTP MCP server that holds one Slack Socket Mode connection and routes messages to multiple independent Claude Code sessions, each scoped to a different repo and reachable via its own Slack channel. Inbound messages are dispatched to whichever session owns the channel they arrived on; outbound tool calls are restricted to channels that session has previously received a message from.\n\n---\n\n## Quick Start\n\n**[Bun](https://bun.sh) is required** — it is CSCB's runtime and the interpreter its install and start scripts run under. Install bun before you install CSCB. `npm install -g claude-slack-channel-bots` on a box without bun fails during postinstall (the postinstall script is a bun script).\n\n1. **Install globally via bun:**\n\n   ```sh\n   bun install -g claude-slack-channel-bots\n   ```\n\n2. **Trust the package so postinstall runs:**\n\n   ```sh\n   bun pm -g trust claude-slack-channel-bots\n   ```\n\n   Bun blocks the lifecycle scripts of untrusted packages, so the postinstall does not run on the plain `install` above — you must trust the package for it to fire. The `-g` flag targets the global install; without it `bun pm trust` looks for a `package.json` in the current directory and errors with `No package.json was found`. (Run `bun pm -g untrusted` to confirm it is listed first.) The postinstall then creates skeleton config files in `~/.claude/channels/slack/`. Skip this step and a later `start` fails with `missing prerequisite: config.json`.\n\n3. **Run the setup skill:**\n\n   The package includes a Claude Code skill at `skills/setup-slack-channel-bots/` that walks you through the entire configuration. Copy or symlink it into `~/.claude/skills/`, then run:\n\n   ```sh\n   claude /setup-slack-channel-bots\n   ```\n\n   It handles Slack app creation, tokens, routing, access control, hooks, and validation — and skips anything already configured.\n\n4. **Start the server:**\n\n   ```sh\n   claude-slack-channel-bots start\n   ```\n\nSee the sections below for manual configuration details if you prefer not to use the skill.\n\n---\n\n## Prerequisites\n\n- [Bun](https://bun.sh) `>= 1.0.21` (agent-director minimum)\n- [Claude Code](https://claude.ai/code) installed and authenticated\n- [`agent-director`](https://github.com/gabemahoney/agent-director) **installed system-wide** as a prerequisite — like `git` or `docker`. CSCB no longer vendors the AD binary. The npm `agent-director` package CSCB depends on is now a thin TypeScript shim that locates the system-installed binary at startup via `resolveSystemBinary()` / `Client.create()` and refuses to start when the binary is missing, too old, or unreachable. The startup gate enforces AD's required version (declared by AD in `dist/version-floor.json`) and reports the required version on mismatch. agent-director itself requires [tmux](https://github.com/tmux/tmux) on the operator's PATH; CSCB no longer probes for it directly.\n- Slack workspace admin access (to create and configure the Slack app)\n- **cozempic** (optional) — Python 3.10+ and `pip install cozempic` — used by JSONL path resolution helpers retained for downstream callers.\n\n### Supported platforms (inherited from agent-director)\n\n| Platform | Status |\n|---|---|\n| `linux-x64` | Supported |\n| `darwin-arm64` (Apple Silicon Mac) | Supported |\n| `linux-arm64` | **Not supported** by agent-director |\n| `darwin-x64` (Intel Mac) | **Not supported** by agent-director |\n| Windows | **Not supported** by agent-director |\n\nIf the host is unsupported, the system-installed `agent-director` itself will refuse to install or run; CSCB's startup gate then exits non-zero with one of the `ad-system-install-*` class labels (see [Startup errors](#startup-errors)) and writes the failure to `~/.claude/channels/slack/startup-errors.log` and stderr. Consult [agent-director's documentation](https://github.com/gabemahoney/agent-director) for the canonical platform support list.\n\n> **Note on agent-director versions.** v0.4.1 is a zombie release (the published tarball is missing `dist/` and cannot be imported). v0.4.2 lacks the `MakeTemplateParams.overwrite` field CSCB needs for the boot-time template refresh. v0.5.4 and earlier lack `allow_pending` on `readPane`/`sendKeys`, causing `ErrSpawnNotInteractive` during dev-channels dialog approval on freshly-spawned bots. v0.6.0 shipped a stale TS shim whose `Client` dropped `getPermission`, whose `buildDecide()` dropped `--request-token`, and whose error catalog omitted `ErrInvalidFlags` / `ErrPermissionRequestNotFound` / `ErrAmbiguousRequest` — each silently breaks the disambiguation relay. v0.6.1–0.6.2 still lack the full `permission_requests` plural projection + composite-key disambiguation surface CSCB depends on for concurrent open requests. From v0.7.0 onward, AD ships as a thin npm shim around a system-installed binary, and CSCB defers the minimum-AD-version decision to AD itself via `dist/version-floor.json` (AD's library-side `Client.create()` reads it). CSCB's `package.json` caret-pin on `agent-director` governs npm resolution of AD's TypeScript shim only — not the runtime floor, which is owned by the AD release the system binary belongs to.\n\n### Checking your agent-director install\n\nBefore starting the server, you can confirm `agent-director` is installed system-wide and meets the declared minimum with:\n\n```sh\nbun run install-check\n```\n\nThe script calls the same discovery + floor-comparison pipeline the startup gate uses (it reads AD's `dist/version-floor.json`, calls `resolveSystemBinary()`, and compares versions via `semver.gte`). It exits 0 on success with a single-line block naming `agent-director`, the absolute resolved binary path, the detected version, and the floor. On failure it writes one of the canonical class labels to stderr and exits non-zero:\n\n- `ad-system-install-not-found` — no agent-director on PATH or at the standard install path. Install AD and retry. The stderr also points at the install-cscb skill for interactive remediation.\n- `ad-system-install-too-old` — AD binary is below the floor. Upgrade AD and retry. The stderr points at the skill.\n- `ad-system-install-unreachable` — AD discovered but the probe could not invoke it (eight `.reason` values exposed verbatim). The stderr points at the skill.\n- `ad-version-floor-unreadable` — `dist/version-floor.json` is missing, malformed, or lacks `min_binary_version`. The remediation is to reinstall `agent-director` from npm; the install-cscb skill cannot fix a corrupt AD package, so this case does NOT append the skill instructions block.\n\nThe script is purely diagnostic — it never prompts, never runs an install command, never fetches the skill. The startup gate enforces the same floor automatically at server boot via AD's `Client.create()`; `install-check` is for operators who want to confirm their setup ahead of time.\n\n### Installing the install-cscb skill\n\nIf `bun run install-check` (or the startup gate) reports one of the\n`ad-system-install-*` failure classes, you can install the `install-cscb`\nClaude skill for an interactive walkthrough. The skill drives the same\nshared check module but walks you through install/upgrade and a\nper-reason remediation flow for each of the eight\n`ErrSystemInstallUnreachable.reason` values.\n\nThe skill is NOT auto-installed by `bun install` — fetch it manually\nfrom CSCB's GitHub repo and place it in your local Claude skills\nfolder:\n\n1. **Fetch** `SKILL.md` from:\n\n   ```\n   https://github.com/gabemahoney/claude-slack-channel-bots/blob/main/skills/install-cscb/SKILL.md\n   ```\n\n   (The startup gate's `ad-system-install-*` error log line includes\n   this URL automatically.)\n\n2. **Place** it at:\n\n   ```\n   ~/.claude/skills/install-cscb/SKILL.md\n   ```\n\n3. **Invoke** the skill from Claude Code:\n\n   ```\n   /install-cscb\n   ```\n\nThe skill calls `bun run install-check` on each iteration, surfaces\n`agent-director`'s published install/upgrade command verbatim (no\nCSCB-owned install command — AD's documentation is the source of\ntruth), prompts before running, and loops until the check passes or\nyou decline. The `ad-version-floor-unreadable` class is handled\nseparately: the skill prints reinstall-from-npm guidance and does NOT\nloop on it (the skill cannot fix a corrupt AD npm package).\n\nThe published CSCB npm tarball includes `skills/install-cscb/SKILL.md`\nunder its `files` array, so the skill source is also available via\n`node_modules/claude-slack-channel-bots/skills/install-cscb/SKILL.md`\nafter `bun install`. The manual GitHub-fetch step above is for users\nwho haven't yet installed CSCB at all.\n\n---\n\n## Configuration\n\n### Environment Variables\n\nTokens and runtime options are read from environment variables. There is no `.env` file — export these in your shell profile.\n\n| Variable | Description |\n|---|---|\n| `SLACK_BOT_TOKEN` | Slack bot token (`xoxb-…`). Required. Granted by the OAuth install flow. |\n| `SLACK_APP_TOKEN` | Slack app-level token (`xapp-…`). Required. Generated under Basic Information → App-Level Tokens with the `connections:write` scope. |\n| `SLACK_STATE_DIR` | Override the directory where `config.json`, `access.json`, and runtime state are stored. Defaults to `~/.claude/channels/slack`. |\n| `SLACK_ACCESS_MODE` | Set to `static` to load `access.json` once at startup and cache it for the lifetime of the process rather than re-reading it on every event. Useful in high-throughput environments where disk reads are a concern. |\n| `SLACK_DRY_RUN` | Set to `1` to start the server without Slack credentials. Token validation is skipped, Socket Mode and `web.auth.test()` are not called, and MCP tool calls (`reply`, `react`, etc.) are logged instead of sent. Useful for integration testing. |\n| `CSCB_LOG_MAX_BYTES` | Rotate `server.log` / `clean_restart.log` when the active file reaches this many bytes. Defaults to `10485760` (10 MiB). Values `<= 0` or non-numeric are ignored. |\n| `CSCB_LOG_KEEP` | Number of rotated generations to retain (`server.log.1` … `server.log.N`). Defaults to `5`. Set to `0` to keep none (the log is truncated instead of rolled). Values `< 0` or non-numeric are ignored. |\n| `CSCB_AD_VERBOSE` | Set to a truthy value (`1`, `true`, `yes`, `on`) to restore the agent-director library's per-poll `SubprocessClient: <verb> ok` success dumps in `server.log`. Off by default — these routine dumps are dropped so the log stays readable. Failures and warnings from agent-director always pass through regardless of this flag. Read once at server startup, so it takes effect on server restart. |\n| `CSCB_HTTP_VERBOSE` | Set to a truthy value (`1`, `true`, `yes`, `on`) to restore the per-request MCP access line (`HTTP <method> <path> session=…`) in `server.log`. Off by default — the `/mcp` endpoint is hit on every client poll and SSE open, so these routine lines are dropped to keep the log readable. Session connect/disconnect, route mismatches, and errors are logged unconditionally regardless of this flag. Checked per request, so it takes effect without a restart. |\n\nShell profile example:\n\n```sh\nexport SLACK_BOT_TOKEN=xoxb-your-bot-token\nexport SLACK_APP_TOKEN=xapp-your-app-token\n# Optional overrides:\nexport SLACK_STATE_DIR=~/.config/slack-channel-bots\nexport SLACK_ACCESS_MODE=static\n# Dry-run mode (no Slack credentials needed):\nexport SLACK_DRY_RUN=1\n```\n\n---\n\n### Routing (config.json)\n\n`config.json` is read from `~/.claude/channels/slack/config.json` by default. Override the directory with `SLACK_STATE_DIR`.\n\nA skeleton file is created by postinstall. Populate it before running `start`.\n\n#### Complete example\n\n```json\n{\n  \"routes\": {\n    \"C0123456789\": { \"cwd\": \"~/projects/alpha\" },\n    \"C9876543210\": { \"cwd\": \"~/projects/beta\" }\n  },\n  \"default_route\": \"~/projects/alpha\",\n  \"default_dm_session\": \"~/projects/alpha\",\n  \"bind\": \"127.0.0.1\",\n  \"port\": 3100,\n  \"session_restart_delay\": 60,\n  \"health_check_interval\": 120,\n  \"exit_timeout\": 120,\n  \"stop_timeout\": 30,\n  \"mcp_config_path\": \"~/.claude/slack-mcp.json\",\n  \"cozempic_prescription\": \"standard\"\n}\n```\n\n#### Field reference\n\n| Field | Type | Default | Description |\n|---|---|---|---|\n| `routes` | object | required | Map of Slack channel ID → route entry. Each entry requires a `cwd` field: the working directory for that session. Used to identify sessions via `roots/list` after MCP handshake. `~` is expanded. Each `cwd` must be unique across all routes. May also include an optional `claude_config_dir` string (see below). |\n| `default_route` | string | — | CWD path to use when a message arrives on a channel with no explicit entry in `routes`. Must match an existing route `cwd`. Channels that are in `routes` but whose session is not yet registered have their messages dropped — they do not fall back to `default_route`. |\n| `default_dm_session` | string | — | CWD path of the session that handles direct messages. Must match an existing route `cwd`. |\n| `bind` | string | `\"127.0.0.1\"` | Interface the HTTP server binds to. Use `\"0.0.0.0\"` to expose on all interfaces. The in-process cron scheduler delivers via `127.0.0.1`, so `bind` must include loopback (the default, or `0.0.0.0`) for scheduled fires to work. |\n| `port` | number | `3100` | Port the HTTP server listens on. |\n| `session_restart_delay` | number | `60` | Seconds to wait before auto-restarting a dead session. Set to `0` to disable auto-restart. Must be non-negative. |\n| `health_check_interval` | number | `120` | Seconds between periodic liveness polls. Set to `0` to disable. Must be non-negative. |\n| `exit_timeout` | number | `120` | Seconds to wait for a managed Claude Code session to exit gracefully during `clean_restart` before force-killing its tmux session. |\n| `stop_timeout` | number | `30` | Seconds to wait for the server process to exit after `SIGTERM` before escalating to `SIGKILL`. |\n| `mcp_config_path` | string | `~/.claude/slack-mcp.json` | Path to the MCP config file passed to Claude Code when launching managed sessions. |\n| `append_system_prompt_file` | string | — | Path to a file appended to every managed session's system prompt via `--append-system-prompt-file`. Missing file silently skipped. See `skills/EXAMPLE_CLAUDE.md` for a template. |\n| `system_prompt_mode` | string | `\"append\"` | Controls how `append_system_prompt_file` is applied. `\"append\"`: the custom prompt file is appended on top of `CLAUDE.md` (default, current behavior). `\"none\"`: only `CLAUDE.md` is used; `append_system_prompt_file` is ignored even if set. Use `\"none\"` when the project's `CLAUDE.md` already contains everything the bot needs. |\n| `cozempic_prescription` | string | `\"standard\"` | Cozempic cleaning intensity before resume. Valid values: `gentle`, `standard`, `aggressive`. Has no effect if cozempic is not installed. |\n| `message_archive_db` | string | — | Path to a SQLite DB where every inbound Slack message is archived in real time. Parent directories are created if missing; schema is initialized on first open. Compatible with the `archive-messages.py` backfill script — both can write concurrently. Feature is disabled when absent. |\n| `claude_config_dir` | string | — | Path to a Claude on-disk config directory. When set, managed sessions launch with `CLAUDE_CONFIG_DIR='<resolved-path>'` so the bot authenticates against a specific account. `~` is expanded and the path is resolved to absolute. Per-route `routes[id].claude_config_dir` overrides this top-level value for individual channels. When neither is set, Claude's own default applies. Must be non-empty when set. |\n| `resume_enabled` | boolean | `true` | When `true` (default), a bot whose session died — including after a host reboot or pod resume — comes back with its prior conversation history intact instead of starting fresh. When `false`, the session manager always performs a fresh launch instead of resuming, both on startup and on runtime auto-restart, even when a stored session exists. Set `false` as a workaround if your Claude Code version crashes with \"sandbox required but unavailable\" on resume (a known regression in v2.1.120). Requires a system-installed `agent-director` ≥ 0.8.0 for reboot recovery to actually restore history. |\n| `agent_director_poll_interval_ms` | number | `1000` | Poll interval (ms) for the agent-director permission relay tick. Must be a positive integer in `[200, 3_600_000]`. Replaces the pre-rename `claude_director_poll_interval_ms` — the old name is rejected at startup. Unknown top-level config fields are also rejected to surface stale configs after the rename. |\n| `stop_hook_bootstrap` | boolean | `true` | Controls whether the server installs the CSCB-managed Slack Reply Guard Stop hook into `<claude_config_dir>/settings.json` at boot (see [Slack Reply Guard (Stop hook)](#slack-reply-guard-stop-hook)). Set to `false` to disable installation for every route and to actively remove any previously-installed managed entry. Per-route `routes[id].stop_hook_bootstrap` overrides this top-level value. Non-boolean values are rejected by config validation at startup. |\n| `cron_table_path` | string | `<config dir>/crontab` | Path to the crontable for the built-in cron scheduler (`cscb_cron`). Defaults to `crontab` in the directory of the loaded `config.json`. `~` is expanded like other path keys. The resolved path is exported into every managed session as `CSCB_CRONTABLE_PATH` so bots can find the crontable and self-schedule (see [Scheduled Prompts](#scheduled-prompts-cscb_cron)). Must be a non-empty string when set. Changing it requires a server restart. |\n| `cron_log_path` | string | `<config dir>/cron.log` | Path to the `cscb_cron` log file. Defaults to `cron.log` in the directory of the loaded `config.json`. `~` is expanded like other path keys. Must be a non-empty string when set. Changing it requires a server restart. |\n| `cron_log_max_bytes` | number | — | Size cap in bytes for the cron log. Must be a positive integer when set. Cron-log pruning is disabled when absent. Changing it requires a server restart. |\n\n#### Per-route `claude_config_dir` override\n\nWhen you want different bot sessions to authenticate as different Claude accounts (e.g. one channel runs as a personal Max account, another as a corporate account), set `claude_config_dir` on the individual route. Per-route values take priority over the top-level `claude_config_dir`; routes without their own override fall back to the top-level value.\n\n```json\n{\n  \"routes\": {\n    \"C_PERSONAL\": {\n      \"cwd\": \"~/projects/alpha\",\n      \"claude_config_dir\": \"~/.claude-maxauth\"\n    },\n    \"C_CORPORATE\": {\n      \"cwd\": \"~/projects/beta\"\n    }\n  },\n  \"claude_config_dir\": \"~/.claude-corp\"\n}\n```\n\n`C_PERSONAL` launches with the Max account; `C_CORPORATE` falls through to the top-level value and uses the corporate account. Use `claude auth login --claudeai` (or `--console`) with `CLAUDE_CONFIG_DIR` set to the same directory to populate each config dir before starting the server.\n\n#### Per-route `stop_hook_bootstrap` override\n\nSet `stop_hook_bootstrap` on an individual route to override the top-level default for that one bot. Per-route values win over the top-level value; routes without their own value inherit the top-level default (which is itself `true` when absent).\n\n```json\n{\n  \"routes\": {\n    \"C_EDIT_ONLY_BOT\": {\n      \"cwd\": \"~/projects/gamma\",\n      \"claude_config_dir\": \"~/.claude-gamma\",\n      \"stop_hook_bootstrap\": false\n    },\n    \"C_NORMAL_BOT\": {\n      \"cwd\": \"~/projects/delta\",\n      \"claude_config_dir\": \"~/.claude-delta\"\n    }\n  }\n}\n```\n\nA per-route opt-out only *fully* disables the guard for that bot when the route owns a **dedicated** `claude_config_dir` — see [Shared-dir aggregation](#shared-dir-aggregation) for the interaction when routes share a dir.\n\n---\n\n### Access Control (access.json)\n\n`access.json` is read from `~/.claude/channels/slack/access.json` by default (same directory as `config.json`). A skeleton file with defaults is created by postinstall. The file is written with `0600` permissions.\n\nChannels in `config.json` are automatically allowed — you do not need to list them here. The `channels` map is only needed for per-channel overrides like requiring @mentions or restricting which users can trigger the bot.\n\nThe `slack-channel-access` skill manages pairings and allowlist entries at runtime.\n\n#### Complete example\n\n```json\n{\n  \"dmPolicy\": \"pairing\",\n  \"allowFrom\": [\"U0123456789\"],\n  \"channels\": {\n    \"C9876543210\": {\n      \"requireMention\": true,\n      \"allowFrom\": [\"U0123456789\", \"U9876543210\"]\n    }\n  },\n  \"pending\": {},\n  \"ackReaction\": \"eyes\",\n  \"textChunkLimit\": 3000,\n  \"chunkMode\": \"newline\"\n}\n```\n\n#### Field reference\n\n| Field | Type | Default | Description |\n|---|---|---|---|\n| `dmPolicy` | `\"pairing\"` \\| `\"allowlist\"` \\| `\"disabled\"` | `\"pairing\"` | Controls who can DM the bot. `pairing`: unknown users receive a one-time code and are added to `allowFrom` after verification. `allowlist`: only users in `allowFrom` are accepted. `disabled`: all DMs are dropped. |\n| `allowFrom` | string[] | `[]` | Slack user IDs allowed to DM the bot unconditionally (regardless of `dmPolicy`). |\n| `channels` | object | `{}` | Optional per-channel overrides. Channels in `config.json` are allowed automatically — only add entries here to customize behavior (e.g. require @mention or restrict users). Each entry is a `ChannelPolicy`. |\n| `channels[id].requireMention` | boolean | `false` | When `true`, messages in that channel are only delivered if the bot is `@mentioned`. |\n| `channels[id].allowFrom` | string[] | `[]` | When non-empty, restricts delivery to the listed Slack user IDs for that channel. |\n| `pending` | object | `{}` | Managed by the server. Stores in-flight pairing codes indexed by code string. Do not edit manually. |\n| `ackReaction` | string | — | Emoji name (without colons) to react with when a message is received and dispatched. Automatically removed when the bot sends its first reply. |\n| `textChunkLimit` | number | — | Maximum character count per Slack message when chunking long replies. Controlled by the `reply` tool. |\n| `chunkMode` | `\"length\"` \\| `\"newline\"` | — | How to split overlong replies. `length`: hard split at `textChunkLimit` characters. `newline`: split at newline boundaries without exceeding `textChunkLimit`. |\n\n---\n\n### MCP Server Config (slack-mcp.json)\n\nClaude Code sessions need a config file pointing at the MCP server. A skeleton is created by postinstall at `~/.claude/slack-mcp.json`.\n\n```json\n{\n  \"mcpServers\": {\n    \"slack-channel-router\": {\n      \"type\": \"http\",\n      \"url\": \"http://127.0.0.1:3100/mcp\"\n    }\n  }\n}\n```\n\nIf you changed `port` or `bind` in `config.json`, update the `url` here to match. The server-managed session launcher uses `mcp_config_path` from `config.json` to locate this file.\n\n---\n\n## CLI Reference\n\nThe `claude-slack-channel-bots` binary exposes three subcommands.\n\n### `claude-slack-channel-bots start`\n\nChecks prerequisites, then daemonizes the server.\n\n**Prerequisite checks (in order):**\n\n1. `SLACK_BOT_TOKEN` is set — fails with `missing prerequisite: SLACK_BOT_TOKEN environment variable` if absent.\n2. `SLACK_APP_TOKEN` is set — fails with `missing prerequisite: SLACK_APP_TOKEN environment variable` if absent.\n3. `config.json` exists at `STATE_DIR/config.json` — fails with the full path if not found.\n\nOnce the server daemonizes, the SR-5.1 startup gate runs inside the child process: it imports `agent-director`, constructs the singleton Client, runs `client.version()`, and verifies `~/.agent-director/state.db` is owned by the current user. Failures land in `startup-errors.log` (see [Startup errors](#startup-errors)). The previous `tmux -V` probe at the CLI level has been removed — agent-director enforces tmux availability at spawn time.\n\nIf all checks pass, the parent process spawns a detached child process and exits immediately, printing the child PID. The child starts the server and writes its PID to `STATE_DIR/server.pid`. Conversation context is preserved across server restarts when possible.\n\n```\n[slack] Server starting in background (PID 12345)\n```\n\n### `claude-slack-channel-bots stop`\n\nReads `STATE_DIR/server.pid` and sends `SIGTERM` to the process.\n\nBehavior by case:\n\n- **PID file missing:** prints `server is not running` and exits 0.\n- **Stale PID file** (process no longer running): removes the PID file, prints `server is not running (removed stale PID file)`, exits 0.\n- **Live process:** sends `SIGTERM`, polls for exit for up to `stop_timeout` seconds (default 30s). Prints `[slack] Server stopped.` on clean exit. Escalates to `SIGKILL` if the process does not exit within `stop_timeout`.\n\nPlain `stop` leaves the managed bots running — they are meant to survive a server restart. Pass `--stop-bots` to gracefully exit the bots first:\n\n```sh\nclaude-slack-channel-bots stop --stop-bots\n```\n\nThis mirrors `clean_restart`'s order: the server is stopped **first**, then the bot teardown runs for each route — pause the bot, poll until it exits (or up to `exit_timeout` seconds), then force-kill on timeout. Teardown kills but never deletes each row, preserving its `claude_session_id` so the bots can resume their conversation history on the next start. Stopping the server first prevents its `onsessionclosed`/`scheduleRestart` handler from respawning a just-exited bot mid-teardown (which would delete its `ended` row and history). Use it when you want a clean, flushed shutdown of the bots (for example before a host reboot).\n\nIf agent-director is unreachable, the teardown **fails loudly** — the command prints the error and exits non-zero rather than silently reporting a clean stop. (A missing config is best-effort: teardown is skipped but the server stop still succeeds, since the server is already down.)\n\n### `claude-slack-channel-bots clean_restart`\n\nGracefully exits all managed Claude Code sessions, then stops and starts the server.\n\n```sh\nclaude-slack-channel-bots clean_restart\n```\n\nFor each configured route, calls `client.pause({claude_instance_id})` via agent-director and polls `client.status(...)` until the spawn transitions to `ended` / `missing` (or `client.list(...)` returns no row). If the spawn does not exit within `exit_timeout` seconds (default 120s), the spawn is force-killed via `client.kill(...)`. Teardown kills but never deletes each row, preserving its `claude_session_id` so bots resume their conversation history on the next start. All routes are processed in parallel. After the server restarts, the SR-1.4 collision-then-act dispatcher decides resume-vs-fresh per route — agent-director owns Claude session-id state, not CSCB.\n\nA benign kill outcome — the row already being gone — is tolerated per-route and does not abort the restart. Any other per-route teardown failure, including a pause failure that escalates to a kill which then fails to reach agent-director, is fatal: it fails loudly and aborts the restart (non-zero exit).\n\nBehavior by case:\n\n- **No configured routes:** skips the shutdown phase and proceeds directly to stop/start.\n- **Server already stopped:** `stop` reports `server is not running`; `start` then brings up a fresh server.\n- **agent-director unreachable:** teardown fails loudly and the restart is aborted (non-zero exit); no new server is started. The `no spawn row` message appears only when a route genuinely has no spawn, never when the client failed to reach agent-director.\n\n### PID file\n\nThe PID file is stored at `STATE_DIR/server.pid` (default: `~/.claude/channels/slack/server.pid`). It is written on startup and removed on clean shutdown. A conflict check at startup prevents running two servers against the same state directory.\n\n### Installing from a local worktree\n\nTo install the version of CSCB sitting in your working copy (so the globally-linked `claude-slack-channel-bots` binary runs your local sources), use the helper script rather than `bun install -g .`:\n\n```sh\n./scripts/install-local.sh\n```\n\n`bun install -g .` (and the equivalent `bun install -g <local-path>`) is broken on Bun 1.3.13 — it inserts an invalid empty-string dependency key into `~/.bun/install/global/package.json` and then any subsequent global op fails with `error: Package \"@\" has a dependency loop` (upstream: [oven-sh/bun#24207](https://github.com/oven-sh/bun/issues/24207)). The script uses `bun add -g file:<abs-path>` instead, and pre-emptively strips any empty-string entry a prior `bun install -g .` may have already left behind.\n\n### Direct invocation for development\n\nSkip the CLI and run the server directly with Bun for development or debugging:\n\n```sh\nbun server.ts\n```\n\nOn startup the server prints the MCP endpoint and example config:\n\n```\n[slack] Loaded routing config: 2 route(s)\n[slack] Socket Mode connected\n[slack] MCP server listening on http://127.0.0.1:3100/mcp\n\n{\n  \"mcpServers\": {\n    \"slack-channel-router\": { \"type\": \"http\", \"url\": \"http://127.0.0.1:3100/mcp\" }\n  }\n}\n```\n\n---\n\n## Tools\n\nEach MCP endpoint exposes the following tools to the connected Claude Code session:\n\n| Tool | Description |\n|---|---|\n| `reply` | Send a message to a Slack channel or DM. Auto-chunks long text according to `textChunkLimit` and `chunkMode` in `access.json`. Supports file attachments. |\n| `react` | Add an emoji reaction to a Slack message. |\n| `edit_message` | Edit a previously sent message (bot's own messages only). |\n| `fetch_messages` | Fetch message history from a channel or thread. Returns oldest-first. |\n| `download_attachment` | Download attachments from a Slack message. Saves files to `STATE_DIR/inbox/`. Returns local file paths. |\n\n---\n\n## Interject\n\nPOST to `/interject` to inject a message into an active Claude session from localhost. Only requests from `127.0.0.1` or `::1` are accepted — external callers are rejected with 403.\n\n### Request\n\n```sh\ncurl -X POST http://localhost:<port>/interject \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"channel\": \"C1234567890\", \"message\": \"Hello from a script\", \"sender\": \"my-cron-job\"}'\n```\n\n| Field | Required | Description |\n|---|---|---|\n| `channel` | yes | Slack channel ID matching an entry in `config.json → routes`. |\n| `message` | yes | Text to inject into the session. |\n| `sender` | no | Label attached to the injected message. Defaults to `\"interject\"`. |\n\n### Response\n\nOn success, returns HTTP 200:\n\n```json\n{ \"ok\": true, \"channel\": \"C1234567890\", \"cwd\": \"/path/to/session\" }\n```\n\n### Error conditions\n\n| Status | Meaning |\n|---|---|\n| 400 | Invalid JSON or missing required field (`channel` or `message`). |\n| 403 | Request did not originate from localhost. |\n| 404 | Channel not found in `config.json → routes`. |\n| 405 | Must use POST method. |\n| 413 | Request body exceeds 32KB. |\n| 503 | Channel is routed but no active session is connected. |\n\n### Example: crontab reminder\n\nFor recurring prompts, prefer the built-in scheduler (see [Scheduled Prompts](#scheduled-prompts-cscb_cron)) — it needs no host cron and delivers straight into a bot channel. The host-crontab example below is an alternative when you already run `cron`:\n\n```sh\n# crontab -e\n0 9 * * 1 curl -s -X POST http://localhost:3100/interject \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"channel\": \"C1234567890\", \"message\": \"Weekly reminder: update the changelog before standup.\", \"sender\": \"cron\"}'\n```\n\n---\n\n## Scheduled Prompts (cscb_cron)\n\nThe server fires scheduled prompts into bot channels once per minute, reading them from a crontable. Each fire is delivered as an `/interject` message into the target channel, exactly as if a script had POSTed it.\n\n### The crontable\n\nSchedules live in the crontable file at `cron_table_path` (default `<config dir>/crontab`, where `<config dir>` is the directory of your loaded `config.json`; override it with the `cron_table_path` key in `config.json`). The server creates the file on first boot if it is absent, with a self-documenting comment header describing the line format. See [Crontable format](#crontable-format) below for the full reference. With the default config location the crontable is at `~/.claude/channels/slack/crontab`:\n\n```sh\ncat ~/.claude/channels/slack/crontab\n```\n\n### Crontable format\n\nOn first boot the server auto-creates the crontable with this self-documenting header:\n\n```\n# CSCB crontable — scheduled prompts for the Slack channel bots.\n#\n# One schedule per line. Fields are positional and whitespace-delimited:\n#\n#   <min> <hour> <dom> <mon> <dow> <prompt-path> [<channel-id>[,<channel-id>...]]\n#\n#   tokens 1-5 : a standard 5-field cron expression (minute hour day-of-month\n#                month day-of-week).\n#   token 6    : path to the prompt file to run. It must contain NO spaces — a\n#                line with more than 7 whitespace-delimited tokens is a parse\n#                error (a path with spaces is unrepresentable). The prompt\n#                file's content is capped at 32KB (enforced when the job fires).\n#   token 7    : OPTIONAL comma-separated list of Slack channel IDs to target.\n#                Omit it entirely to target ALL bots — that omission IS the\n#                all-bots form. There is NO all-bots wildcard: a literal '*' in\n#                the channel position is a parse error, not \"all channels\".\n#\n# Lines beginning with '#' and blank lines are ignored. A malformed line is\n# skipped on its own; sibling lines still schedule.\n#\n# Example (every day at 09:00, run grooming-tick.md, target two channels):\n#   0 9 * * * /home/horde/prompts/grooming-tick.md C0123ABC,C0456DEF\n#\n# Example (every hour on the hour, run standup.md, target all bots):\n#   0 * * * * /home/horde/prompts/standup.md\n```\n\nEach schedule is one line of **exactly 5 cron fields**, then the prompt-file path, then an optional comma-separated channel list:\n\n```\n0 9 * * 1 /home/horde/prompts/weekly-report.md C0123ABC,C0456DEF\n```\n\nRules:\n\n- **Exactly 5 cron fields** (minute hour day-of-month month day-of-week). Croner's 6-field (seconds-precision) and `@macro` forms are **not** supported.\n- **Omit the channel list to target ALL bots** — the omission itself is the all-bots form. (All-bots delivery is currently deferred — see [Delivery semantics](#delivery-semantics).)\n- **No `*` wildcard in the channel position.** A literal `*` where a channel ID belongs is a parse error, not \"all channels\".\n- **Prompt paths cannot contain spaces.** A path with spaces is unrepresentable; the extra tokens make the line a parse error and it is skipped.\n- **`#` comments and blank lines are allowed** and ignored.\n- **A bad line is skipped and logged** (as `parse-error` in the cron log), never fatal — sibling lines still schedule.\n\nBecause the count is positional, a **6-field line silently mis-parses instead of erroring.** For example:\n\n```\n0 0 1 1 1 1 ~/prompts/p.md\n```\n\nHere the 6th field (`1`) is taken as the prompt path and the real path (`~/prompts/p.md`) is taken as the channel list. No error is raised — every slot is filled with something syntactically acceptable — so the schedule fires on a nonsense cadence against a nonsense path. Keep expressions to exactly 5 fields.\n\n### Path resolution\n\nThe prompt-file path resolves as follows:\n\n- A leading `~` expands to the home directory.\n- A **relative** path resolves against the **crontable's own directory** — not `$HOME`. This is a deliberate divergence from system cron's convention, so you can keep a `prompts/` directory alongside the crontable and reference it as `prompts/standup.md`.\n- An **absolute** path is used as-is.\n\n### How fires appear\n\nA scheduled fire arrives in the channel as an `/interject` message whose `sender` label is `cscb-cron:<prompt-file-basename>` — for a prompt file `standup.md` the sender is `cscb-cron:standup`. This distinguishes a cron tick from a human and from peer-bot traffic. Each schedule delivers its own message independently, so when several schedules match the same minute for the same channel each one arrives as its own `/interject` message.\n\n### The cron log\n\nEvery fire outcome is recorded in the cron log at `cron_log_path` (default `<config dir>/cron.log`; override with the `cron_log_path` key). Each attempt writes one line per target channel plus a per-fire summary line carrying `delivered=N failed=M` counts. The log is plain text, so `grep no-session cron.log` yields readable lines.\n\nThe `outcome` field of each line is one of these classes:\n\n| Outcome | What happened | What to do |\n|---|---|---|\n| `delivered` | The prompt reached the target channel's session. | Nothing — success. |\n| `no-session` | The channel is routed but no live session is connected, so the message was dropped. | Bring the session up. Failed fires are **never** retried or queued (see below). |\n| `unknown-channel` | The target channel is not in `config.json → routes`. | Fix the channel ID in the crontable, or add the route. |\n| `prompt-missing` | The prompt file did not exist at fire time. | Create the file or correct its path in the crontable. |\n| `prompt-unreadable` | The prompt file existed but could not be read (see the `errno`). | Fix file permissions or the path. |\n| `prompt-oversize` | The prompt exceeds the 32KB `/interject` cap and was skipped, never truncated. | Shorten the prompt file. |\n| `parse-error` | The crontable line could not be parsed. | Fix the line — see the crontable header for the format. |\n| `http-error` | The localhost POST hit an unexpected HTTP status or a network failure. | Check that the server is listening on loopback (see the `bind` note below) and inspect the `errno`/`status` in the line. |\n| `fanout-deferred` | A channel-less (all-bots) line was matched but not delivered. | None — all-bots fan-out is not yet enabled; give the line an explicit channel to deliver it today. |\n\n### Delivery semantics\n\n- **No retry.** A failed fire is logged and dropped — never queued or re-sent. A channel with no live session fails every fire until its session is running again; the server does not queue the missed prompts.\n- **Missed fires are skipped, not caught up.** While the server is down, no scheduled prompts fire, and they are not replayed on restart. The `scheduler started, N schedules loaded` line in the cron log marks when scheduling resumed, bounding the outage window.\n- **Edits take effect after a server restart.** The crontable is read and parsed once, at scheduler start. Editing the file — by hand or by a bot appending a line — does nothing until the server restarts and reloads the table.\n- **Server-local time.** Cron expressions are evaluated in the server's local timezone.\n- **Channel-less lines are deferred.** A line with no channel is currently matched but logged `fanout-deferred` and not delivered. Give a line an explicit channel to have it fire.\n- **`bind` must include loopback.** The scheduler delivers via `127.0.0.1`, so a `bind` set to a single non-loopback interface makes every fire fail with `http-error`. Use the default `127.0.0.1` or `0.0.0.0`.\n\n### Bot self-scheduling\n\nEvery managed session carries the resolved crontable path in the `CSCB_CRONTABLE_PATH` environment variable, so a bot can schedule its own prompts without being told where the crontable lives. Discover it from inside a session:\n\n```sh\necho $CSCB_CRONTABLE_PATH\n```\n\nThe crontable is the single source of truth for schedules. When adding a schedule, **append** a new line — never rewrite, reorder, or delete other lines. An appended line takes effect after the next server restart (the table is read once at scheduler start).\n\n---\n\n## Permission Relay\n\nWhen Claude Code requires tool approval, the permission relay surfaces an interactive Slack message with **Allow** and **Deny** buttons instead of blocking the TUI. Architecture is polling-based on the `agent-director` library — there are **no hook scripts to install** and no HTTP long-poll loops.\n\nFlow:\n\n1. agent-director moves the spawn into `check_permission` state when Claude requests a tool permission.\n2. CSCB's poller (`src/permission-poller.ts`) runs `client.list({ state: ['check_permission'], label: ['service=cscb'] })` at the `agent_director_poll_interval_ms` cadence (default 1000 ms).\n3. For each new spawn, `client.get(...)` returns the open `permission_request` (tool name + tool input + integer `request_id`). CSCB `chat.postMessage`s the Block Kit prompt to the spawn's `channel` label.\n4. The operator clicks Allow / Deny in Slack. CSCB's interactive handler calls `client.decide({ claude_instance_id, decision })` and `chat.update`s the message to \"Allowed/Denied by <user>\".\n5. If a tracked prompt drops out of `check_permission` for any reason other than a Slack click (timeout, external `decide`, crash), the next poller tick replaces the buttons with \"expired\".\n\n### Slack app prerequisites\n\nThe Slack app must have **interactivity enabled** with **Socket Mode** as the delivery method. Open your Slack app config → **Interactivity & Shortcuts** → toggle **Interactivity** on. No Request URL is needed; Socket Mode delivers interaction payloads over the existing socket. This is included automatically if you created the app from `slack-app-manifest.yml`.\n\n### AskUserQuestion\n\nThe `AskUserQuestion` tool is denied for every CSCB-spawned bot via the agent-director template (`deny: ['AskUserQuestion']`). Bots respond to operator questions via the Slack `reply` MCP tool instead. There is no `ask-relay.sh` hook and no `/ask` HTTP route.\n\n### Memory-directory reads\n\nThe template also pre-allows each bot to read its own persistent-memory directory, so those reads don't surface a permission prompt to a human. One `Read(//<config-dir>/projects/*/memory/**)` rule is derived per distinct Claude config directory in your routing config (a route's `claude_config_dir`, the top-level `claude_config_dir`, or the `~/.claude` default). The rule is scoped to `projects/*/memory/**` only — never the config-dir root, which holds live credentials — so it never pre-authorizes credential reads.\n\n---\n\n## Slack Reply Guard (Stop hook)\n\nCSCB ships a Claude Code Stop hook that enforces a simple rule for every bot session it manages: **when the most recent real user message on the turn came from Slack, the assistant must call the `mcp__slack-channel-router__reply` tool before ending the turn**. If it does not, the Stop hook exits `2`, and Claude Code shows the assistant the reminder `Slack user is waiting for a reply. You must respond by calling the mcp__slack-channel-router__reply tool before ending your turn.` and re-runs it once. The retry sets `stop_hook_active=true`, which short-circuits the guard, so exactly one forced retry occurs per turn — never an infinite block loop.\n\n### What the server writes, and where\n\nCSCB owns installing the hook on your behalf. On every server boot, alongside the trust-folder bootstrap, the server walks every route, groups them by effective `claude_config_dir` (per-route override falls back to the top-level value), and patches `<claude_config_dir>/settings.json` in place. For each dir it ensures **exactly one** managed Stop-hook group of the shape:\n\n```jsonc\n{\n  \"hooks\": {\n    \"Stop\": [\n      { \"hooks\": [ { \"type\": \"command\", \"command\": \"<absolute path>/stop-hooks/slack-reply-guard.sh\" } ] }\n    ]\n  }\n}\n```\n\nThe command is an absolute path to the script inside CSCB's installed package tree. There is no `matcher` field — Stop is not a tool-scoped event. Any other Stop hooks you have configured, and every other key in `settings.json`, are preserved. Writes are atomic (`.tmp` + `rename`). A missing `settings.json` is created with just this group; a malformed `settings.json` is left untouched and a startup error is recorded.\n\n**Recognition rule.** The server treats *any* Stop-hook `command` string containing the substring `slack-reply-guard.sh` as CSCB-managed. Duplicates from prior boots are collapsed to one canonical entry; stale entries (from an older install path) are rewritten to the current absolute path — this is the self-heal path across upgrades.\n\n### Timing: on-disk at every boot, effective at next Claude process start\n\nThe bootstrap rewrites `settings.json` on **every** CSCB boot, so the on-disk entry always reflects the currently-installed release's absolute path. Claude Code, however, only reads hook configuration when a Claude process starts. On a CSCB restart, live sessions are reconnected and keep their already-running Claude processes — they will not pick up an updated hook path until the next fresh spawn or the next resume of a dead/missing session for that route.\n\n### Shared-dir aggregation\n\nThe install/remove decision is per **directory**, not per route. If two routes resolve to the same `claude_config_dir`, the managed entry is installed when at least one of them has the guard enabled, and removed only when all of them have it disabled. Consequence: a per-route opt-out fully disables the guard for a bot only when that route owns a *dedicated* `claude_config_dir`. A route that shares a dir with any enabled route still gets the guard on that shared dir.\n\n### Personal-dir refusal\n\nThe bootstrap refuses to touch the operator's own `~/.claude` directory. If a route's effective `claude_config_dir` resolves (via `realpathSync`, with a lexical fallback for paths that do not exist on disk) to your home `.claude` dir, nothing is written and a startup error is recorded. This prevents CSCB from ever installing a bot-oriented Stop hook into your interactive Claude Code config.\n\n### Bots without a `claude_config_dir`\n\nRoutes with no effective `claude_config_dir` — neither per-route nor top-level — are skipped. Empty or whitespace-only values are treated as absent (so `resolve(\"\")` never lands in the process cwd). If you want the guard on a bot, give its route a real `claude_config_dir`.\n\n### v1 limitations — opt these bots out\n\nThe v1 guard only recognises a reply via `mcp__slack-channel-router__reply`. Bots whose only Slack surface is `edit_message` or `react` will end their turn without producing a matching `tool_use`, and the guard will block them and force one useless retry every turn. **Opt these bots out** by setting `stop_hook_bootstrap: false` on the route (see the field reference below), and give the route a dedicated `claude_config_dir` — see [Shared-dir aggregation](#shared-dir-aggregation).\n\n### Opting out\n\nThe `stop_hook_bootstrap` boolean lives on the top level of `config.json` and on individual routes. It defaults to `true`. Set it to `false` at the top level to disable the bootstrap for every route; set it on an individual route to override the top-level default for one bot. See the [Field reference](#field-reference) and [Per-route `stop_hook_bootstrap` override](#per-route-stop_hook_bootstrap-override) below for the field details and the per-route-vs-shared-dir interaction.\n\n### Tag drift — fail-open, verify after upgrades\n\nThe guard's Slack-origination predicate is a substring match on the prefix `<channel source=\"slack` in the transcript entry Claude Code writes for every Slack-delivered turn. CSCB only sends `{content, meta}` over MCP; the `<channel source=\"…\">` wrapper is rendered by the **Claude Code harness itself** when it serialises the MCP tool result into the transcript, and the `source` attribute is the MCP server name (e.g. `slack-channel-router`). That tag is therefore an **external, harness-owned contract** — a future Claude Code release can rename it or restructure the wrapper without touching CSCB, and the guard's predicate would silently stop matching. Because the contract sits outside CSCB, the guard is designed to fail open on drift, and a post-upgrade verification recipe (below) exists so operators catch a silent-dark guard the next time the harness changes the tag.\n\nThe guard is **fail-open by design**: any error, missing transcript, missing `jq`, or absence of the tag results in `exit 0` (turn allowed). This means a future rename of the `<channel>` tag will silently disable the guard rather than break the bot. After every CSCB or Claude Code upgrade, verify the guard end-to-end:\n\n1. Send the bot a Slack message that requires a reply.\n2. Confirm the reply lands in Slack.\n3. In the bot's transcript file (`<claude_config_dir>/projects/<slug>/*.jsonl` — guard-covered bots always run with a dedicated `claude_config_dir`, since the bootstrap refuses the operator's personal `~/.claude`), grep for `<channel source=\"slack` on the triggering message and for a subsequent assistant entry containing `\"name\":\"mcp__slack-channel-router__reply\"` in a `tool_use` block.\n\nIf the tag prefix no longer appears, the guard is dark — file an issue.\n\n---\n\n## Troubleshooting\n\n**Missing environment variables**\n`start` exits with `missing prerequisite: SLACK_BOT_TOKEN environment variable` or `SLACK_APP_TOKEN environment variable`. Export both tokens in your shell profile and open a new terminal before running `start`.\n\n**config.json not found**\n`start` exits with `missing prerequisite: config.json not found at <path>`. Run `bun postinstall.ts` to create a skeleton, or create the file manually. Verify `SLACK_STATE_DIR` matches the directory you populated.\n\n**config.json CWD mismatch**\nIf a Claude Code session connects but immediately disconnects, the session's actual CWD does not match any `cwd` in `config.json`. Confirm the session's working directory matches the entry exactly (after tilde expansion). Duplicate CWDs across multiple routes are rejected at startup.\n\n**Bot not receiving messages in a new channel**\nAfter inviting the bot to a channel, Slack may not deliver messages until the bot is @mentioned for the first time. This is a Slack Socket Mode behavior — the first @mention activates event delivery for that channel. After that, all messages flow normally regardless of `requireMention` settings.\n\n**Channel not in access.json**\nMessages to channels not listed in `access.json → channels` and not present in `config.json → routes` are silently dropped. Use the `claude-slack-channels-config` skill or edit `access.json` directly to add the channel ID with a `ChannelPolicy` entry.\n\n**Permission relay not working**\nCheck that the Slack app has interactivity enabled (Interactivity & Shortcuts → toggle on). Verify the bot is in `check_permission` state via `agent-director list --state check_permission --label service=cscb` (operator CLI). Inspect `server.log` for `permission-poller:` lines — skipped-tick WARNs at 5+ consecutive skips signal that the poll interval is too tight; increase `agent_director_poll_interval_ms` in `config.json`.\n\n**Bot appears dead / posts a \"blocked on a native permission prompt\" warning**\nThe bot is wedged in `check_permission` on a native Claude Code TUI prompt that never reached Slack (a permission decision AD recorded but could not deliver). The bot stops responding, and after ~90 s the poller posts a one-shot channel warning. Recover by inspecting the native prompt with `agent-director read-pane --claude-instance-id <id>`, then killing and respawning the session (`agent-director kill <id>` or tmux-kill, then let the server restart it or `claude-slack-channel-bots stop && claude-slack-channel-bots start`). Do **not** use `send-keys` — agent-director hard-rejects it while the spawn is in this relayed permission state. The warning fires once per wedge episode; the detector re-arms if the bot later wedges again.\n\n**Session not restarting after crash**\nAuto-restart backs off exponentially on repeated launch failures — the delay doubles from `session_restart_delay` (default 60s) on each consecutive failure, up to a 15-minute ceiling. After 5 consecutive failures the route hits a cap: a `SpawnCapReached` message is posted to the channel and automatic restarts stop.\n\nSending a message in a channel whose session is dead but not yet capped triggers a fast recovery: the restart is scheduled immediately (the backoff delay is clamped down to 5 seconds for an explicit human trigger, never raised), and the sender is told the session is starting and to retry in a moment. The dropped message itself is **not** delivered or replayed — recovery only starts the session; you must resend after it comes up. This human trigger still counts each failed launch toward the backoff/cap, and a restart already pending or active is not stacked.\n\nA **capped** route (or one with auto-restart disabled via `session_restart_delay: 0`) does **not** recover on an inbound message — firing another launch there would only burn a spawn attempt against a route that cannot come up. The sender is told plainly that the channel will not self-recover and an operator must restart the server. To clear the cap and retry, restart the server with `claude-slack-channel-bots stop && claude-slack-channel-bots start`; the failure counter is in-process and cleared on restart, giving each route a fresh attempt. To disable auto-restart entirely, set `session_restart_delay` to `0` in `config.json`.\n\n**Bot alive but silently unresponsive (MCP disconnected)**\nA bot can stay running yet lose its MCP connection to the server — the process is alive but no longer reachable, so it stops responding without ever emitting a disconnect event. The periodic health-check recovers this automatically: once a channel is seen alive-but-disconnected on two consecutive ticks, the health-check schedules a reconnect (or a relaunch if the process has since died), so a stranded channel comes back with no inbound message and no server restart. The recovery lands within roughly two `health_check_interval` periods (default 120 s each) plus the restart backoff delay (default `session_restart_delay` 60 s) before the reconnect runs — about 3–5 minutes with default settings. A bot mid-turn (`working` state) is deliberately left alone and reconnected on a later tick once its turn settles.\n\nA closely related symptom is a bot that still *looks* connected but silently drops every inbound message — its underlying message stream went away without the connection registering as closed. The same health-check path recovers this on the same two-consecutive-tick cadence, so no inbound message or server restart is needed. If a message does arrive on such a channel before recovery lands, the sender is told the message was not delivered and to retry in a moment, rather than getting silence.\n\nTo verify recovery in the field, tail `server.log` for a stranded channel and confirm a tick-driven recovery lands — look for a `[slack] Scheduling restart for channel=<id> in <N>s (backoff)` line and a `[slack] Session alive but disconnected — reconnecting MCP for channel=<id>` line naming that channel (and, when the bot was mid-turn, a `deferring /mcp reconnect to a later tick (b.9a7/b.rmy)` line first). A **capped** route is exempt: the health-check skips it entirely, including reconnects, so a capped channel still requires a server restart (see below).\n\n**Session stuck during clean_restart**\nIf a session does not exit within `exit_timeout` seconds (default 120s), `clean_restart` force-kills the spawn via `agent-director kill` and proceeds. To manually recover, run `agent-director list --label service=cscb` to find lingering spawns and `agent-director kill <claude_instance_id>` to clear them, then `claude-slack-channel-bots stop && claude-slack-channel-bots start`.\n\n**`clean_restart` or `stop --stop-bots` exits non-zero with an agent-director teardown error**\nThis is intentional: when agent-director is unreachable, the teardown cannot run, so the command fails loudly rather than silently no-op'ing and (for `clean_restart`) restarting on top of bots it never touched. Confirm agent-director is installed and responsive with `agent-director version`, then re-run the command. Teardown kills but never deletes rows on any failure path, so it is always safe to retry once agent-director is reachable.\n\n**Bots come back with no memory of the prior conversation after a reboot**\nWith `resume_enabled: true`, a bot whose host rebooted (or pod resumed) should return with its conversation history. If it comes back amnesiac, confirm the system-installed `agent-director` is **≥ 0.8.0** (`agent-director version`) — reboot recovery relies on capabilities added in that release. Note that `bun run install-check` does **not** confirm this: its client floor is `0.7.0`, lower than the reboot-recovery requirement, so install-check passes on a `0.7.x` binary that still yields amnesiac bots. Verify the resume requirement directly with `agent-director version`. Note: legacy sessions created before upgrading to 0.8.0 may lose history exactly once on their first post-upgrade recovery, then resume cleanly thereafter.\n\n**Session crashes on resume with \"sandbox required but unavailable\"**\nThis is a known regression in certain Claude Code releases (e.g. v2.1.120) where `--resume` triggers a sandbox check that fails in headless environments. Set `resume_enabled: false` in `config.json` to disable `--resume` entirely — the bot will always start a fresh Claude session instead of resuming a prior conversation, both on startup and on runtime auto-restart:\n\n```json\n{\n  \"routes\": { ... },\n  \"resume_enabled\": false\n}\n```\n\n---\n\n## Server log rotation\n\nThe server daemon writes runtime output to `~/.claude/channels/slack/server.log` (and `clean_restart.log` for the `clean_restart` subcommand). Rotation is built into CSCB, so it applies on every machine with no per-host logrotate config: when the active file crosses `CSCB_LOG_MAX_BYTES` it is rolled to `server.log.1`, the previous `.1` → `.2`, and so on up to `CSCB_LOG_KEEP` generations; the oldest is discarded. Rotated generations are not compressed. See the environment-variable table above for the size, retention, and verbosity settings that tune this behavior.\n\nNote this covers only `server.log` / `clean_restart.log`. `startup-errors.log` and `permission-trail.jsonl` are separate append-only files with their own retention (see below).\n\n---\n\n## Startup errors\n\nCSCB writes startup errors to `~/.claude/channels/slack/startup-errors.log` (override the directory with `SLACK_STATE_DIR`) in addition to stderr. Each entry is a single timestamped line. The file is append-only and never rotated by CSCB — copy `docs/logrotate-startup-errors.conf` into `/etc/logrotate.d/` if you want host-level rotation. Most classes below are fatal (the process exits non-zero); the JSONL-persistence warnings at the end are non-fatal and do not block startup.\n\nClasses you may see:\n\n- `ad-system-install-not-found` — `Client.create()` could not locate an `agent-director` binary on PATH or at the standard install path. Install agent-director system-wide and retry. The log line appends a manual-skill-install instructions block pointing at `skills/install-cscb/SKILL.md` (URL, target path under `~/.claude/skills/`, and invocation command `/install-cscb`) for the interactive install/upgrade flow.\n- `ad-system-install-too-old` — the system-installed agent-director binary is below the floor declared in `dist/version-floor.json`. The log line names the detected and required versions, and appends the manual-skill-install instructions block.\n- `ad-system-install-unreachable` — agent-director was discovered but the probe could not execute it (e.g. permission bits, broken symlink, runtime crash). The log line surfaces AD's supplied `err.reason` value verbatim (one of `not-executable`, `not-a-regular-file`, `probe-timeout`, `probe-nonzero-exit`, `probe-killed-by-signal`, `unparseable-version`, `spawn-failed`, `other`) and appends the manual-skill-install instructions block.\n- `ad-bun-version-too-old` — agent-director needs Bun `>= 1.0.21`. Upgrade Bun.\n- `ad-version-probe` — `agent-director` was loaded but the `version()` probe failed (subprocess invocation, platform binary, etc.).\n- `ad-shim-missing-get-permission` — the installed `agent-director` TS shim's `Client` does not expose `getPermission`. The npm-published package is out of sync with the system-installed binary. Reinstall a matching `agent-director` version and confirm the resolved package actually ships the method.\n- `ad-shim-catalog-incomplete` — the installed `agent-director` TS error catalog is missing one or more of `ErrInvalidFlags`, `ErrPermissionRequestNotFound`, `ErrAmbiguousRequest`. The log line lists the missing names. Same remediation as `ad-shim-missing-get-permission`.\n- `ad-shim-decide-drops-token` — the installed `agent-director` dist does not include `--request-token` in its bundled JS, meaning `buildDecide()` would resolve permission clicks against the wrong row. Reinstall a matching `agent-director` version and confirm `buildDecide` carries the flag.\n- `ad-version-floor-unreadable` — `node_modules/agent-director/dist/version-floor.json` could not be read, parsed, or is missing `.min_binary_version`. This is a packaging defect — reinstall `agent-director` from npm. Surfaced by `bun run install-check`; the startup gate itself does not emit this label (it relies on `Client.create()`, which fails differently when the AD package is corrupt).\n- `ad-call-timeout` — an agent-director verb call exceeded the configured `callTimeoutMs` (default 30 s). Investigate the subprocess or increase the timeout.\n- `ad-same-user` — `~/.agent-director/state.db` is owned by a different UID than the CSCB process. Reinstall agent-director as the correct user or remove the mismatched file.\n- `ad-same-user-stat` — Non-ENOENT stat error on the state DB (permissions, I/O). Investigate the file before re-launching.\n- `ad-template-install` — `client.makeTemplate(...)` rejected the boot-time refresh of the `slack-channel-bot` template. The line includes the agent-director `errName`.\n\nThe following classes are **non-fatal warnings** about conversation-memory loss. They are recorded to the same log but never exit the process or block startup. The first four are written by the JSONL-persistence safeguard, which runs *before* the resume path to warn about an *impending* loss; the last two (`jsonl-transcript-lost-on-resume`, `jsonl-diagnosis-inconclusive`) are written *by the resume path itself* when it tried to resume a row and either confirmed a wipe or could not determine whether one occurred:\n\n- `jsonl-non-persistent` — a session-transcript storage root (`<claude_config_dir>/projects`) is on a `tmpfs`/`ramfs` mount, so nothing there survives a reboot and session resume is structurally impossible on this host. A warning is also posted to the affected channels — those whose transcript storage root is the flagged mount, not every routed channel. Move the config dir to a persistent filesystem.\n- `jsonl-persistence-check-warning` — the safeguard could not determine the filesystem type of a transcript storage root (unreadable/unparseable `/proc/self/mountinfo`, or an unresolvable path), so persistence is unverified. No Slack post is made. Investigate the mount before relying on resume.\n- `jsonl-transcript-stale-path` — a channel's saved transcript exists on disk at the resolved fallback path, but agent-director's recorded `jsonl_path` points elsewhere (missing/empty). On the next restart the resume path would treat it as missing and wipe the channel's memory. A warning is posted to that channel; an operator should reconcile the path before restarting.\n- `jsonl-transcript-lost` — a channel's transcript is gone from disk (neither the recorded nor the fallback path exists), yet the message archive shows messages in that channel since the bot spawned. Conversation history has been lost and resume will start the bot fresh. A warning is posted to that channel. Requires `message_archive_db` to be configured for the archive evidence.\n- `jsonl-transcript-lost-on-resume` — resume actually threw `ErrJsonlMissing` for a channel, the bot was delete+fresh-spawned, and the message archive shows messages in that channel since it spawned — so conversation history was destroyed by this recovery, not merely at risk. A warning is also posted to that channel. This is the resume path's own after-the-fact report (distinct from the pre-resume `jsonl-transcript-lost` warning above); the log line names every transcript path tried and whether each came from agent-director or was computed locally. A missing transcript on a channel that was *idle since spawn* — the archive was consulted and shows zero messages since spawn — is expected (the transcript is created lazily on first message) and produces a quiet log line only, no error class and no channel post. Requires `message_archive_db` for the archive evidence; when the archive cannot be consulted the case is instead reported as `jsonl-diagnosis-inconclusive` below.\n- `jsonl-diagnosis-inconclusive` — resume threw `ErrJsonlMissing` and the bot was delete+fresh-spawned, but the diagnosis could not determine whether conversation history was lost: the agent-director row could not be fetched, `started_at` was unparseable, the message archive could not be read, or `message_archive_db` is not configured at all. Because \"inconclusive\" correlates with the same storage problems that cause real loss, this is surfaced (not silently downgraded to a benign never-created): the line records *why* the diagnosis failed, and a warning is posted to the channel worded as uncertainty (\"restarted fresh; could not determine whether prior history was preserved\") rather than as a confirmed loss. When the reason is an unconfigured archive, the message notes that diagnosis is impossible without `message_archive_db` and suggests enabling it. These channels are counted separately in the startup summary as `fresh-after-inconclusive-amnesia` (distinct from the `fresh-after-amnesia` count).\n\n---\n\n## Release process\n\nCSCB releases are cut with the `/publish` skill from a clean checkout of `main` on a dev box tha","readmeFilename":"README.md"}