
Security News
/Research
Fake Corepack Site Distributes Infostealer and Proxyware to Developers
A fake corepack.org site is impersonating the Node.js tool and delivers an infostealer and proxyware to developers who download it.
claudebuttons
Advanced tools
Drop-in "Run on Claude Code" and "Run on Cowork" buttons for any website or framework
Drop-in "Run on Claude Code" and "Run on Cowork" buttons for any website or framework. Built as framework-agnostic Web Components with zero dependencies.
npm install claudebuttons
Or use the CDN (no build step):
<script src="https://unpkg.com/claudebuttons"></script>
<claude-code-button command="/my-skill --flag" theme="branded"></claude-code-button>
<cowork-button command="/my-skill" skill-url="https://example.com/skill.zip"></cowork-button>
<script src="https://unpkg.com/claudebuttons"></script>
<claude-code-button command="/deploy --prod" theme="branded"></claude-code-button>
<cowork-button command="/review" theme="dark"></cowork-button>
<script>
document.querySelector('claude-code-button')
.addEventListener('cb-copy', (e) => console.log('Copied:', e.detail.command));
</script>
Use the dedicated React wrappers (handles SSR, hydration, and prop forwarding):
import { ClaudeCodeButton, CoworkButton } from 'claudebuttons/react';
function App() {
return (
<>
<ClaudeCodeButton
command="/my-skill --flag"
theme="branded"
onCopy={(cmd) => console.log('Copied:', cmd)}
onCbCopy={(e) => console.log('Event:', e.detail.command)}
/>
<CoworkButton
command="/code-review"
skillUrl="https://example.com/skill.zip"
theme="dark"
/>
</>
);
}
The React wrapper:
'use client' for Next.js App RoutersuppressHydrationWarningonCopy) and CustomEvent listeners (onCbCopy)Option A: Vue Plugin (recommended)
// main.ts
import { createApp } from 'vue';
import { ClaudeButtonsPlugin } from 'claudebuttons/vue';
import App from './App.vue';
const app = createApp(App);
app.use(ClaudeButtonsPlugin); // auto-configures isCustomElement
app.mount('#app');
<template>
<claude-code-button
command="/my-skill"
theme="branded"
@cb-copy="onCopy"
/>
<cowork-button
command="/review"
theme="dark"
@cb-download="onDownload"
/>
</template>
<script setup>
function onCopy(e) {
console.log('Copied:', e.detail.command);
}
function onDownload(e) {
console.log('Downloaded:', e.detail.url);
}
</script>
Option B: Manual setup
// vite.config.ts
import vue from '@vitejs/plugin-vue';
export default {
plugins: [
vue({
template: {
compilerOptions: {
isCustomElement: (tag) =>
['claude-code-button', 'cowork-button', 'claude-popup-dialog'].includes(tag),
},
},
}),
],
};
<script setup>
import 'claudebuttons';
</script>
<template>
<claude-code-button command="/my-skill" theme="branded" @cb-copy="onCopy" />
</template>
<script>
import 'claudebuttons';
function handleCopy(e) {
console.log('Copied:', e.detail.command);
}
</script>
<claude-code-button
command="/my-skill"
theme="branded"
on:cb-copy={handleCopy}
/>
<cowork-button command="/review" theme="dark" />
// app.module.ts
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import 'claudebuttons';
@NgModule({
schemas: [CUSTOM_ELEMENTS_SCHEMA],
// ...
})
export class AppModule {}
<!-- component.html -->
<claude-code-button
command="/my-skill"
theme="branded"
(cb-copy)="onCopy($event)"
></claude-code-button>
<cowork-button
command="/review"
skill-url="https://example.com/skill.zip"
theme="dark"
(cb-download)="onDownload($event)"
></cowork-button>
import 'claudebuttons';
function App() {
return (
<>
<claude-code-button
command="/my-skill"
theme="branded"
on:cb-copy={(e) => console.log(e.detail.command)}
/>
<cowork-button command="/review" theme="dark" />
</>
);
}
---
---
<script>
import 'claudebuttons';
</script>
<claude-code-button command="/my-skill" theme="branded" />
<cowork-button command="/review" theme="dark" />
<script>
document.querySelector('claude-code-button')
?.addEventListener('cb-copy', (e) => console.log(e.detail.command));
</script>
import { createClaudeCodeButton, createCoworkButton } from 'claudebuttons';
const btn = createClaudeCodeButton({
command: '/deploy --prod',
theme: 'branded',
onCopy: (cmd) => console.log('Copied:', cmd),
});
document.getElementById('container').appendChild(btn);
| Theme | Description |
|---|---|
branded | Terracotta primary (#D4795C), white text (default) |
dark | Dark surface, light text, terracotta accents |
light | White surface, dark text, terracotta accents |
system | Auto-switches between light/dark based on prefers-color-scheme |
| Size | Height |
|---|---|
sm | 2rem (32px at default font size) |
md | 2.5rem (40px) (default) |
lg | 3rem (48px) |
Sizes use rem units and scale with the user's browser font preferences.
All buttons dispatch native CustomEvents with bubbles: true and composed: true (crosses Shadow DOM).
| Event | Detail | Fired when |
|---|---|---|
cb-copy | { command: string } | Command copied to clipboard |
cb-open | { command: string } | Button clicked / popup opens |
cb-close | — | Popup closed |
cb-download | { url: string } | Skill package downloaded (Cowork only) |
el.addEventListener('cb-copy', (e) => {
console.log('Copied:', e.detail.command);
});
<claude-code-button> Attributes| Attribute | Type | Default | Description |
|---|---|---|---|
command | string | — | The skill/command to run |
theme | 'branded' | 'dark' | 'light' | 'system' | 'branded' | Theme variant |
size | 'sm' | 'md' | 'lg' | 'md' | Button size |
popup | 'true' | 'false' | 'true' | Show popup dialog on click |
prompt-flag | 'true' | 'false' | 'true' | Prepend claude -p to command |
popup-title | string | 'Run on Claude Code' | Custom popup title |
popup-description | string | — | Custom popup description |
<cowork-button> Attributes| Attribute | Type | Default | Description |
|---|---|---|---|
command | string | — | The slash command to run |
skill-url | string | — | URL to downloadable skill package |
theme | 'branded' | 'dark' | 'light' | 'system' | 'branded' | Theme variant |
size | 'sm' | 'md' | 'lg' | 'md' | Button size |
popup | 'true' | 'false' | 'true' | Show popup dialog on click |
popup-title | string | 'Run on Cowork' | Custom popup title |
popup-description | string | — | Custom popup description |
// Web Components + factories
import {
ClaudeCodeButton, // Web Component class
CoworkButton, // Web Component class
createClaudeCodeButton, // Factory function
createCoworkButton, // Factory function
showPopup, // Show popup programmatically
register, // Manually register all custom elements
registerClaudeCodeButton, // Register only claude-code-button
registerCoworkButton, // Register only cowork-button
} from 'claudebuttons';
// React wrappers (SSR-safe, includes 'use client')
import { ClaudeCodeButton, CoworkButton } from 'claudebuttons/react';
// Vue plugin
import { ClaudeButtonsPlugin } from 'claudebuttons/vue';
// Raw SVG icons
import { CLAUDE_CODE_ICON, COWORK_ICON } from 'claudebuttons';
Registration happens automatically on import. For frameworks that need timing control:
import { register } from 'claudebuttons';
// Call when you're ready to register the custom elements
register();
Or register individually with custom tag names:
import { registerClaudeCodeButton, registerCoworkButton } from 'claudebuttons';
registerClaudeCodeButton('my-claude-btn');
registerCoworkButton('my-cowork-btn');
Works in all browsers that support Custom Elements v1:
MIT
FAQs
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
/Research
A fake corepack.org site is impersonating the Node.js tool and delivers an infostealer and proxyware to developers who download it.

Research
/Security News
A large-scale campaign abused GitHub Actions in compromised repositories to exploit CVE-2026-41940 in cPanel and WHM and steal server credentials.

Security News
Five frontier LLMs generated the same nonexistent package names, leaving 53 available for potential slopsquatting across PyPI and npm.