diff --git a/CHANGELOG.md b/CHANGELOG.md
index 897a909a04..9b43319614 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -24,6 +24,7 @@
 - Feat: 絵文字の詳細ダイアログを追加
 - Feat: 枠線をつけるMFM`$[border.width=1,style=solid,color=fff,radius=0 ...]`を追加
   - デフォルトで枠線からはみ出る部分が隠されるようにしました。初期と同じ挙動にするには`$[border.noclip`が必要です
+- Enhance: MFM等のコードブロックに全文コピー用のボタンを追加
 - Enhance: ハッシュタグ入力時に、本文の末尾の行に何も書かれていない場合は新たにスペースを追加しないように
 - Enhance: チャンネルノートのピン留めをノートのメニューからできるように
 - Enhance: 管理者の場合はAPI tokenの発行画面で管理機能に関する権限を付与できるように
diff --git a/packages/frontend/src/components/MkCode.vue b/packages/frontend/src/components/MkCode.vue
index 2c016e4d7c..b81afe2920 100644
--- a/packages/frontend/src/components/MkCode.vue
+++ b/packages/frontend/src/components/MkCode.vue
@@ -4,29 +4,36 @@ SPDX-License-Identifier: AGPL-3.0-only
 -->
 
 <template>
-<Suspense>
-	<template #fallback>
-		<MkLoading v-if="!inline ?? true"/>
-	</template>
-	<code v-if="inline" :class="$style.codeInlineRoot">{{ code }}</code>
-	<XCode v-else-if="show && lang" :code="code" :lang="lang"/>
-	<pre v-else-if="show" :class="$style.codeBlockFallbackRoot"><code :class="$style.codeBlockFallbackCode">{{ code }}</code></pre>
-	<button v-else :class="$style.codePlaceholderRoot" @click="show = true">
-		<div :class="$style.codePlaceholderContainer">
-			<div><i class="ti ti-code"></i> {{ i18n.ts.code }}</div>
-			<div>{{ i18n.ts.clickToShow }}</div>
-		</div>
+<code v-if="inline" :class="$style.codeInlineRoot">{{ code }}</code>
+<div v-else :class="$style.codeBlockRoot">
+	<button :class="$style.codeBlockCopyButton" class="_button" @click="copy">
+		<i class="ti ti-copy"></i>
 	</button>
-</Suspense>
+	<Suspense>
+		<template #fallback>
+			<MkLoading />
+		</template>
+		<XCode v-if="show && lang" :code="code" :lang="lang"/>
+		<pre v-else-if="show" :class="$style.codeBlockFallbackRoot"><code :class="$style.codeBlockFallbackCode">{{ code }}</code></pre>
+		<button v-else :class="$style.codePlaceholderRoot" @click="show = true">
+			<div :class="$style.codePlaceholderContainer">
+				<div><i class="ti ti-code"></i> {{ i18n.ts.code }}</div>
+				<div>{{ i18n.ts.clickToShow }}</div>
+			</div>
+		</button>
+	</Suspense>
+</div>
 </template>
 
 <script lang="ts" setup>
 import { defineAsyncComponent, ref } from 'vue';
+import * as os from '@/os.js';
 import MkLoading from '@/components/global/MkLoading.vue';
 import { defaultStore } from '@/store.js';
 import { i18n } from '@/i18n.js';
+import copyToClipboard from '@/scripts/copy-to-clipboard.js';
 
-defineProps<{
+const props = defineProps<{
 	code: string;
 	lang?: string;
 	inline?: boolean;
@@ -35,9 +42,30 @@ defineProps<{
 const show = ref(!defaultStore.state.dataSaver.code);
 
 const XCode = defineAsyncComponent(() => import('@/components/MkCode.core.vue'));
+
+function copy() {
+	copyToClipboard(props.code);
+	os.success();
+}
 </script>
 
 <style module lang="scss">
+.codeBlockRoot {
+	position: relative;
+}
+
+.codeBlockCopyButton {
+	color: #D4D4D4;
+	position: absolute;
+	top: 8px;
+	right: 8px;
+	opacity: 0.5;
+
+	&:hover {
+		opacity: 0.8;
+	}
+}
+
 .codeInlineRoot {
 	display: inline-block;
 	font-family: Consolas, Monaco, Andale Mono, Ubuntu Mono, monospace;