diff --git a/packages/desktop-client/e2e/rules.test.js b/packages/desktop-client/e2e/rules.test.js
index 20cc4f7d172b5bee98dc10b0050d30cc56f2728c..71c16d0cde1078d7626b4ce0cb30f0600028876a 100644
--- a/packages/desktop-client/e2e/rules.test.js
+++ b/packages/desktop-client/e2e/rules.test.js
@@ -120,7 +120,7 @@ test.describe('Rules', () => {
     });
 
     const transaction = accountPage.getNthTransaction(0);
-    await expect(transaction.payee).toHaveText('Ikea');
+    await expect(transaction.payee).toHaveText('Split');
     await expect(transaction.notes).toHaveText('food / entertainment');
     await expect(transaction.category).toHaveText('Split');
     await expect(transaction.debit).toHaveText('100.00');
diff --git a/packages/desktop-client/e2e/rules.test.js-snapshots/Rules-creates-a-split-transaction-rule-and-makes-sure-it-is-applied-when-creating-a-transaction-1-chromium-linux.png b/packages/desktop-client/e2e/rules.test.js-snapshots/Rules-creates-a-split-transaction-rule-and-makes-sure-it-is-applied-when-creating-a-transaction-1-chromium-linux.png
index 8ae36b41d02ca7d915f036280bd1a468ced670a1..f677aafa811024cf31eb71f45e8383dbe02e11ae 100644
Binary files a/packages/desktop-client/e2e/rules.test.js-snapshots/Rules-creates-a-split-transaction-rule-and-makes-sure-it-is-applied-when-creating-a-transaction-1-chromium-linux.png and b/packages/desktop-client/e2e/rules.test.js-snapshots/Rules-creates-a-split-transaction-rule-and-makes-sure-it-is-applied-when-creating-a-transaction-1-chromium-linux.png differ
diff --git a/packages/desktop-client/e2e/rules.test.js-snapshots/Rules-creates-a-split-transaction-rule-and-makes-sure-it-is-applied-when-creating-a-transaction-2-chromium-linux.png b/packages/desktop-client/e2e/rules.test.js-snapshots/Rules-creates-a-split-transaction-rule-and-makes-sure-it-is-applied-when-creating-a-transaction-2-chromium-linux.png
index ff186283451bd3bc6f691373403e942f48acccb3..c3620db1d281278e0f1b3c1b7e5399addf89b30d 100644
Binary files a/packages/desktop-client/e2e/rules.test.js-snapshots/Rules-creates-a-split-transaction-rule-and-makes-sure-it-is-applied-when-creating-a-transaction-2-chromium-linux.png and b/packages/desktop-client/e2e/rules.test.js-snapshots/Rules-creates-a-split-transaction-rule-and-makes-sure-it-is-applied-when-creating-a-transaction-2-chromium-linux.png differ
diff --git a/packages/desktop-client/e2e/rules.test.js-snapshots/Rules-creates-a-split-transaction-rule-and-makes-sure-it-is-applied-when-creating-a-transaction-3-chromium-linux.png b/packages/desktop-client/e2e/rules.test.js-snapshots/Rules-creates-a-split-transaction-rule-and-makes-sure-it-is-applied-when-creating-a-transaction-3-chromium-linux.png
index ea44917d0d870e3d5532daf34847ce2d5f27c951..7490e7d3318415efa6680634f50a629830804b4c 100644
Binary files a/packages/desktop-client/e2e/rules.test.js-snapshots/Rules-creates-a-split-transaction-rule-and-makes-sure-it-is-applied-when-creating-a-transaction-3-chromium-linux.png and b/packages/desktop-client/e2e/rules.test.js-snapshots/Rules-creates-a-split-transaction-rule-and-makes-sure-it-is-applied-when-creating-a-transaction-3-chromium-linux.png differ
diff --git a/packages/desktop-client/e2e/transactions.test.js b/packages/desktop-client/e2e/transactions.test.js
index f0ea08d796feba991c5dad6b0298cbbae59efc1d..91bdd02c485d73a7f866adc05f99a3cbb5961c47 100644
--- a/packages/desktop-client/e2e/transactions.test.js
+++ b/packages/desktop-client/e2e/transactions.test.js
@@ -120,7 +120,7 @@ test.describe('Transactions', () => {
     ]);
 
     const firstTransaction = accountPage.getNthTransaction(0);
-    await expect(firstTransaction.payee).toHaveText('Krogger');
+    await expect(firstTransaction.payee).toHaveText('Split');
     await expect(firstTransaction.notes).toHaveText('Notes');
     await expect(firstTransaction.category).toHaveText('Split');
     await expect(firstTransaction.debit).toHaveText('333.33');
