Commit Graph

197 Commits

Author SHA1 Message Date
Daisy Hollman
c7c5162e4a fix: error message points to real path (/plugin manage), not nonexistent subcommand
/plugin reconfigure doesn't exist. The actual path is /plugin manage →
select plugin → Configure options (ManagePlugins.tsx:1692).

🏠 Remote-Dev: homespace
2026-03-24 23:42:25 +00:00
Daisy Hollman
cbfd4c8c82 feat(telegram,discord): migrate to plugin userConfig secrets
Closes H1 #3617646 via the proper path — plugin userConfig with
sensitive: true routes tokens to keychain (macOS) or .credentials.json
0600 (elsewhere) instead of world-readable .env files.

Requires claude-cli-internal#23383 (PLUGIN_OPTIONS ungate + per-server
sensitive split).

Changes per plugin:
  - plugin.json: add userConfig.{PLATFORM}_BOT_TOKEN with sensitive: true
  - .mcp.json: add env block with ${user_config.{PLATFORM}_BOT_TOKEN}
  - server.ts: update comment + error message to point to
    /plugin reconfigure instead of .env file

The .env read loop stays as a legacy fallback for existing users —
process.env wins (injected value takes precedence), so no migration
forced. New users get prompted at enable time via CC's built-in dialog;
token lands in keychain, never touches settings.json.

/telegram:configure and /discord:configure skills are NOT removed in this
PR — they still work for the legacy .env path. Follow-up: repurpose or
remove after a grace period once cli#23383 is released.

