diff --git a/lua/orgmode/agenda/views/todos.lua b/lua/orgmode/agenda/views/todos.lua
index 725aa02c8..52ec74b24 100644
--- a/lua/orgmode/agenda/views/todos.lua
+++ b/lua/orgmode/agenda/views/todos.lua
@@ -6,9 +6,59 @@ local hl_map = agenda_highlights.get_agenda_hl_map()
 
 local function sort_todos(todos)
   table.sort(todos, function(a, b)
+    -- Tasks marked as clocked_in appear first
+    if a:is_clocked_in() then
+      return true
+    end
+    if b:is_clocked_in() then
+      return false
+    end
+
+    -- Then tasks are sorted by their priority
     if a:get_priority_sort_value() ~= b:get_priority_sort_value() then
       return a:get_priority_sort_value() > b:get_priority_sort_value()
     end
+
+    -- Then tasks are sorted by their TODO keyword
+    local a_keyword = a:get_todo()
+    local b_keyword = b:get_todo()
+    if (a_keyword and b_keyword) and (a_keyword ~= b_keyword) then
+      return a:get_todo_sort_value() < b:get_todo_sort_value()
+    end
+
+    -- Then tasks which have a DEADLINE have priority over SCHEDULED over nothing
+    local a_deadline = a:get_deadline_date()
+    local a_scheduled = a:get_scheduled_date()
+    local b_deadline = b:get_deadline_date()
+    local b_scheduled = b:get_scheduled_date()
+
+    -- If both have deadlines, earlier deadline comes first
+    if a_deadline and b_deadline then
+      return a_deadline < b_deadline
+    end
+
+    -- If only one has deadline, it comes first
+    if a_deadline then
+      return true
+    end
+    if b_deadline then
+      return false
+    end
+
+    -- If both have scheduled dates, earlier date comes first
+    if a_scheduled and b_scheduled then
+      return a_scheduled < b_scheduled
+    end
+
+    -- If only one has scheduled date, it comes first
+    if a_scheduled then
+      return true
+    end
+    if b_scheduled then
+      return false
+    end
+
+    -- Then tasks are sorted by their category keyword
     return a:get_category() < b:get_category()
   end)
   return todos
diff --git a/lua/orgmode/config/defaults.lua b/lua/orgmode/config/defaults.lua
index f2c18d9a4..b30f8aa0a 100644
--- a/lua/orgmode/config/defaults.lua
+++ b/lua/orgmode/config/defaults.lua
@@ -7,6 +7,7 @@ local DefaultConfig = {
   org_agenda_files = '',
   org_default_notes_file = '',
   org_todo_keywords = { 'TODO', '|', 'DONE' },
+  org_todo_default_state = nil,
   org_todo_repeat_to_state = nil,
   org_todo_keyword_faces = {},
   org_deadline_warning_days = 14,
diff --git a/lua/orgmode/files/headline.lua b/lua/orgmode/files/headline.lua
index c008dd2aa..085b26660 100644
--- a/lua/orgmode/files/headline.lua
+++ b/lua/orgmode/files/headline.lua
@@ -196,6 +196,19 @@ function Headline:get_priority_sort_value()
   return PriorityState:new(priority, prio_range):get_sort_value()
 end
 
+---@return integer | nil
+function Headline:get_todo_sort_value()
+  local todo_keyword = self:get_todo()
+  if todo_keyword == nil then
+    return nil
+  end
+  local todo_state = config:get_todo_keywords():find(todo_keyword)
+  if todo_state == nil then
+    return nil
+  end
+  return todo_state.index
+end
+
 function Headline:is_archived()
   return #vim.tbl_filter(function(tag)
     return tag:upper() == 'ARCHIVE'
diff --git a/lua/orgmode/org/mappings.lua b/lua/orgmode/org/mappings.lua
index ae63928e2..d4a9e3c2b 100644
--- a/lua/orgmode/org/mappings.lua
+++ b/lua/orgmode/org/mappings.lua
@@ -739,18 +739,25 @@ function OrgMappings:insert_heading_respect_content(suffix)
 end
 
 function OrgMappings:insert_todo_heading_respect_content()
-  return self:insert_heading_respect_content(config:get_todo_keywords():first_by_type('TODO').value .. ' ')
+  local first_todo_keyword = config.org_todo_default_state or config:get_todo_keywords():first_by_type('TODO').value
+  if not first_todo_keyword then
+    error('No default TODO keyword found')
+  end
+  return self:insert_heading_respect_content(first_todo_keyword .. ' ')
 end
 
 function OrgMappings:insert_todo_heading()
   local item = self.files:get_closest_headline_or_nil()
-  local first_todo_keyword = config:get_todo_keywords():first_by_type('TODO')
+  local first_todo_keyword = config.org_todo_default_state or config:get_todo_keywords():first_by_type('TODO').value
+  if not first_todo_keyword then
+    error('No default TODO keyword found')
+  end
   if not item then
-    self:_insert_heading_from_plain_line(first_todo_keyword.value .. ' ')
+    self:_insert_heading_from_plain_line(first_todo_keyword .. ' ')
     return vim.cmd([[startinsert!]])
   else
     vim.fn.cursor(item:get_range().start_line, 1)
-    return self:meta_return(first_todo_keyword.value .. ' ')
+    return self:meta_return(first_todo_keyword .. ' ')
   end
 end