diff --git a/packages/desktop-client/e2e/transactions.test.js-snapshots/Transactions-creates-a-split-test-transaction-1-chromium-linux.png b/packages/desktop-client/e2e/transactions.test.js-snapshots/Transactions-creates-a-split-test-transaction-1-chromium-linux.png
index 9e5f39e6e79a39bedd9f2f0cce58b2f46b2ca033..987db8a0c82dcbca515b9fd419fb4acb1527efc4 100644
Binary files a/packages/desktop-client/e2e/transactions.test.js-snapshots/Transactions-creates-a-split-test-transaction-1-chromium-linux.png and b/packages/desktop-client/e2e/transactions.test.js-snapshots/Transactions-creates-a-split-test-transaction-1-chromium-linux.png differ
diff --git a/packages/desktop-client/e2e/transactions.test.js-snapshots/Transactions-creates-a-split-test-transaction-2-chromium-linux.png b/packages/desktop-client/e2e/transactions.test.js-snapshots/Transactions-creates-a-split-test-transaction-2-chromium-linux.png
index 5cb575b8e0daafd6e516ab278da16ca7cc88b0d0..123571a606f7d16b1a53e93199d62e5daefd168a 100644
Binary files a/packages/desktop-client/e2e/transactions.test.js-snapshots/Transactions-creates-a-split-test-transaction-2-chromium-linux.png and b/packages/desktop-client/e2e/transactions.test.js-snapshots/Transactions-creates-a-split-test-transaction-2-chromium-linux.png differ
diff --git a/packages/desktop-client/e2e/transactions.test.js-snapshots/Transactions-creates-a-split-test-transaction-3-chromium-linux.png b/packages/desktop-client/e2e/transactions.test.js-snapshots/Transactions-creates-a-split-test-transaction-3-chromium-linux.png
index 44649349d2e4721da7df30f89f95571a7f30491d..ae65b4cb2386051c967c5bc50c4d4892200f7d94 100644
Binary files a/packages/desktop-client/e2e/transactions.test.js-snapshots/Transactions-creates-a-split-test-transaction-3-chromium-linux.png and b/packages/desktop-client/e2e/transactions.test.js-snapshots/Transactions-creates-a-split-test-transaction-3-chromium-linux.png differ
diff --git a/packages/desktop-client/src/components/Modals.tsx b/packages/desktop-client/src/components/Modals.tsx
index cb814ec23d2f44f4ad7ab23bd00a5012811d6cea..81f48f391e5d39c72f4f737824ad9cc69d9fc7ad 100644
--- a/packages/desktop-client/src/components/Modals.tsx
+++ b/packages/desktop-client/src/components/Modals.tsx
@@ -401,7 +401,6 @@ export function Modals() {
               actions={actions}
               transactionIds={options?.transactionIds}
               getTransaction={options?.getTransaction}
-              pushModal={options?.pushModal}
             />
           );
 
diff --git a/packages/desktop-client/src/components/accounts/Account.jsx b/packages/desktop-client/src/components/accounts/Account.jsx
index beac95b915d34f9b0d833841833580de23bbd7d4..5ae43fe4270f8e0a7d3feb3f4470877dae399f0b 100644
--- a/packages/desktop-client/src/components/accounts/Account.jsx
+++ b/packages/desktop-client/src/components/accounts/Account.jsx
@@ -1,8 +1,9 @@
 import React, { PureComponent, createRef, useMemo } from 'react';
 import { useSelector } from 'react-redux';
-import { Navigate, useParams, useLocation, useMatch } from 'react-router-dom';
+import { Navigate, useParams, useLocation } from 'react-router-dom';
 
 import { debounce } from 'debounce';
+import { v4 as uuidv4 } from 'uuid';
 
 import { validForTransfer } from 'loot-core/client/transfer';
 import { useFilters } from 'loot-core/src/client/data-hooks/filters';
@@ -20,6 +21,8 @@ import {
   realizeTempTransactions,
   ungroupTransaction,
   ungroupTransactions,
+  makeChild,
+  makeAsNonChildTransactions,
 } from 'loot-core/src/shared/transactions';
 import { applyChanges, groupById } from 'loot-core/src/shared/util';
 
@@ -1049,6 +1052,114 @@ class AccountInternal extends PureComponent {
     );
   };
 