🏠 Remote-Dev: homespace
2026-03-24 23:42:25 +00:00
Kenneth Lien
79caa0d824 Merge pull request #957 from anthropics/kenneth/fix-imessage-lockfile
Fix imessage startup: regenerate bun.lock without internal registry URLs
2026-03-23 23:53:32 -07:00
Kenneth Lien
12e9c01d5f Regenerate imessage bun.lock without artifactory URLs
The lockfile had 94 artifactory.infra.ant.dev URLs baked in from
generation behind a private registry. External users hit 401s on
'bun install' and the server never starts. Regenerated against
registry.npmjs.org to match the .npmrc.
2026-03-23 23:45:03 -07:00
Kenneth Lien
7074ac045b Merge pull request #737 from anthropics/add-imessage-channel
Add imessage channel plugin
2026-03-23 23:13:45 -07:00
Kenneth Lien
d49d339d1e Show input_preview only for Bash in permission prompts
Write/Edit previews are unbearably long over iMessage. Bash is the
dangerous one where seeing the command matters; everything else gets
tool_name + description only.
2026-03-23 23:05:00 -07:00
Noah Zweben
4b1e2a28ce feat(telegram,discord): compact permission messages with expandable details (#952)
* feat(telegram,discord): compact permission messages with expandable details

Replace verbose permission request messages with a compact format showing
only the tool name. Adds a "See more" button that expands inline to show
tool_name, description, and pretty-printed input_preview JSON. Yes/No
buttons replace Allow/Deny. Bump plugin versions to 0.0.4.

* revert: restore Allow/Deny button labels
2026-03-23 22:53:47 -07:00
Daisy S. Hollman
b3a0714d7f feat(telegram,discord): inline buttons for permission approval (#945)
Replace "Reply 'yes abcde' to allow" text instruction with native
inline buttons (Telegram InlineKeyboard, Discord ButtonBuilder).
One tap to approve/deny instead of typing a 5-char ID.

- Telegram: callback_query handler with allowFrom gate, edits message
  to show outcome and remove buttons after decision
- Discord: interactionCreate handler with allowFrom gate, updates
  interaction with outcome and clears components
- Text-reply path (PERMISSION_REPLY_RE) kept as fallback
- Bump both plugins to v0.0.3

🏠 Remote-Dev: homespace
2026-03-23 22:19:51 -07:00
Kenneth Lien
9693fd75c3 Document IMESSAGE_STATE_DIR in README 2026-03-23 20:12:20 -07:00
Kenneth Lien
bfed4635f5 feat(imessage): port permission-relay + lifecycle fixes from telegram
Brings the imessage channel to parity with recent telegram/discord
hardening:

- Permission-relay capability: declare claude/channel/permission,
  handle inbound permission_request notifications by fanning out to
  allowlisted DM chats + self-chat, intercept "yes/no <id>" replies
  after the gate check and emit structured permission events instead
  of relaying as chat. Groups excluded per single-user-mode policy.
- Global unhandledRejection/uncaughtException handlers so the server
  logs instead of dying silently.
- IMESSAGE_STATE_DIR env override for the state directory.
- .unref() on both setInterval timers so they don't block shutdown.
- stdin EOF / SIGTERM / SIGINT shutdown handler that closes chat.db
  and exits cleanly instead of leaving a zombie poll loop.

Adds zod as a direct dep (already transitively present via the MCP SDK)
for the notification handler schema.
2026-03-23 20:10:34 -07:00
Kenneth Lien
0f8c170fa7 Merge remote-tracking branch 'origin/main' into add-imessage-channel 2026-03-23 20:07:40 -07:00
Daisy S. Hollman
15268f03d2 Merge pull request #833 from anthropics/daisy/plugin-7/channel-permissions
feat(telegram,discord): permission-relay — approve Claude Code tool use from your phone
2026-03-23 13:15:41 -07:00
Daisy Hollman
daa84c99c8 feat(telegram,discord): permission-relay capability + bidirectional handlers
Complete the plugin side of anthropics/claude-cli-internal#23061 (permission
prompts over channels).

Capability: both servers now declare
  experimental["claude/channel/permission"]
which tells CC they can relay permission requests. This capability asserts the
server authenticates the replier — gate()/access.allowFrom filters
non-allowlisted senders before handleInbound runs.

Outbound (CC → user): setNotificationHandler for
  notifications/claude/channel/permission_request
formats the tool name, description, and input preview into a human-readable
message and sends it to every allowlisted DM. Groups are excluded — the
security thread resolution was "single-user mode for official plugins."

Inbound (user → CC): PERMISSION_REPLY_RE intercept in handleInbound catches
"yes xxxxx" / "no xxxxx" replies, emits the structured
  notifications/claude/channel/permission
event with {request_id, behavior}, reacts with checkmark/cross, and returns
without relaying the text to Claude as a chat message.

The regex is inlined from channelPermissions.ts (no cross-repo dep). IDs are
lowercased at the plugin boundary per the case-insensitive spec.

Version bumped 0.0.1 → 0.0.2 so the plugin reconciler picks up the change.

🏠 Remote-Dev: homespace
2026-03-23 08:59:02 +00:00
Kenneth Lien
61c0597779 Merge pull request #825 from anthropics/kenneth/channels-rollup
Channels rollup: resilience + discord port + bucket-1 features
2026-03-20 17:40:59 -07:00
Tobin South
da61886c07 Merge pull request #823 from anthropics/claude/slack-add-claude-plugin-marketplace
fix(plugin): switch stripe plugin to git-subdir source and remove local copy
2026-03-20 23:02:17 +00:00
Kenneth Lien
6d0053f69e Add IMESSAGE_APPEND_SIGNATURE env var (default true) 2026-03-20 14:51:47 -07:00
Kenneth Lien
252577f8de Register imessage plugin in marketplace.json 2026-03-20 14:44:25 -07:00
Kenneth Lien
272de726d6 Merge branch 'main' into add-imessage-channel 2026-03-20 14:43:23 -07:00
Ralph Furman
d56d7b61f0 Merge pull request #755 from anthropics/ralph/add-math-olympiad
Add math-olympiad skill
2026-03-20 13:31:34 -07:00
Claude
802464cff3 Fix frontmatter validation to skip deleted files
The workflow was passing deleted files to the validation script, which
failed when trying to read them. Add --diff-filter=AMRC to only process
Added, Modified, Renamed, and Copied files.
2026-03-20 20:30:40 +00:00
Kenneth Lien
51bd7bd5f2 Merge remote-tracking branch 'origin/kenneth/telegram-all-file-types' into kenneth/channels-rollup 2026-03-20 13:13:58 -07:00
Kenneth Lien
71b102d75d Merge remote-tracking branch 'origin/kenneth/telegram-bot-commands-795' into kenneth/channels-rollup
# Conflicts:
#	external_plugins/telegram/server.ts
2026-03-20 13:13:58 -07:00
Kenneth Lien
556b21af96 Merge remote-tracking branch 'origin/kenneth/telegram-bot-commands' into kenneth/channels-rollup 2026-03-20 13:13:08 -07:00
Kenneth Lien
87e0f09336 Merge remote-tracking branch 'origin/kenneth/discord-resilience' into kenneth/channels-rollup 2026-03-20 13:13:08 -07:00
Kenneth Lien
aa4f7c4fb0 Merge remote-tracking branch 'origin/kenneth/discord-edit-notif-guidance' into kenneth/channels-rollup 2026-03-20 13:13:08 -07:00
Kenneth Lien
24a170a704 Merge remote-tracking branch 'origin/kenneth/channels-state-dir' into kenneth/channels-rollup 2026-03-20 13:13:07 -07:00
Kenneth Lien
f3fc62a8e7 Merge remote-tracking branch 'origin/kenneth/telegram-409' into kenneth/channels-rollup
# Conflicts:
#	external_plugins/telegram/server.ts
2026-03-20 13:13:07 -07:00
Kenneth Lien
757480dd76 Merge remote-tracking branch 'origin/kenneth/telegram-shutdown' into kenneth/channels-rollup 2026-03-20 13:12:58 -07:00
Claude
af6b2c490b Remove local stripe external plugin
Now that the stripe plugin sources from the stripe/ai git-subdir, the
locally vendored copy under external_plugins/stripe is no longer needed.
2026-03-20 20:09:40 +00:00
Claude
2bc9dfb449 Update stripe plugin to use git-subdir source
Change the stripe plugin source from local path (./external_plugins/stripe)
to git-subdir pointing to stripe/ai repo at providers/claude/plugin without
SHA pinning.
2026-03-20 19:59:36 +00:00
Kenneth Lien
1636fedbd4 Sanitize user-controlled filenames and download path components
- safeName() strips <>[]\r\n; from file_name/title before they hit the
  <channel> notification — delimiter chars would let an uploader break
  out of the tag or forge meta entries
- download_attachment strips ext/uniqueId to alphanumeric before join()
  — defense-in-depth against path traversal (file_unique_id is
  Telegram-controlled so this is belt-and-braces)
2026-03-20 11:56:57 -07:00
Kenneth Lien
ea382ec6a4 Tighten /start and /help copy
Less chatty, more precise. Explicitly mentions the /telegram:access
skill and the 6-char code format.
2026-03-20 11:55:56 -07:00
Kenneth Lien
9a101ba34c Restrict bot commands to DMs (security)
- /status in a group would leak the sender's pending pairing code to
  other group members, who could then pair as that user
- Commands in non-allowlisted groups confirm bot presence and enable spam
- /start now acknowledges dmPolicy === 'disabled' instead of lying
- setMyCommands scoped to private chats so the / menu only shows in DMs
2026-03-20 11:54:48 -07:00
Kenneth Lien
a9bc23da6f telegram: handle all inbound file types + download_attachment tool 2026-03-20 11:51:42 -07:00
Kenneth Lien
521f858e11 telegram: add /start /help /status bot commands 2026-03-20 11:47:39 -07:00
Kenneth Lien
a7cb39c269 telegram: add MarkdownV2 parse_mode to reply/edit_message 2026-03-20 11:45:46 -07:00
Kenneth Lien
aa71c24314 discord: port resilience fixes from telegram
Same patterns as #812/#813 for the discord channel:
- process-level unhandledRejection/uncaughtException handlers
- client.on('error') to log discord.js errors
- mcp.notification().catch() so inbound delivery failures surface
- stdin close / SIGTERM -> client.destroy() + exit (zombie fix)
- .unref() the approval-check interval
- client.login().catch() to log+exit on bad token instead of crashing

Discord is inherently more resilient than telegram (discord.js
auto-reconnects, no 409 equivalent), but these gaps were still there.
2026-03-20 11:28:51 -07:00
Kenneth Lien
5c58308be4 discord/telegram: guide assistant to send new reply on completion
Message edits don't trigger push notifications on the user's device.
Update system instructions and edit_message tool description to steer
the assistant toward edit-for-progress + new-reply-on-completion.

Fixes #786
2026-03-20 11:27:09 -07:00
Kenneth Lien
3d8042f259 Silently return when bot.stop() aborts the setup phase
If bot.stop() is called while bot.start() is still in setup (deleteWebhook/
getMe), grammy rejects with 'Aborted delay'. Expected, not an error.
2026-03-20 11:07:05 -07:00
Kenneth Lien
14927ff475 telegram/discord: make state dir configurable via env var
Hardcoded ~/.claude/channels/<name>/ meant only one bot per machine.
Respect TELEGRAM_STATE_DIR / DISCORD_STATE_DIR so users can run
multiple bots with separate tokens and allowlists.

Also fixed README path ('in your project' -> '~/...') to match the code.

Fixes #792
2026-03-20 10:56:57 -07:00
Kenneth Lien
1daff5f224 telegram: retry on 409 Conflict instead of crashing
During /mcp reload or when a zombie from a previous session still holds
the polling slot, the new process gets 409 Conflict on its first
getUpdates and dies immediately. Retry with backoff until the slot
frees — typically within a second or two.

Also handles the two-sessions case: the second Claude Code instance
keeps retrying (with a clear message about what's happening) and takes
over when the first one exits.

Fixes #804 #794, partial #788 (issue 4)
2026-03-20 10:55:27 -07:00
Kenneth Lien
2aa90a8387 telegram: exit when Claude Code closes the connection
When the MCP stdio transport closes, the bot kept polling Telegram as
a zombie process — holding the token and causing 409 Conflict for the
next session.

- Listen for stdin end/close and SIGTERM/SIGINT -> bot.stop() + exit
- Force-exit after 2s if bot.stop() stalls on the long-poll timeout
- unref the approval-check interval so it doesn't keep us alive

Fixes #793, partial #788 (issue 3)
2026-03-20 10:54:33 -07:00
Kenneth Lien
9f2a4feab9 telegram: add error handlers to stop silent polling death
The bot would silently stop delivering messages after the first error:
grammy's default handler calls bot.stop() on any middleware throw, and
void bot.start() / void mcp.notification() swallow rejections with no log.

- bot.catch(): log and keep polling on handler errors
- bot.start().catch(): log when polling dies (bad token, 409, network)
- mcp.notification().catch(): log when inbound delivery to Claude fails
- process-level unhandledRejection/uncaughtException as a safety net

Fixes #756 #759 #761 #777 #809, partial #788
2026-03-20 10:53:36 -07:00
Tobin South
90accf6fd2 add(plugin): mcp-server-dev — skills for building MCP servers (#731) 2026-03-20 17:51:32 +00:00
Kenneth Lien
562a27feec Merge pull request #811 from anthropics/kenneth/chmod-env-files
Lock telegram/discord .env files to owner (chmod 600)
2026-03-20 10:48:05 -07:00
Tobin South
d687c591f4 Staging → main: plugin marketplace additions (#730) 2026-03-20 17:41:01 +00:00
Kenneth Lien
8140fbad22 Lock telegram/discord .env files to owner (chmod 600)
The bot token is a credential. Tighten perms on load so hand-written
or pre-existing .env files get locked down, and update the configure
skill to chmod after writing. No-op on Windows.
2026-03-20 10:37:13 -07:00
Kenneth Lien
b664e152af Merge pull request #758 from anthropics/docs/readme-clarifications
README clarifications from docs walkthrough testing
2026-03-19 21:34:55 -07:00
Ralph Furman
c3f6d9e9fa Fix YAML frontmatter — quote description, replace colon with em-dash
Unquoted colon in 'calibrated confidence: will say' broke strict YAML parsing.
CC's parser is lenient but fix for robustness.
2026-03-20 02:07:27 +00:00
Ralph Furman
9720278412 math-olympiad: forbid web access in deep mode
Deep-mode allows bounded local computation but must NOT use WebFetch
or WebSearch. Finding the solution on AoPS is not solving the problem.
Adds explicit NO WEB prompt block and orchestrator self-restraint note.

Found by Ralph's test run (skill solved 5/6 then started fetching
dgrozev.wordpress.com and artofproblemsolving.com for P6).
2026-03-20 00:39:08 +00:00