diff --git a/Content.Client/Items/Systems/MultiHandedItemSystem.cs b/Content.Client/Items/Systems/MultiHandedItemSystem.cs
new file mode 100644
index 0000000000..716a4ad1a4
--- /dev/null
+++ b/Content.Client/Items/Systems/MultiHandedItemSystem.cs
@@ -0,0 +1,15 @@
+using Content.Shared.Hands;
+using Content.Shared.Item;
+
+namespace Content.Client.Items.Systems;
+
+public sealed class MultiHandedItemSystem : SharedMultiHandedItemSystem
+{
+ protected override void OnEquipped(EntityUid uid, MultiHandedItemComponent component, GotEquippedHandEvent args)
+ {
+ }
+
+ protected override void OnUnequipped(EntityUid uid, MultiHandedItemComponent component, GotUnequippedHandEvent args)
+ {
+ }
+}
diff --git a/Content.Server/Item/MultiHandedItemSystem.cs b/Content.Server/Item/MultiHandedItemSystem.cs
new file mode 100644
index 0000000000..3dc213e1fc
--- /dev/null
+++ b/Content.Server/Item/MultiHandedItemSystem.cs
@@ -0,0 +1,23 @@
+using Content.Server.Hands.Systems;
+using Content.Shared.Hands;
+using Content.Shared.Item;
+
+namespace Content.Server.Item;
+
+public sealed class MultiHandedItemSystem : SharedMultiHandedItemSystem
+{
+ [Dependency] private readonly HandVirtualItemSystem _virtualItem = default!;
+
+ protected override void OnEquipped(EntityUid uid, MultiHandedItemComponent component, GotEquippedHandEvent args)
+ {
+ for (var i = 0; i < component.HandsNeeded - 1; i++)
+ {
+ _virtualItem.TrySpawnVirtualItemInHand(uid, args.User);
+ }
+ }
+
+ protected override void OnUnequipped(EntityUid uid, MultiHandedItemComponent component, GotUnequippedHandEvent args)
+ {
+ _virtualItem.DeleteInHandsMatching(args.User, uid);
+ }
+}
diff --git a/Content.Shared/Item/MultiHandedItemComponent.cs b/Content.Shared/Item/MultiHandedItemComponent.cs
new file mode 100644
index 0000000000..fd2a931172
--- /dev/null
+++ b/Content.Shared/Item/MultiHandedItemComponent.cs
@@ -0,0 +1,14 @@
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Item;
+
+///
+/// This is used for items that need
+/// multiple hands to be able to be picked up
+///
+[RegisterComponent, NetworkedComponent]
+public sealed class MultiHandedItemComponent : Component
+{
+ [DataField("handsNeeded"), ViewVariables(VVAccess.ReadWrite)]
+ public int HandsNeeded = 2;
+}
diff --git a/Content.Shared/Item/SharedMultiHandedItemSystem.cs b/Content.Shared/Item/SharedMultiHandedItemSystem.cs
new file mode 100644
index 0000000000..deef57b872
--- /dev/null
+++ b/Content.Shared/Item/SharedMultiHandedItemSystem.cs
@@ -0,0 +1,48 @@
+using Content.Shared.Hands;
+using Content.Shared.Hands.Components;
+using Content.Shared.Hands.EntitySystems;
+using Content.Shared.Popups;
+using Robust.Shared.Player;
+using Robust.Shared.Timing;
+
+namespace Content.Shared.Item;
+
+public abstract class SharedMultiHandedItemSystem : EntitySystem
+{
+ [Dependency] private readonly IGameTiming _timing = default!;
+ [Dependency] private readonly SharedHandsSystem _hands = default!;
+ [Dependency] private readonly SharedPopupSystem _popup = default!;
+
+ ///
+ public override void Initialize()
+ {
+ SubscribeLocalEvent(OnAttemptPickup);
+ SubscribeLocalEvent(OnVirtualItemDeleted);
+ SubscribeLocalEvent(OnEquipped);
+ SubscribeLocalEvent(OnUnequipped);
+ }
+
+ protected abstract void OnEquipped(EntityUid uid, MultiHandedItemComponent component, GotEquippedHandEvent args);
+ protected abstract void OnUnequipped(EntityUid uid, MultiHandedItemComponent component, GotUnequippedHandEvent args);
+
+ private void OnAttemptPickup(EntityUid uid, MultiHandedItemComponent component, GettingPickedUpAttemptEvent args)
+ {
+ if (TryComp(args.User, out var hands) && hands.CountFreeHands() >= component.HandsNeeded)
+ return;
+
+ args.Cancel();
+ if (_timing.IsFirstTimePredicted)
+ {
+ _popup.PopupEntity(Loc.GetString("multi-handed-item-pick-up-fail",
+ ("number", component.HandsNeeded - 1), ("item", uid)), args.User, Filter.Local());
+ }
+ }
+
+ private void OnVirtualItemDeleted(EntityUid uid, MultiHandedItemComponent component, VirtualItemDeletedEvent args)
+ {
+ if (args.BlockingEntity != uid)
+ return;
+
+ _hands.TryDrop(args.User, uid);
+ }
+}
diff --git a/Resources/Locale/en-US/items/components/multi-handed-item-component.ftl b/Resources/Locale/en-US/items/components/multi-handed-item-component.ftl
new file mode 100644
index 0000000000..d33630dc5e
--- /dev/null
+++ b/Resources/Locale/en-US/items/components/multi-handed-item-component.ftl
@@ -0,0 +1,4 @@
+multi-handed-item-pick-up-fail = {$number ->
+ [one] You need one more free hand to pick up { THE($item) }.
+ *[other] You need { $number } more free hands to pick up { THE($item) }.
+}