diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index 526f9b0f35..c34f398c94 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -581,6 +581,8 @@ common/views/components/note-menu.vue:
   unpin: "ピン留め解除"
   delete: "削除"
   delete-confirm: "この投稿を削除しますか?"
+  delete-and-edit: "削除して編集"
+  delete-and-edit-confirm: "この投稿を削除してもう一度編集しますか?この投稿へのリアクション、リノート、返信も全て削除されます。"
   remote: "投稿元で見る"
   pin-limit-exceeded: "これ以上ピン留めできません。"
 
diff --git a/src/client/app/common/scripts/post-form.ts b/src/client/app/common/scripts/post-form.ts
index ff3fd0792b..2b591ac659 100644
--- a/src/client/app/common/scripts/post-form.ts
+++ b/src/client/app/common/scripts/post-form.ts
@@ -35,6 +35,10 @@ export default (opts) => ({
 			type: String,
 			required: false
 		},
+		initialNote: {
+			type: Object,
+			required: false
+		},
 		instant: {
 			type: Boolean,
 			required: false,
@@ -195,6 +199,28 @@ export default (opts) => ({
 					this.$emit('change-attached-files', this.files);
 				}
 			}
+			if (this.initialNote) {
+				// 削除して編集
+				const init = this.initialNote;
+				this.text = init.text ? init.text : '';
+				this.files = init.files;
+				this.cw = init.cw;
+				this.useCw = init.cw != null;
+				if (init.poll) {
+					this.poll = true;
+					this.$nextTick(() => {
+						(this.$refs.poll as any).set({
+							choices: init.poll.choices.map(c => c.text),
+							multiple: init.poll.multiple
+						});
+					});
+				}
+				// hack 位置情報投稿が動くようになったら適用する
+				this.geo = null;
+				this.visibility = init.visibility;
+				this.localOnly = init.localOnly;
+				this.quoteId = init.renote ? init.renote.id : null;
+			}
 
 			this.$nextTick(() => this.watch());
 		});
diff --git a/src/client/app/common/views/components/note-menu.vue b/src/client/app/common/views/components/note-menu.vue
index f3bb5c38c8..6e2b778b32 100644
--- a/src/client/app/common/views/components/note-menu.vue
+++ b/src/client/app/common/views/components/note-menu.vue
@@ -74,7 +74,13 @@ export default Vue.extend({
 				action: () => this.togglePin(true)
 			} : undefined,
 			...(this.note.userId == this.$store.state.i.id || this.$store.state.i.isAdmin || this.$store.state.i.isModerator ? [
-				null, {
+				null,
+				this.note.userId == this.$store.state.i.id ? {
+					icon: 'undo-alt',
+					text: this.$t('delete-and-edit'),
+					action: this.deleteAndEdit
+				} : undefined,
+				{
 					icon: ['far', 'trash-alt'],
 					text: this.$t('delete'),
 					action: this.del
@@ -154,6 +160,25 @@ export default Vue.extend({
 			});
 		},
 
+		deleteAndEdit() {
+			this.$root.dialog({
+				type: 'warning',
+				text: this.$t('delete-and-edit-confirm'),
+				showCancelButton: true
+			}).then(({ canceled }) => {
+				if (canceled) return;
+				this.$root.api('notes/delete', {
+					noteId: this.note.id
+				}).then(() => {
+					this.destroyDom();
+				});
+				this.$post({
+					initialNote: this.note,
+					reply: this.note.reply,
+				});
+			});
+		},
+
 		toggleFavorite(favorite: boolean) {
 			this.$root.api(favorite ? 'notes/favorites/create' : 'notes/favorites/delete', {
 				noteId: this.note.id
diff --git a/src/client/app/desktop/script.ts b/src/client/app/desktop/script.ts
index 1a4be33020..32e4886de3 100644
--- a/src/client/app/desktop/script.ts
+++ b/src/client/app/desktop/script.ts
@@ -63,7 +63,10 @@ init(async (launch, os) => {
 					this.$root.newAsync(() => import('./views/components/post-form-window.vue').then(m => m.default), {
 						reply: o.reply,
 						mention: o.mention,
-						animation: o.animation == null ? true : o.animation
+						animation: o.animation == null ? true : o.animation,
+						initialText: o.initialText,
+						instant: o.instant,
+						initialNote: o.initialNote,
 					}).then(vm => {
 						if (o.cb) vm.$once('closed', o.cb);
 					});
diff --git a/src/client/app/desktop/views/components/post-form-window.vue b/src/client/app/desktop/views/components/post-form-window.vue
index 78e69049a1..ff6f24b6e1 100644
--- a/src/client/app/desktop/views/components/post-form-window.vue
+++ b/src/client/app/desktop/views/components/post-form-window.vue
@@ -15,6 +15,10 @@
 		<x-post-form ref="form"
 			:reply="reply"
 			:mention="mention"
+			:initial-text="initialText"
+			:initial-note="initialNote"
+			:instant="instant"
+
 			@posted="onPosted"
 			@change-uploadings="onChangeUploadings"
 			@change-attached-files="onChangeFiles"
@@ -50,7 +54,23 @@ export default Vue.extend({
 			type: Boolean,
 			required: false,
 			default: true
-		}
+		},
+
+		initialText: {
+			type: String,
+			required: false
+		},
+
+		initialNote: {
+			type: Object,
+			required: false
+		},
+
+		instant: {
+			type: Boolean,
+			required: false,
+			default: false
+		},
 	},
 
 	data() {
diff --git a/src/client/app/init.ts b/src/client/app/init.ts
index da7baff4fe..6fd11b9b75 100644
--- a/src/client/app/init.ts
+++ b/src/client/app/init.ts
@@ -125,7 +125,8 @@ import {
 	faMapMarker,
 	faRobot,
 	faHourglassHalf,
-	faGavel
+	faGavel,
+	faUndoAlt,
 } from '@fortawesome/free-solid-svg-icons';
 
 import {
@@ -258,6 +259,7 @@ library.add(
 	faRobot,
 	faHourglassHalf,
 	faGavel,
+	faUndoAlt,
 
 	farBell,
 	farEnvelope,
diff --git a/src/client/app/mobile/script.ts b/src/client/app/mobile/script.ts
index 082b3e895f..1e0441987f 100644
--- a/src/client/app/mobile/script.ts
+++ b/src/client/app/mobile/script.ts
@@ -55,7 +55,10 @@ init((launch, os) => {
 				const vm = this.$root.new(PostFormDialog, {
 					reply: o.reply,
 					mention: o.mention,
-					renote: o.renote
+					renote: o.renote,
+					initialText: o.initialText,
+					instant: o.instant,
+					initialNote: o.initialNote,
 				});
 				vm.$once('cancel', recover);
 				vm.$once('posted', recover);
diff --git a/src/client/app/mobile/views/components/post-form-dialog.vue b/src/client/app/mobile/views/components/post-form-dialog.vue
index a6801be0ef..716ad8fd07 100644
--- a/src/client/app/mobile/views/components/post-form-dialog.vue
+++ b/src/client/app/mobile/views/components/post-form-dialog.vue
@@ -7,6 +7,7 @@
 			:renote="renote"
 			:mention="mention"
 			:initial-text="initialText"
+			:initial-note="initialNote"
 			:instant="instant"
 			@posted="onPosted"
 			@cancel="onCanceled"/>
@@ -41,6 +42,10 @@ export default Vue.extend({
 			type: String,
 			required: false
 		},
+		initialNote: {
+			type: Object,
+			required: false
+		},
 		instant: {
 			type: Boolean,
 			required: false,