+  onMakeAsSplitTransaction = async ids => {
+    this.setState({ workingHard: true });
+
+    const { data: transactions } = await runQuery(
+      q('transactions')
+        .filter({ id: { $oneof: ids } })
+        .select('*')
+        .options({ splits: 'none' }),
+    );
+
+    if (!transactions || transactions.length === 0) {
+      return;
+    }
+
+    const [firstTransaction] = transactions;
+    const parentTransaction = {
+      id: uuidv4(),
+      is_parent: true,
+      cleared: transactions.every(t => !!t.cleared),
+      date: firstTransaction.date,
+      account: firstTransaction.account,
+      amount: transactions
+        .map(t => t.amount)
+        .reduce((total, amount) => total + amount, 0),
+    };
+    const childTransactions = transactions.map(t =>
+      makeChild(parentTransaction, t),
+    );
+
+    await send('transactions-batch-update', {
+      added: [parentTransaction],
+      updated: childTransactions,
+    });
+
+    this.refetchTransactions();
+  };
+
+  onMakeAsNonSplitTransactions = async ids => {
+    this.setState({ workingHard: true });
+
+    const { data: groupedTransactions } = await runQuery(
+      q('transactions')
+        .filter({ id: { $oneof: ids } })
+        .select('*')
+        .options({ splits: 'grouped' }),
+    );
+
+    let changes = {
+      updated: [],
+      deleted: [],
+    };
+
+    const groupedTransactionsToUpdate = groupedTransactions.filter(
+      t => t.is_parent,
+    );
+
+    for (const groupedTransaction of groupedTransactionsToUpdate) {
+      const transactions = ungroupTransaction(groupedTransaction);
+      const [parentTransaction, ...childTransactions] = transactions;
+
+      if (ids.includes(parentTransaction.id)) {
+        // Unsplit all child transactions.
+        const diff = makeAsNonChildTransactions(
+          childTransactions,
+          transactions,
+        );
+
+        changes = {
+          updated: [...changes.updated, ...diff.updated],
+          deleted: [...changes.deleted, ...diff.deleted],
+        };
+
+        // Already processed the child transactions above, no need to process them below.
+        continue;
+      }
+
+      // Unsplit selected child transactions.
+
+      const selectedChildTransactions = childTransactions.filter(t =>
+        ids.includes(t.id),
+      );
+
+      if (selectedChildTransactions.length === 0) {
+        continue;
+      }
+
+      const diff = makeAsNonChildTransactions(
+        selectedChildTransactions,
+        transactions,
+      );
+
+      changes = {
+        updated: [...changes.updated, ...diff.updated],
+        deleted: [...changes.deleted, ...diff.deleted],
+      };
+    }
+
+    await send('transactions-batch-update', changes);
+
+    this.refetchTransactions();
+
+    const transactionsToSelect = changes.updated.map(t => t.id);
+    this.dispatchSelected({
+      type: 'select-all',
+      ids: transactionsToSelect,
+    });
+  };
+
   checkForReconciledTransactions = async (ids, confirmReason, onConfirm) => {
     const { data } = await runQuery(
       q('transactions')
@@ -1610,6 +1721,8 @@ class AccountInternal extends PureComponent {
                 onApplyFilter={this.onApplyFilter}
                 onScheduleAction={this.onScheduleAction}
                 onSetTransfer={this.onSetTransfer}
+                onMakeAsSplitTransaction={this.onMakeAsSplitTransaction}
+                onMakeAsNonSplitTransactions={this.onMakeAsNonSplitTransactions}
               />
 
               <View style={{ flex: 1 }}>
@@ -1686,13 +1799,11 @@ class AccountInternal extends PureComponent {
 
 function AccountHack(props) {
   const { dispatch: splitsExpandedDispatch } = useSplitsExpanded();
-  const match = useMatch(props.location.pathname);
 
   return (
     <AccountInternal
-      {...props}
-      match={match}
       splitsExpandedDispatch={splitsExpandedDispatch}
+      {...props}
     />
   );
 }
diff --git a/packages/desktop-client/src/components/accounts/Header.jsx b/packages/desktop-client/src/components/accounts/Header.jsx
index fd29b4cc42781c7391e34d7d4e40a2156f039d48..4506034fcd4904bb3980cea21d7eed771302f5e1 100644
--- a/packages/desktop-client/src/components/accounts/Header.jsx
+++ b/packages/desktop-client/src/components/accounts/Header.jsx
@@ -26,7 +26,7 @@ import { View } from '../common/View';
 import { FilterButton } from '../filters/FiltersMenu';
 import { FiltersStack } from '../filters/FiltersStack';
 import { NotesButton } from '../NotesButton';
-import { SelectedTransactionsButton } from '../transactions/SelectedTransactions';
+import { SelectedTransactionsButton } from '../transactions/SelectedTransactionsButton';
 
 import { Balances } from './Balance';
 import { ReconcilingMessage, ReconcileMenu } from './Reconcile';
@@ -84,6 +84,8 @@ export function AccountHeader({
   onDeleteFilter,
   onScheduleAction,
   onSetTransfer,
+  onMakeAsSplitTransaction,
+  onMakeAsNonSplitTransactions,
 }) {
   const [menuOpen, setMenuOpen] = useState(false);
   const searchInput = useRef(null);
@@ -319,6 +321,8 @@ export function AccountHeader({
               onScheduleAction={onScheduleAction}
               pushModal={pushModal}
               showMakeTransfer={showMakeTransfer}
+              onMakeAsSplitTransaction={onMakeAsSplitTransaction}
+              onMakeAsNonSplitTransactions={onMakeAsNonSplitTransactions}
             />
           )}
           <Button
diff --git a/packages/desktop-client/src/components/mobile/transactions/TransactionEdit.jsx b/packages/desktop-client/src/components/mobile/transactions/TransactionEdit.jsx
index 62593477e15141ac8874fb9e0b26b1d7ec39cbf4..8018f1ef7bd9124dc5cf8dd8e867ef1cef5ba90a 100644
--- a/packages/desktop-client/src/components/mobile/transactions/TransactionEdit.jsx
+++ b/packages/desktop-client/src/components/mobile/transactions/TransactionEdit.jsx
@@ -362,7 +362,7 @@ const ChildTransactionEdit = forwardRef(
         <View>
           <FieldLabel title="Category" />
           <TapField
-            style={{
+            textStyle={{
               ...((isOffBudget || isBudgetTransfer(transaction)) && {
                 fontStyle: 'italic',
                 color: theme.pageTextSubdued,
@@ -490,6 +490,9 @@ const TransactionEditInner = memo(function TransactionEditInner({
   };
 
   const getPrettyPayee = trans => {
+    if (trans && trans.is_parent) {
+      return 'Split';
+    }
     const transPayee = trans && getPayee(trans);
     const transTransferAcct = trans && getTransferAcct(trans);
     return getDescriptionPretty(trans, transPayee, transTransferAcct);
@@ -763,11 +766,17 @@ const TransactionEditInner = memo(function TransactionEditInner({
         <View>
           <FieldLabel title="Payee" />
           <TapField
+            textStyle={{
+              ...(transaction.is_parent && {
+                fontStyle: 'italic',
+                fontWeight: 300,
+              }),
+            }}
+            value={getPrettyPayee(transaction)}
             disabled={
               editingField &&
               editingField !== getFieldName(transaction.id, 'payee')
             }
-            value={getPrettyPayee(transaction)}
             onClick={() => onEditField(transaction.id, 'payee')}
             data-testid="payee-field"
           />
diff --git a/packages/desktop-client/src/components/modals/PayeeAutocompleteModal.tsx b/packages/desktop-client/src/components/modals/PayeeAutocompleteModal.tsx
index 5c860cacc38215afb0114c4b4e017c3daf0b19cf..952361cacc735f1186bde7537e817853d1f6b3c3 100644
--- a/packages/desktop-client/src/components/modals/PayeeAutocompleteModal.tsx
+++ b/packages/desktop-client/src/components/modals/PayeeAutocompleteModal.tsx
@@ -1,6 +1,7 @@
 import React, { type ComponentPropsWithoutRef } from 'react';
 
 import { useAccounts } from '../../hooks/useAccounts';
+import { useNavigate } from '../../hooks/useNavigate';
 import { usePayees } from '../../hooks/usePayees';
 import { useResponsive } from '../../ResponsiveProvider';
 import { theme } from '../../style';
@@ -21,6 +22,7 @@ export function PayeeAutocompleteModal({
 }: PayeeAutocompleteModalProps) {
   const payees = usePayees() || [];
   const accounts = useAccounts() || [];
+  const navigate = useNavigate();
 
   const _onClose = () => {
     modalProps.onClose();
@@ -32,6 +34,8 @@ export function PayeeAutocompleteModal({
     containerProps: { style: { height: isNarrowWidth ? '90vh' : 275 } },
   };
 
+  const onManagePayees = () => navigate('/payees');
+
   return (
     <Modal
       title={
@@ -56,20 +60,19 @@ export function PayeeAutocompleteModal({
         />
       )}
     >
-      {() => (
-        <PayeeAutocomplete
-          payees={payees}
-          accounts={accounts}
-          focused={true}
-          embedded={true}
-          closeOnBlur={false}
-          onClose={_onClose}
-          showManagePayees={false}
-          showMakeTransfer={!isNarrowWidth}
-          {...defaultAutocompleteProps}
-          {...autocompleteProps}
-        />
-      )}
+      <PayeeAutocomplete
+        payees={payees}
+        accounts={accounts}
+        focused={true}
+        embedded={true}
+        closeOnBlur={false}
+        onClose={_onClose}
+        onManagePayees={onManagePayees}
+        showManagePayees={!isNarrowWidth}
+        showMakeTransfer={!isNarrowWidth}
+        {...defaultAutocompleteProps}
+        {...autocompleteProps}
+      />
     </Modal>
   );
 }
diff --git a/packages/desktop-client/src/components/schedules/ScheduleLink.tsx b/packages/desktop-client/src/components/schedules/ScheduleLink.tsx
index e35d0791e41e9ec1b30e599bc8a2d235466ede0e..5743087d3fd7409b627eee4f2cf0c4602b577fb2 100644
--- a/packages/desktop-client/src/components/schedules/ScheduleLink.tsx
+++ b/packages/desktop-client/src/components/schedules/ScheduleLink.tsx
@@ -1,6 +1,8 @@
 // @ts-strict-ignore
 import React, { useCallback, useRef, useState } from 'react';
+import { useDispatch } from 'react-redux';
 
+import { pushModal } from 'loot-core/client/actions';
 import { useSchedules } from 'loot-core/src/client/data-hooks/schedules';
 import { send } from 'loot-core/src/platform/client/fetch';
 import { type Query } from 'loot-core/src/shared/query';
@@ -17,24 +19,18 @@ import { type CommonModalProps } from '../Modals';
 
 import { ROW_HEIGHT, SchedulesTable } from './SchedulesTable';
 
-type ModalParams = {
-  id: string;
-  transaction: TransactionEntity;
-};
-
 export function ScheduleLink({
   modalProps,
   actions,
   transactionIds: ids,
   getTransaction,
-  pushModal,
 }: {
   actions: BoundActions;
   modalProps?: CommonModalProps;
   transactionIds: string[];
   getTransaction: (transactionId: string) => TransactionEntity;
-  pushModal: (name: string, params: ModalParams) => void;
 }) {
+  const dispatch = useDispatch();
   const [filter, setFilter] = useState('');
 
   const scheduleData = useSchedules({
@@ -59,10 +55,12 @@ export function ScheduleLink({
 
   async function onCreate() {
     actions.popModal();
-    pushModal('schedule-edit', {
-      id: null,
-      transaction: getTransaction(ids[0]),
-    });
+    dispatch(
+      pushModal('schedule-edit', {
+        id: null,
+        transaction: getTransaction(ids[0]),
+      }),
+    );
   }
 
   return (
diff --git a/packages/desktop-client/src/components/transactions/SelectedTransactions.jsx b/packages/desktop-client/src/components/transactions/SelectedTransactionsButton.jsx
similarity index 51%
rename from packages/desktop-client/src/components/transactions/SelectedTransactions.jsx
rename to packages/desktop-client/src/components/transactions/SelectedTransactionsButton.jsx
index d08e73c706c517084fd3a7a32b5795d4844e6804..5d982ebbe9e8f6aa5825c2e1e00a469510dac2d9 100644
--- a/packages/desktop-client/src/components/transactions/SelectedTransactions.jsx
+++ b/packages/desktop-client/src/components/transactions/SelectedTransactionsButton.jsx
@@ -1,6 +1,8 @@
 import React, { useMemo } from 'react';
 import { useHotkeys } from 'react-hotkeys-hook';
+import { useDispatch } from 'react-redux';
 
+import { pushModal } from 'loot-core/client/actions';
 import { isPreviewId } from 'loot-core/shared/transactions';
 import { validForTransfer } from 'loot-core/src/client/transfer';
 
@@ -18,43 +20,45 @@ export function SelectedTransactionsButton({
   onCreateRule,
   onSetTransfer,
   onScheduleAction,
-  pushModal,
   showMakeTransfer,
+  onMakeAsSplitTransaction,
+  onMakeAsNonSplitTransactions,
 }) {
+  const dispatch = useDispatch();
   const selectedItems = useSelectedItems();
+  const selectedIds = useMemo(() => [...selectedItems], [selectedItems]);
 
   const types = useMemo(() => {
-    const items = [...selectedItems];
+    const items = selectedIds;
     return {
       preview: !!items.find(id => isPreviewId(id)),
       trans: !!items.find(id => !isPreviewId(id)),
     };
-  }, [selectedItems]);
+  }, [selectedIds]);
 
   const ambiguousDuplication = useMemo(() => {
-    const transactions = [...selectedItems].map(id => getTransaction(id));
+    const transactions = selectedIds.map(id => getTransaction(id));
 
     return transactions.some(t => t && t.is_child);
-  }, [selectedItems]);
+  }, [selectedIds, getTransaction]);
 
   const linked = useMemo(() => {
     return (
       !types.preview &&
-      [...selectedItems].every(id => {
+      selectedIds.every(id => {
         const t = getTransaction(id);
         return t && t.schedule;
       })
     );
-  }, [types.preview, selectedItems, getTransaction]);
+  }, [types.preview, selectedIds, getTransaction]);
 
   const canBeTransfer = useMemo(() => {
     // only two selected
-    if (selectedItems.size !== 2) {
+    if (selectedIds.length !== 2) {
       return false;
     }
-    const transactions = [...selectedItems];
-    const fromTrans = getTransaction(transactions[0]);
-    const toTrans = getTransaction(transactions[1]);
+    const fromTrans = getTransaction(selectedIds[0]);
+    const toTrans = getTransaction(selectedIds[1]);
 
     // previously selected transactions aren't always present in current transaction list
     if (!fromTrans || !toTrans) {
@@ -62,39 +66,83 @@ export function SelectedTransactionsButton({
     }
 
     return validForTransfer(fromTrans, toTrans);
-  }, [selectedItems, getTransaction]);
+  }, [selectedIds, getTransaction]);
+
+  const canMakeAsSplitTransaction = useMemo(() => {
+    if (selectedIds.length <= 1 || types.preview) {
+      return false;
+    }
+
+    const transactions = selectedIds.map(id => getTransaction(id));
+    const [firstTransaction] = transactions;
+
+    const areAllSameDateAndAccount = transactions.every(
+      t =>
+        t &&
+        t.date === firstTransaction.date &&
+        t.account === firstTransaction.account,
+    );
+    const areNoSplitTransactions = transactions.every(
+      t => t && !t.is_parent && !t.is_child,
+    );
+    const areNoReconciledTransactions = transactions.every(
+      t => t && !t.reconciled,
+    );
+
+    return (
+      areAllSameDateAndAccount &&
+      areNoSplitTransactions &&
+      areNoReconciledTransactions
+    );
+  }, [selectedIds, types, getTransaction]);
+
+  const canUnsplitTransactions = useMemo(() => {
+    if (selectedIds.length === 0 || types.preview) {
+      return false;
+    }
+
+    const transactions = selectedIds.map(id => getTransaction(id));
+
+    const areNoReconciledTransactions = transactions.every(
+      t => t && !t.reconciled,
+    );
+    const areAllSplitTransactions = transactions.every(
+      t => t && (t.is_parent || t.is_child),
+    );
+    return areNoReconciledTransactions && areAllSplitTransactions;
+  }, [selectedIds, types, getTransaction]);
 
   const hotKeyOptions = {
     enabled: types.trans,
     scopes: ['app'],
   };
-  useHotkeys('f', () => onShow([...selectedItems]), hotKeyOptions, [
+  useHotkeys('f', () => onShow(selectedIds), hotKeyOptions, [
     onShow,
-    selectedItems,
+    selectedIds,
   ]);
-  useHotkeys('d', () => onDelete([...selectedItems]), hotKeyOptions, [
+  useHotkeys('d', () => onDelete(selectedIds), hotKeyOptions, [
     onDelete,
-    selectedItems,
+    selectedIds,
   ]);
-  useHotkeys('a', () => onEdit('account', [...selectedItems]), hotKeyOptions, [
+  useHotkeys('a', () => onEdit('account', selectedIds), hotKeyOptions, [
     onEdit,
-    selectedItems,
+    selectedIds,
   ]);
-  useHotkeys('p', () => onEdit('payee', [...selectedItems]), hotKeyOptions, [
+  useHotkeys('p', () => onEdit('payee', selectedIds), hotKeyOptions, [
     onEdit,
-    selectedItems,
+    selectedIds,
   ]);
-  useHotkeys('n', () => onEdit('notes', [...selectedItems]), hotKeyOptions, [
+  useHotkeys('n', () => onEdit('notes', selectedIds), hotKeyOptions, [
     onEdit,
-    selectedItems,
+    selectedIds,
   ]);
-  useHotkeys('c', () => onEdit('category', [...selectedItems]), hotKeyOptions, [
+  useHotkeys('c', () => onEdit('category', selectedIds), hotKeyOptions, [
     onEdit,
-    selectedItems,
+    selectedIds,
   ]);
-  useHotkeys('l', () => onEdit('cleared', [...selectedItems]), hotKeyOptions, [
+  useHotkeys('l', () => onEdit('cleared', selectedIds), hotKeyOptions, [
     onEdit,
-    selectedItems,
+    selectedIds,
   ]);
 
   return (
@@ -120,7 +168,7 @@ export function SelectedTransactionsButton({
                     {
                       name: 'view-schedule',
                       text: 'View schedule',
-                      disabled: selectedItems.size > 1,
+                      disabled: selectedIds.length > 1,
                     },
                     { name: 'unlink-schedule', text: 'Unlink schedule' },
                   ]
@@ -143,6 +191,24 @@ export function SelectedTransactionsButton({
                     },
                   ]
                 : []),
+              ...(canMakeAsSplitTransaction
+                ? [
+                    {
+                      name: 'make-as-split-transaction',
+                      text: 'Make as split transaction',
+                    },
+                  ]
+                : []),
+              ...(canUnsplitTransactions
+                ? [
+                    {
+                      name: 'unsplit-transactions',
+                      text:
+                        'Unsplit transaction' +
+                        (selectedIds.length > 1 ? 's' : ''),
+                    },
+                  ]
+                : []),
               Menu.line,
               { type: Menu.label, name: 'Edit field' },
               { name: 'date', text: 'Date' },
@@ -157,20 +223,26 @@ export function SelectedTransactionsButton({
       onSelect={name => {
         switch (name) {
           case 'show':
-            onShow([...selectedItems]);
+            onShow(selectedIds);
             break;
           case 'duplicate':
-            onDuplicate([...selectedItems]);
+            onDuplicate(selectedIds);
             break;
           case 'delete':
-            onDelete([...selectedItems]);
+            onDelete(selectedIds);
+            break;
+          case 'make-as-split-transaction':
+            onMakeAsSplitTransaction(selectedIds);
+            break;
+          case 'unsplit-transactions':
+            onMakeAsNonSplitTransactions(selectedIds);
             break;
           case 'post-transaction':
           case 'skip':
-            onScheduleAction(name, selectedItems);
+            onScheduleAction(name, selectedIds);
             break;
           case 'view-schedule':
-            const firstId = [...selectedItems][0];
+            const firstId = selectedIds[0];
             let scheduleId;
             if (isPreviewId(firstId)) {
               const parts = firstId.split('/');
@@ -181,27 +253,28 @@ export function SelectedTransactionsButton({
             }
 
             if (scheduleId) {
-              pushModal('schedule-edit', { id: scheduleId });
+              dispatch(pushModal('schedule-edit', { id: scheduleId }));
             }
             break;
           case 'link-schedule':
-            pushModal('schedule-link', {
-              transactionIds: [...selectedItems],
-              getTransaction,
-              pushModal,
-            });
+            dispatch(
+              pushModal('schedule-link', {
+                transactionIds: selectedIds,
+                getTransaction,
+              }),
+            );
             break;
           case 'unlink-schedule':
-            onUnlink([...selectedItems]);
+            onUnlink(selectedIds);
             break;
           case 'create-rule':
-            onCreateRule([...selectedItems]);
+            onCreateRule(selectedIds);
             break;
           case 'set-transfer':
-            onSetTransfer([...selectedItems]);
+            onSetTransfer(selectedIds);
             break;
           default:
-            onEdit(name, [...selectedItems]);
+            onEdit(name, selectedIds);
         }
       }}
     />
diff --git a/packages/desktop-client/src/components/transactions/TransactionList.jsx b/packages/desktop-client/src/components/transactions/TransactionList.jsx
index 20cf3a97717421818cfb40eea3c4d2621cb7814f..95c6e66fb5f262cb42b3c391ab24f6be6c47a189 100644
--- a/packages/desktop-client/src/components/transactions/TransactionList.jsx
+++ b/packages/desktop-client/src/components/transactions/TransactionList.jsx
@@ -90,9 +90,9 @@ export function TransactionList({
   onCreatePayee,
   onApplyFilter,
 }) {
+  const dispatch = useDispatch();
   const transactionsLatest = useRef();
   const navigate = useNavigate();
-  const dispatch = useDispatch();
 
   useLayoutEffect(() => {
     transactionsLatest.current = transactions;
@@ -158,7 +158,7 @@ export function TransactionList({
   }, []);
 
   const onManagePayees = useCallback(id => {
-    navigate('/payees', { selectedPayee: id });
+    navigate('/payees', { state: { selectedPayee: id } });
   });
 
   const onNavigateToTransferAccount = useCallback(accountId => {
diff --git a/packages/desktop-client/src/components/transactions/TransactionsTable.jsx b/packages/desktop-client/src/components/transactions/TransactionsTable.jsx
index adcf236f115ca55bf36eec871b6acb83c51a42c3..3633f8fa9b0e18ecb1da942232a7c3877859ef01 100644
--- a/packages/desktop-client/src/components/transactions/TransactionsTable.jsx
+++ b/packages/desktop-client/src/components/transactions/TransactionsTable.jsx
@@ -49,7 +49,7 @@ import { useMergedRefs } from '../../hooks/useMergedRefs';
 import { usePrevious } from '../../hooks/usePrevious';
 import { useSelectedDispatch, useSelectedItems } from '../../hooks/useSelected';
 import { useSplitsExpanded } from '../../hooks/useSplitsExpanded';
-import { SvgLeftArrow2, SvgRightArrow2 } from '../../icons/v0';
+import { SvgLeftArrow2, SvgRightArrow2, SvgSplit } from '../../icons/v0';
 import { SvgArrowDown, SvgArrowUp, SvgCheveronDown } from '../../icons/v1';
 import {
   SvgArrowsSynchronize,
@@ -457,7 +457,6 @@ function PayeeCell({
   id,
   payee,
   focused,
-  inherited,
   payees,
   accounts,
   valueStyle,
@@ -473,16 +472,75 @@ function PayeeCell({
 }) {
   const isCreatingPayee = useRef(false);
 
-  return (
+  const dispatch = useDispatch();
+
+  return transaction.is_parent ? (
+    <Cell
+      name="payee"
+      width="flex"
+      focused={focused}
+      style={{ padding: 0 }}
+      plain
+    >
+      <CellButton
+        bare
+        style={{
+          alignSelf: 'flex-start',
+          borderRadius: 4,
+          border: '1px solid transparent', // so it doesn't shift on hover
+          ':hover': {
+            border: '1px solid ' + theme.buttonNormalBorder,
+          },
+        }}
+        disabled={isPreview}
+        onSelect={() =>
+          dispatch(
+            pushModal('payee-autocomplete', {
+              onSelect: payeeId => {
+                onUpdate('payee', payeeId);
+              },
+            }),
+          )
+        }
+      >
+        <View
+          style={{
+            flexDirection: 'row',
+            alignItems: 'center',
+            alignSelf: 'stretch',
+            borderRadius: 4,
+            flex: 1,
+            padding: 4,
+            color: theme.pageTextSubdued,
+          }}
+        >
+          <SvgSplit
+            style={{
+              color: 'inherit',
+              width: 14,
+              height: 14,
+              marginRight: 2,
+            }}
+          />
+          <Text
+            style={{
+              fontStyle: 'italic',
+              fontWeight: 300,
+              userSelect: 'none',
+            }}
+          >
+            Split
+          </Text>
+        </View>
+      </CellButton>
+    </Cell>
+  ) : (
     <CustomCell
       width="flex"
       name="payee"
       textAlign="flex"
       value={payee?.id}
-      valueStyle={{
-        ...valueStyle,
-        ...(inherited && { color: theme.tableTextInactive }),
-      }}
+      valueStyle={valueStyle}
       exposed={focused}
       onExpose={name => !isPreview && onEdit(id, name)}
       onUpdate={async value => {
@@ -614,41 +672,38 @@ function PayeeIcons({
   );
 }
 
-const Transaction = memo(function Transaction(props) {
-  const {
-    transaction: originalTransaction,
-    subtransactions,
-    editing,
-    showAccount,
-    showBalance,
-    showCleared,
-    showZeroInDeposit,
-    style,
-    selected,
-    highlighted,
-    added,
-    matched,
-    expanded,
-    inheritedFields,
-    focusedField,
-    categoryGroups,
-    payees,
-    accounts,
-    balance,
-    dateFormat = 'MM/dd/yyyy',
-    hideFraction,
-    onSave,
-    onEdit,
-    onDelete,
-    onSplit,
-    onManagePayees,
-    onCreatePayee,
-    onToggleSplit,
-    onNavigateToTransferAccount,
-    onNavigateToSchedule,
-    onNotesTagClick,
-  } = props;
-
+const Transaction = memo(function Transaction({
+  transaction: originalTransaction,
+  subtransactions,
+  editing,
+  showAccount,
+  showBalance,
+  showCleared,
+  showZeroInDeposit,
+  style,
+  selected,
+  highlighted,
+  added,
+  matched,
+  expanded,
+  focusedField,
+  categoryGroups,
+  payees,
+  accounts,
+  balance,
+  dateFormat = 'MM/dd/yyyy',
+  hideFraction,
+  onSave,
+  onEdit,
+  onDelete,
+  onSplit,
+  onManagePayees,
+  onCreatePayee,
+  onToggleSplit,
+  onNavigateToTransferAccount,
+  onNavigateToSchedule,
+  onNotesTagClick,
+}) {
   const dispatch = useDispatch();
   const dispatchSelected = useSelectedDispatch();
 
@@ -989,7 +1044,6 @@ const Transaction = memo(function Transaction(props) {
           id={id}
           payee={payee}
           focused={focusedField === 'payee'}
-          inherited={inheritedFields && inheritedFields.has('payee')}
           /* Filter out the account we're currently in as it is not a valid transfer */
           accounts={accounts.filter(account => account.id !== accountId)}
           payees={payees.filter(payee => payee.transfer_acct !== accountId)}
@@ -1090,6 +1144,7 @@ const Transaction = memo(function Transaction(props) {
                 borderRadius: 4,
                 flex: 1,
                 padding: 4,
+                color: theme.pageTextSubdued,
               }}
             >
               {isParent && (
@@ -1103,7 +1158,13 @@ const Transaction = memo(function Transaction(props) {
                   }}
                 />
               )}
-              <Text style={{ fontStyle: 'italic', userSelect: 'none' }}>
+              <Text
+                style={{
+                  fontStyle: 'italic',
+                  fontWeight: 300,
+                  userSelect: 'none',
+                }}
+              >
                 Split
               </Text>
             </View>
@@ -1632,9 +1693,6 @@ function TransactionTableInner({
           accounts={accounts}
           categoryGroups={categoryGroups}
           payees={payees}
-          inheritedFields={
-            parent?.payee === trans.payee ? new Set(['payee']) : new Set()
-          }
           dateFormat={dateFormat}
           hideFraction={hideFraction}
           onEdit={tableNavigator.onEdit}
diff --git a/packages/loot-core/src/client/state-types/modals.d.ts b/packages/loot-core/src/client/state-types/modals.d.ts
index 941671c3266a8f317d1062669c904603b1c7906f..f45233af13203199e0c3686de7d4ef31d335a4a7 100644
--- a/packages/loot-core/src/client/state-types/modals.d.ts
+++ b/packages/loot-core/src/client/state-types/modals.d.ts
@@ -4,6 +4,7 @@ import type {
   CategoryEntity,
   CategoryGroupEntity,
   GoCardlessToken,
+  TransactionEntity,
 } from '../../types/models';
 import type { NewRuleEntity, RuleEntity } from '../../types/models/rule';
 import type { EmptyObject, StripNever } from '../../types/util';
@@ -121,7 +122,7 @@ type FinanceModals = {
     month: string;
   };
 
-  'schedule-edit': { id: string } | null;
+  'schedule-edit': { id: string; transaction?: TransactionEntity } | null;
 
   'schedule-link': { transactionIds: string[] } | null;
 
diff --git a/packages/loot-core/src/server/accounts/transactions.ts b/packages/loot-core/src/server/accounts/transactions.ts
index 5d6001eb5875077446b9b5c32a215c46cce71523..08fb702a7a1948be20faecf6a614f60dd6596257 100644
--- a/packages/loot-core/src/server/accounts/transactions.ts
+++ b/packages/loot-core/src/server/accounts/transactions.ts
@@ -1,6 +1,6 @@
 // @ts-strict-ignore
 import * as connection from '../../platform/server/connection';
-import { TransactionEntity } from '../../types/models';
+import { NewTransactionEntity, TransactionEntity } from '../../types/models';
 import * as db from '../db';
 import { incrFetch, whereIn } from '../db/util';
 import { batchMessages } from '../sync';
@@ -43,14 +43,9 @@ export async function batchUpdateTransactions({
   detectOrphanPayees = true,
   runTransfers = true,
 }: {
-  added?: Array<{ id: string; payee: unknown; category: unknown }>;
-  deleted?: Array<{ id: string; payee: unknown }>;
-  updated?: Array<{
-    id: string;
-    payee?: unknown;
-    account?: unknown;
-    category?: unknown;
-  }>;
+  added?: Array<Partial<NewTransactionEntity | TransactionEntity>>;
+  deleted?: Array<Partial<NewTransactionEntity | TransactionEntity>>;
+  updated?: Array<Partial<NewTransactionEntity | TransactionEntity>>;
   learnCategories?: boolean;
   detectOrphanPayees?: boolean;
   runTransfers?: boolean;
diff --git a/packages/loot-core/src/server/main.ts b/packages/loot-core/src/server/main.ts
index 70617167357c45de4028c7ca8868ebd5d69dce4c..3c1be8ef49ed591b0d31c3b10cf2c8a7ea0d43f7 100644
--- a/packages/loot-core/src/server/main.ts
+++ b/packages/loot-core/src/server/main.ts
@@ -112,8 +112,7 @@ handlers['transactions-batch-update'] = mutator(async function ({
       learnCategories,
     });
 
-    // Return all data updates to the frontend
-    return result.updated;
+    return result;
   });
 });
 
diff --git a/packages/loot-core/src/shared/transactions.ts b/packages/loot-core/src/shared/transactions.ts
index 96c8a7c3aa246ffa0fd1a8314ad7ae0f919671d9..773d59fac70c2f1d6c897f1d0d1fb25880bdfa12 100644
--- a/packages/loot-core/src/shared/transactions.ts
+++ b/packages/loot-core/src/shared/transactions.ts
@@ -66,6 +66,22 @@ export function makeChild<T extends GenericTransactionEntity>(
   } as unknown as T;
 }
 
+function makeNonChild<T extends GenericTransactionEntity>(
+  parent: T,
+  data: object,
+) {
+  return {
+    amount: 0,
+    ...data,
+    cleared: parent.cleared != null ? parent.cleared : null,
+    reconciled: parent.reconciled != null ? parent.reconciled : null,
+    sort_order: parent.sort_order || null,
+    starting_balance_flag: null,
+    is_child: false,
+    parent_id: null,
+  } as unknown as T;
+}
+
 export function recalculateSplit(trans: TransactionEntity) {
   // Calculate the new total of split transactions and make sure
   // that it equals the parent amount
@@ -314,3 +330,47 @@ export function realizeTempTransactions(transactions: TransactionEntity[]) {
     })),
   ];
 }
+
+export function makeAsNonChildTransactions(
+  childTransactionsToUpdate: TransactionEntity[],
+  transactions: TransactionEntity[],
+) {
+  const [parentTransaction, ...childTransactions] = transactions;
+  const newNonChildTransactions = childTransactionsToUpdate.map(t =>
+    makeNonChild(parentTransaction, t),
+  );
+
+  const remainingChildTransactions = childTransactions.filter(
+    t =>
+      !newNonChildTransactions.some(updatedTrans => updatedTrans.id === t.id),
+  );
+
+  const nonChildTransactionsToUpdate =
+    remainingChildTransactions.length === 1
+      ? [
+          ...newNonChildTransactions,
+          makeNonChild(parentTransaction, remainingChildTransactions[0]),
+        ]
+      : newNonChildTransactions;
+
+  const deleteParentTransaction = remainingChildTransactions.length <= 1;
+
+  const updatedParentTransaction = {
+    ...parentTransaction,
+    ...(!deleteParentTransaction
+      ? {
+          amount: remainingChildTransactions
+            .map(t => t.amount)
+            .reduce((total, amount) => total + amount, 0),
+        }
+      : {}),
+  };
+
+  return {
+    updated: [
+      ...(!deleteParentTransaction ? [updatedParentTransaction] : []),
+      ...nonChildTransactionsToUpdate,
+    ],
+    deleted: [...(deleteParentTransaction ? [updatedParentTransaction] : [])],
+  };
+}
diff --git a/packages/loot-core/src/types/server-handlers.d.ts b/packages/loot-core/src/types/server-handlers.d.ts
index 0cf51bc85bc1ae4fa05f9624cfedbac257dc7abd..50736f01325d8b5e4a9f2cb4d2002562f81fc34f 100644
--- a/packages/loot-core/src/types/server-handlers.d.ts
+++ b/packages/loot-core/src/types/server-handlers.d.ts
@@ -32,7 +32,7 @@ export interface ServerHandlers {
       Parameters<typeof batchUpdateTransactions>[0],
       'detectOrphanPayees'
     >,
-  ) => Promise<Awaited<ReturnType<typeof batchUpdateTransactions>>['updated']>;
+  ) => Promise<Awaited<ReturnType<typeof batchUpdateTransactions>>>;
 
   'transaction-add': (transaction) => Promise<EmptyObject>;
 
diff --git a/upcoming-release-notes/2805.md b/upcoming-release-notes/2805.md
new file mode 100644
index 0000000000000000000000000000000000000000..52655dc81d9da511455a21275553a58175c9fe25
--- /dev/null
+++ b/upcoming-release-notes/2805.md
@@ -0,0 +1,6 @@
+---
+category: Features
+authors: [joel-jeremy]
+---
+
+Make multiple transactions as a split transaction or separate a split transaction into multiple individual ones.