diff --git a/.changeset/vue-protect-to-show-codemod.md b/.changeset/vue-protect-to-show-codemod.md
new file mode 100644
index 00000000000..bd628f70eb8
--- /dev/null
+++ b/.changeset/vue-protect-to-show-codemod.md
@@ -0,0 +1,5 @@
+---
+'@clerk/upgrade': patch
+---
+
+Add Vue-specific `transform-protect-to-show-vue` codemod that handles `.vue` SFC files with proper Vue v-bind syntax for the Protect to Show migration.
diff --git a/packages/upgrade/src/codemods/__tests__/__fixtures__/transform-protect-to-show-vue.fixtures.js b/packages/upgrade/src/codemods/__tests__/__fixtures__/transform-protect-to-show-vue.fixtures.js
new file mode 100644
index 00000000000..1dcd0fff575
--- /dev/null
+++ b/packages/upgrade/src/codemods/__tests__/__fixtures__/transform-protect-to-show-vue.fixtures.js
@@ -0,0 +1,435 @@
+export const fixtures = [
+ {
+ name: 'Transforms Protect import in Vue SFC',
+ path: 'component.vue',
+ source: `
+
+
+
+
+
+`,
+ output: `
+
+
+
+
+
+`,
+ },
+ {
+ name: 'Transforms SignedIn in Vue SFC',
+ path: 'component.vue',
+ source: `
+
+
+
+
+
+`,
+ output: `
+
+
+
+
+
+`,
+ },
+ {
+ name: 'Transforms SignedOut in Vue SFC',
+ path: 'component.vue',
+ source: `
+
+
+
+
+
+`,
+ output: `
+
+
+
+
+
+`,
+ },
+ {
+ name: 'Transforms Protect with permission in Vue SFC',
+ path: 'component.vue',
+ source: `
+
+
+
+
+
+`,
+ output: `
+
+
+
+
+
+`,
+ },
+ {
+ name: 'Transforms Protect with feature in Vue SFC',
+ path: 'component.vue',
+ source: `
+
+
+
+
+
+`,
+ output: `
+
+
+
+
+
+`,
+ },
+ {
+ name: 'Transforms Protect with plan in Vue SFC',
+ path: 'component.vue',
+ source: `
+
+
+
+
+
+`,
+ output: `
+
+
+
+
+
+`,
+ },
+ {
+ name: 'Transforms Protect with multiple auth props in Vue SFC',
+ path: 'component.vue',
+ source: `
+
+
+
+
+
+`,
+ output: `
+
+
+
+
+
+`,
+ },
+ {
+ name: 'Transforms Protect with condition in Vue SFC',
+ path: 'component.vue',
+ source: `
+
+
+
+
+
+`,
+ output: `
+
+
+
+
+
+`,
+ },
+ {
+ name: 'Transforms Protect with fallback in Vue SFC',
+ path: 'component.vue',
+ source: `
+
+
+
+
+
+`,
+ output: `
+
+
+
+
+
+`,
+ },
+ {
+ name: 'Transforms self-closing Protect in Vue SFC',
+ path: 'component.vue',
+ source: `
+
+
+
+`,
+ output: `
+
+
+
+`,
+ },
+ {
+ name: 'Transforms self-closing SignedIn in Vue SFC',
+ path: 'component.vue',
+ source: `
+
+
+
+`,
+ output: `
+
+
+
+`,
+ },
+ {
+ name: 'Transforms SignedOut with fallback in Vue SFC',
+ path: 'component.vue',
+ source: `
+
+
+
+
+
+`,
+ output: `
+
+
+
+
+
+`,
+ },
+ {
+ name: 'Transforms multiple components in Vue SFC',
+ path: 'component.vue',
+ source: `
+
+
+
+`,
+ output: `
+
+
+
+`,
+ },
+ {
+ name: 'Transforms ProtectProps type in Vue SFC',
+ path: 'component.vue',
+ source: `
+
+
+
+
+
+`,
+ output: `
+
+
+
+
+
+`,
+ },
+ {
+ name: 'Transforms Protect with dynamic binding in Vue SFC',
+ path: 'component.vue',
+ source: `
+
+
+
+
+
+`,
+ output: `
+
+
+
+
+
+`,
+ },
+ {
+ name: 'Does not transform non-.vue files',
+ path: 'component.tsx',
+ source: `import { Protect } from "@clerk/vue"
+
+const App = () => (
+
+
+
+)`,
+ output: null,
+ },
+ {
+ name: 'Does not transform non-clerk imports in Vue SFC',
+ path: 'component.vue',
+ source: `
+
+
+
+
+
+`,
+ output: null,
+ },
+ {
+ name: 'Transforms Protect with no props to default signed-in',
+ path: 'component.vue',
+ source: `
+
+
+
+
+
+`,
+ output: `
+
+
+
+
+
+`,
+ },
+ {
+ name: 'Transforms Nuxt import in Vue SFC',
+ path: 'component.vue',
+ source: `
+
+
+
+
+
+
+
+
+`,
+ output: null, // #clerk is not @clerk/* so should not transform
+ },
+ {
+ name: 'Preserves other attributes on Protect in Vue SFC',
+ path: 'component.vue',
+ source: `
+
+
+
+
+
+`,
+ output: `
+
+
+
+
+
+`,
+ },
+];
diff --git a/packages/upgrade/src/codemods/__tests__/transform-protect-to-show-vue.test.js b/packages/upgrade/src/codemods/__tests__/transform-protect-to-show-vue.test.js
new file mode 100644
index 00000000000..2e7591b72db
--- /dev/null
+++ b/packages/upgrade/src/codemods/__tests__/transform-protect-to-show-vue.test.js
@@ -0,0 +1,18 @@
+import { applyTransform } from 'jscodeshift/dist/testUtils';
+import { describe, expect, it } from 'vitest';
+
+import transformer from '../transform-protect-to-show-vue.cjs';
+import { fixtures } from './__fixtures__/transform-protect-to-show-vue.fixtures';
+
+describe('transform-protect-to-show-vue', () => {
+ it.each(fixtures)(`$name`, ({ source, output, path }) => {
+ const result = applyTransform(transformer, {}, { source, path });
+
+ if (output === null) {
+ // null output means no transformation should occur
+ expect(result).toBeFalsy();
+ } else {
+ expect(result).toEqual(output.trim());
+ }
+ });
+});
diff --git a/packages/upgrade/src/codemods/transform-protect-to-show-vue.cjs b/packages/upgrade/src/codemods/transform-protect-to-show-vue.cjs
new file mode 100644
index 00000000000..b3077aef3dd
--- /dev/null
+++ b/packages/upgrade/src/codemods/transform-protect-to-show-vue.cjs
@@ -0,0 +1,393 @@
+const CLERK_PACKAGE_PREFIX = '@clerk/';
+
+const isClerkPackageSource = sourceValue => {
+ return typeof sourceValue === 'string' && sourceValue.startsWith(CLERK_PACKAGE_PREFIX);
+};
+
+/**
+ * Vue-specific codemod to transform ``, ``, and `` components to ``.
+ *
+ * This codemod handles Vue SFC (.vue) files, transforming both:
+ * - Script imports (ESM/CJS)
+ * - Template component usage with Vue's v-bind syntax
+ *
+ * Template transformations:
+ * - `` → ``
+ * - `` → ``
+ * - `` → ``
+ * - `` → ``
+ * - `` → ``
+ *
+ * @param {import('jscodeshift').FileInfo} fileInfo - The file information
+ * @param {import('jscodeshift').API} api - The API object provided by jscodeshift
+ * @returns {string|undefined} - The transformed source code if modifications were made
+ */
+module.exports = function transformProtectToShowVue(fileInfo, { jscodeshift: j }) {
+ const { source, path: filePath } = fileInfo;
+
+ // Only process .vue files
+ if (!filePath || !filePath.endsWith('.vue')) {
+ return undefined;
+ }
+
+ let dirtyFlag = false;
+ let result = source;
+
+ // Track which components were imported from @clerk/*
+ const importedComponents = new Set();
+
+ // Extract and transform
+ const scriptMatch = result.match(/(