diff --git a/spec/command_spec.cr b/spec/command_spec.cr
index 38f5f1f..f7c9a5e 100644
--- a/spec/command_spec.cr
+++ b/spec/command_spec.cr
@@ -37,6 +37,11 @@ module Game::TestCommand
           ts: 20,
           resource: Resource.new(Resource::Type::Crystals, 40),
           input: ResourceBag.new({Resource::Type::Crystals => 5})
+        ),
+        production: Production.new(
+          ts: 20,
+          input: ResourceBag.new({Resource::Type::Crystals => 40}),
+          output: ResourceBag.new({Resource::Type::Terraformation => 20})
         )
       )
     )
@@ -104,5 +109,18 @@ module Game::TestCommand
       tile = world.map.get(1, 0).as(DepositTile)
       tile.dep.cur.should eq 40
     end
+
+    it "should complete produce command" do
+      world = World.new create_map_with_resource
+      world.resources.inc(Resource::Type::Crystals, 100)
+      command = ProduceCommand.new Point.new(0, 1), once: true
+      time_point = (20 + 1 * 2 + 1 * 2).to_i64
+      done_at = world.push command
+      done_at.should eq time_point
+      world.run time_point
+      # Check world resources
+      world.resources[Resource::Type::Crystals].should eq 60
+      world.resources[Resource::Type::Terraformation].should eq 20
+    end
   end
 end
diff --git a/src/game/command.cr b/src/game/command.cr
index a5c8d3a..69e5689 100644
--- a/src/game/command.cr
+++ b/src/game/command.cr
@@ -154,6 +154,54 @@ module Game
     end
   end
 
+  class ProduceCommand < Command
+    @holded : ResourceBag? = nil
+
+    def initialize(@point : Point, *, @once = false)
+    end
+
+    def desc : String
+      if @holded
+        sprintf "Produce at %d,%d", @point.x, @point.y
+      else
+        sprintf "Wait for resources at %d,%d", @point.x, @point.y
+      end
+    end
+
+    def start(world : World) : TimeSpan
+      tile = world.map.get(@point).as(BuildingTile)
+      building = tile.building
+      production = building.production.as(Production)
+      if !world.resources.has(production.input)
+        return production.ts
+      end
+      stock_tile = nearest_stock(world)
+      if stock_tile
+        world.resources.dec production.input
+        @holded = production.output
+        production.ts + 4 * tile.point.distance(stock_tile.point)
+      else
+        production.ts
+      end
+    end
+
+    def finish(world : World)
+      if @holded
+        world.resources.inc @holded.as(ResourceBag)
+      end
+      if !@once
+        world.push(ProduceCommand.new(@point))
+      end
+    end
+
+    private def nearest_stock(world : World) : BuildingTile?
+      tile = world.map.nearest_tile @point do |t|
+        t.is_a?(BuildingTile) && t.building.has_role Building::Role::Storehouse
+      end
+      tile.as?(BuildingTile)
+    end
+  end
+
   # class BuildCrystalHarvesterCommand < Command
   #   BUILD_TIME = 30