diff --git a/docs/product/explore/logs/getting-started/index.mdx b/docs/product/explore/logs/getting-started/index.mdx
index a743b1fe17cd0..10d82fbc7a1fd 100644
--- a/docs/product/explore/logs/getting-started/index.mdx
+++ b/docs/product/explore/logs/getting-started/index.mdx
@@ -14,156 +14,187 @@ To set up Sentry Logs, use the links below for supported SDKs. After it's been s
platform="javascript.browser"
label="Browser JavaScript"
url="/platforms/javascript/logs/"
+ skill="sentry-browser-sdk"
/>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
### Java
@@ -190,40 +221,47 @@ To set up Sentry Logs, use the links below for supported SDKs. After it's been s
platform="android"
label="Android"
url="/platforms/android/logs/"
+ skill="sentry-android-sdk"
/>
-
-
-
-
### PHP
--
+-
-
-
### Python
@@ -232,6 +270,7 @@ To set up Sentry Logs, use the links below for supported SDKs. After it's been s
platform="python"
label="Python"
url="/platforms/python/logs/"
+ skill="sentry-python-sdk"
/>
### Ruby
@@ -240,16 +279,18 @@ To set up Sentry Logs, use the links below for supported SDKs. After it's been s
platform="ruby"
label="Ruby"
url="/platforms/ruby/logs/"
+ skill="sentry-ruby-sdk"
/>
-
### Go
--
+-
### Rust
@@ -265,26 +306,31 @@ To set up Sentry Logs, use the links below for supported SDKs. After it's been s
platform="dotnet"
label=".NET"
url="/platforms/dotnet/logs/"
+ skill="sentry-dotnet-sdk"
/>
-
-
-
-
### Native
diff --git a/docs/product/explore/metrics/getting-started/index.mdx b/docs/product/explore/metrics/getting-started/index.mdx
index c15e6d8c0bef2..49352cc718de3 100644
--- a/docs/product/explore/metrics/getting-started/index.mdx
+++ b/docs/product/explore/metrics/getting-started/index.mdx
@@ -14,156 +14,187 @@ To set up Sentry's Application Metrics, use the links below for supported SDKs.
platform="javascript.browser"
label="Browser JavaScript"
url="/platforms/javascript/metrics/"
+ skill="sentry-browser-sdk"
/>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
### Java
@@ -190,6 +221,7 @@ To set up Sentry's Application Metrics, use the links below for supported SDKs.
platform="elixir"
label="Elixir"
url="/platforms/elixir/metrics/"
+ skill="sentry-elixir-sdk"
/>
### Mobile
@@ -198,41 +230,49 @@ To set up Sentry's Application Metrics, use the links below for supported SDKs.
platform="android"
label="Android"
url="/platforms/android/metrics/"
+ skill="sentry-android-sdk"
/>
-
-
-
-
-
-
-
### Python
@@ -241,41 +281,49 @@ To set up Sentry's Application Metrics, use the links below for supported SDKs.
platform="python"
label="Python"
url="/platforms/python/metrics/"
+ skill="sentry-python-sdk"
/>
-
-
-
-
-
-
-
### PHP
@@ -284,16 +332,19 @@ To set up Sentry's Application Metrics, use the links below for supported SDKs.
platform="php"
label="PHP"
url="/platforms/php/metrics/"
+ skill="sentry-php-sdk"
/>
-
-
### Ruby
@@ -302,6 +353,7 @@ To set up Sentry's Application Metrics, use the links below for supported SDKs.
platform="ruby"
label="Ruby (incl. Rails)"
url="/platforms/ruby/metrics/"
+ skill="sentry-ruby-sdk"
/>
### Go
@@ -310,6 +362,7 @@ To set up Sentry's Application Metrics, use the links below for supported SDKs.
platform="go"
label="Go"
url="/platforms/go/metrics/"
+ skill="sentry-go-sdk"
/>
### .NET
@@ -318,91 +371,109 @@ To set up Sentry's Application Metrics, use the links below for supported SDKs.
platform="dotnet"
label=".NET"
url="/platforms/dotnet/metrics/"
+ skill="sentry-dotnet-sdk"
/>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
### Native
diff --git a/docs/product/explore/profiling/getting-started.mdx b/docs/product/explore/profiling/getting-started.mdx
index 3561477c4c9c2..847f18be738bf 100644
--- a/docs/product/explore/profiling/getting-started.mdx
+++ b/docs/product/explore/profiling/getting-started.mdx
@@ -26,11 +26,13 @@ Continuous Profiling can be used both independently and as a complement to the t
platform="python"
label="Python (since version 2.24.1)"
url="/platforms/python/profiling/"
+ skill="sentry-python-sdk"
/>
-
### UI Profiling
@@ -45,21 +47,25 @@ UI Profiling can be used both independently and as a complement to the tracing p
platform="apple"
label="iOS & macOS (since version 8.49.0)"
url="/platforms/apple/profiling/"
+ skill="sentry-cocoa-sdk"
/>
-
-
-
### Transaction-based Profiling
@@ -78,16 +84,19 @@ Transaction-based Profiling requires Sentry's tracing product being enabled befo
platform="react-native"
label="React Native (beta)"
url="/platforms/react-native/profiling/"
+ skill="sentry-react-native-sdk"
/>
-
-
#### Standalone and server apps
@@ -96,14 +105,17 @@ Transaction-based Profiling requires Sentry's tracing product being enabled befo
platform="php"
label="PHP"
url="/platforms/php/profiling/"
+ skill="sentry-php-sdk"
/>
-
-
diff --git a/src/components/agentSkillsCallout/index.tsx b/src/components/agentSkillsCallout/index.tsx
index a1672cb68d9b2..3cea70876d787 100644
--- a/src/components/agentSkillsCallout/index.tsx
+++ b/src/components/agentSkillsCallout/index.tsx
@@ -9,11 +9,9 @@ import {DocMetrics} from 'sentry-docs/metrics';
import {CodeBlock} from '../codeBlock';
import {CodeTabs} from '../codeTabs';
+import {buildDotagentsCommand, buildNpxSkillsCommand, buildPrompt} from './shared';
import styles from './style.module.scss';
-const SKILLS_BASE_URL = 'https://skills.sentry.dev';
-const SKILLS_REPO = 'getsentry/sentry-for-ai';
-
type Props = {
/** Display name for the platform, e.g. "Next.js", "Python". Omit for generic. */
platformName?: string;
@@ -21,32 +19,6 @@ type Props = {
skill?: string;
};
-function buildPromptUrl(skill?: string): string {
- if (!skill) {
- return SKILLS_BASE_URL + '/';
- }
- return `${SKILLS_BASE_URL}/${skill}/SKILL.md`;
-}
-
-function buildPrompt(skill?: string): string {
- const url = buildPromptUrl(skill);
- return `Use curl to download, read and follow: ${url}`;
-}
-
-function buildDotagentsCommand(skill?: string): string {
- if (!skill) {
- return `npx @sentry/dotagents add ${SKILLS_REPO} --all`;
- }
- return `npx @sentry/dotagents add ${SKILLS_REPO} --name ${skill}`;
-}
-
-function buildNpxSkillsCommand(skill?: string): string {
- if (!skill) {
- return `npx skills add ${SKILLS_REPO}`;
- }
- return `npx skills add ${SKILLS_REPO} --skill ${skill}`;
-}
-
export function AgentSkillsCallout({skill, platformName}: Props) {
const [copied, setCopied] = useState(false);
const [isExpanded, setIsExpanded] = useState(false);
diff --git a/src/components/agentSkillsCallout/shared.ts b/src/components/agentSkillsCallout/shared.ts
new file mode 100644
index 0000000000000..3decc8ede4243
--- /dev/null
+++ b/src/components/agentSkillsCallout/shared.ts
@@ -0,0 +1,33 @@
+/**
+ * Shared constants and utilities for agent skills prompt building.
+ * Used by AgentSkillsCallout (full banner) and inline copy-prompt buttons.
+ */
+
+export const SKILLS_BASE_URL = 'https://skills.sentry.dev';
+export const SKILLS_REPO = 'getsentry/sentry-for-ai';
+
+export function buildPromptUrl(skill?: string): string {
+ if (!skill) {
+ return SKILLS_BASE_URL + '/';
+ }
+ return `${SKILLS_BASE_URL}/${skill}/SKILL.md`;
+}
+
+export function buildPrompt(skill?: string): string {
+ const url = buildPromptUrl(skill);
+ return `Use curl to download, read and follow: ${url}`;
+}
+
+export function buildDotagentsCommand(skill?: string): string {
+ if (!skill) {
+ return `npx @sentry/dotagents add ${SKILLS_REPO} --all`;
+ }
+ return `npx @sentry/dotagents add ${SKILLS_REPO} --name ${skill}`;
+}
+
+export function buildNpxSkillsCommand(skill?: string): string {
+ if (!skill) {
+ return `npx skills add ${SKILLS_REPO}`;
+ }
+ return `npx skills add ${SKILLS_REPO} --skill ${skill}`;
+}
diff --git a/src/components/copyPromptButton/index.tsx b/src/components/copyPromptButton/index.tsx
new file mode 100644
index 0000000000000..b010c98c41971
--- /dev/null
+++ b/src/components/copyPromptButton/index.tsx
@@ -0,0 +1,132 @@
+'use client';
+
+import * as Tooltip from '@radix-ui/react-tooltip';
+import {Theme} from '@radix-ui/themes';
+import * as Sentry from '@sentry/nextjs';
+import {useTheme} from 'next-themes';
+import {useCallback, useMemo, useState} from 'react';
+import {usePlausibleEvent} from 'sentry-docs/hooks/usePlausibleEvent';
+import {DocMetrics} from 'sentry-docs/metrics';
+
+import {buildPrompt} from '../agentSkillsCallout/shared';
+import styles from './style.module.scss';
+
+type Props = {
+ /** Skill package name, e.g. "sentry-nextjs-sdk". */
+ skill: string;
+};
+
+export function CopyPromptButton({skill}: Props) {
+ const [copied, setCopied] = useState(false);
+ const {emit} = usePlausibleEvent();
+ const {resolvedTheme} = useTheme();
+ const isDark = resolvedTheme === 'dark';
+
+ const prompt = buildPrompt(skill);
+
+ /**
+ * Tooltip styles matching the onboarding tooltip pattern.
+ * Inline styles are required because Radix portals the tooltip to document.body,
+ * outside the Theme wrapper, so CSS module classes don't reliably apply.
+ */
+ const tooltipContentStyle: React.CSSProperties = useMemo(
+ () => ({
+ borderRadius: '4px',
+ padding: '8px 12px',
+ fontSize: '12px',
+ lineHeight: 1.2,
+ textAlign: 'center' as const,
+ color: isDark ? 'var(--foreground)' : 'var(--gray-11)',
+ backgroundColor: isDark ? 'var(--gray-4)' : 'white',
+ boxShadow: '0px 4px 16px 0px rgba(31, 22, 51, 0.1)',
+ zIndex: 9999,
+ position: 'relative' as const,
+ pointerEvents: 'none' as const,
+ userSelect: 'none' as const,
+ whiteSpace: 'nowrap' as const,
+ animationDuration: '100ms',
+ animationTimingFunction: 'ease-in',
+ }),
+ [isDark]
+ );
+
+ const tooltipArrowStyle: React.CSSProperties = useMemo(
+ () => ({
+ fill: isDark ? 'var(--gray-4)' : 'white',
+ }),
+ [isDark]
+ );
+
+ const copyPrompt = useCallback(
+ async (event: React.MouseEvent) => {
+ event.stopPropagation();
+ event.preventDefault();
+
+ emit('Copy AI Prompt', {
+ props: {page: window.location.pathname, title: 'Inline Platform Link'},
+ });
+
+ try {
+ setCopied(false);
+ await navigator.clipboard.writeText(prompt);
+ setCopied(true);
+ DocMetrics.copyAIPrompt(window.location.pathname, skill, true, 'inline_link');
+ setTimeout(() => setCopied(false), 1500);
+ } catch (error) {
+ Sentry.captureException(error);
+ DocMetrics.copyAIPrompt(window.location.pathname, skill, false, 'inline_link');
+ setCopied(false);
+ }
+ },
+ [prompt, emit, skill]
+ );
+
+ return (
+
+ |
+
+
+
+
+
+ {!copied && (
+
+
+
+ Copy setup prompt for AI agents
+
+
+
+
+ )}
+
+
+
+ );
+}
+
+function CopyIcon() {
+ return (
+
+ );
+}
diff --git a/src/components/copyPromptButton/style.module.scss b/src/components/copyPromptButton/style.module.scss
new file mode 100644
index 0000000000000..4bc6f92171583
--- /dev/null
+++ b/src/components/copyPromptButton/style.module.scss
@@ -0,0 +1,70 @@
+.wrapper {
+ display: inline-flex;
+ align-items: center;
+ margin-left: 0.4rem;
+ vertical-align: middle;
+
+ @media (max-width: 768px) {
+ display: none;
+ }
+}
+
+.divider {
+ color: var(--gray-200);
+ font-size: 0.85rem;
+ margin-right: 0.4rem;
+ user-select: none;
+}
+
+:global(.dark) .divider {
+ color: var(--gray-600);
+}
+
+.button {
+ display: inline-flex;
+ align-items: center;
+ gap: 0.3rem;
+ padding: 0.15rem 0.5rem;
+ border: 1px solid color-mix(in srgb, var(--accent-purple), transparent 60%);
+ border-radius: 4px;
+ background: color-mix(in srgb, var(--accent-purple), transparent 92%);
+ color: var(--accent-purple);
+ font-size: 0.72rem;
+ font-weight: 500;
+ white-space: nowrap;
+ cursor: pointer;
+ transition:
+ background-color 150ms,
+ border-color 150ms;
+ line-height: 1.4;
+
+ &:hover {
+ background: color-mix(in srgb, var(--accent-purple), transparent 82%);
+ border-color: color-mix(in srgb, var(--accent-purple), transparent 40%);
+ }
+
+ &:active {
+ background: color-mix(in srgb, var(--accent-purple), transparent 72%);
+ }
+}
+
+:global(.dark) .button {
+ background: color-mix(in srgb, var(--accent-purple), transparent 85%);
+ border-color: color-mix(in srgb, var(--accent-purple), transparent 50%);
+ color: var(--accent-purple-light, var(--accent-purple));
+
+ &:hover {
+ background: color-mix(in srgb, var(--accent-purple), transparent 75%);
+ border-color: color-mix(in srgb, var(--accent-purple), transparent 30%);
+ }
+
+ &:active {
+ background: color-mix(in srgb, var(--accent-purple), transparent 65%);
+ }
+}
+
+.label {
+ letter-spacing: 0.01em;
+}
+
+
diff --git a/src/components/linkWithPlatformIcon.tsx b/src/components/linkWithPlatformIcon.tsx
index 84b22326de675..17ae9d8b53e1a 100644
--- a/src/components/linkWithPlatformIcon.tsx
+++ b/src/components/linkWithPlatformIcon.tsx
@@ -1,13 +1,16 @@
+import {CopyPromptButton} from './copyPromptButton';
import {PlatformIcon} from './platformIcon';
import {SmartLink} from './smartLink';
type Props = {
label?: string;
platform?: string;
+ /** Agent skill name, e.g. "sentry-react-sdk". When provided, renders an inline "Agent Setup" copy-prompt button. */
+ skill?: string;
url?: string;
};
-export function LinkWithPlatformIcon({platform, label, url}: Props) {
+export function LinkWithPlatformIcon({platform, label, url, skill}: Props) {
if (!platform) {
return null;
}
@@ -27,6 +30,7 @@ export function LinkWithPlatformIcon({platform, label, url}: Props) {
/>
{label ?? platform}
+ {skill && }
);
}
diff --git a/src/metrics.ts b/src/metrics.ts
index d4b34347e6c1d..8e0343e3f7064 100644
--- a/src/metrics.ts
+++ b/src/metrics.ts
@@ -166,13 +166,20 @@ export const DocMetrics = {
* @param pathname - Page where the prompt was copied
* @param skill - Skill name if present (e.g., "sentry-nextjs-sdk")
* @param success - Whether the clipboard copy succeeded
+ * @param source - Where the copy was triggered from ('callout' for the full banner, 'inline_link' for platform list buttons)
*/
- copyAIPrompt: (pathname: string, skill: string | undefined, success: boolean) => {
+ copyAIPrompt: (
+ pathname: string,
+ skill: string | undefined,
+ success: boolean,
+ source: 'callout' | 'inline_link' = 'callout'
+ ) => {
Sentry.metrics.count('docs.copy_ai_prompt', 1, {
attributes: {
page_path: pathname.split('/').slice(0, 3).join('/'), // First 3 segments
skill: skill || 'generic',
success,
+ source,
},
});
},