diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -11,6 +11,7 @@
 - Search for a branch
 - Delete a branch
 - Fetch / Update
+- Worktree support
 
 ## Usage
 
@@ -42,6 +43,22 @@
 ```sh
 yay -S git-brunch
 pamac install git-brunch
+```
+
+### Homebrew (macOS)
+
+You can install `git-brunch` via a Homebrew tap. This uses a prebuilt macOS binary.
+
+```sh
+brew tap andys8/tap
+brew install git-brunch
+```
+
+#### macOS Security Note
+Since the binary is not signed with an Apple Developer certificate, macOS might block it initially. After installation, you can run this command to allow the binary to execute:
+
+```sh
+xattr -d com.apple.quarantine $(which git-brunch)
 ```
 
 ### FreeBSD
diff --git a/app/Git.hs b/app/Git.hs
--- a/app/Git.hs
+++ b/app/Git.hs
@@ -7,27 +7,35 @@
   isCommonBranch,
   isRemoteBranch,
   listBranches,
+  getWorktreePath,
   rebaseInteractive,
   merge,
   toBranches,
 ) where
 
 import Data.Char (isSpace)
+import Data.Map (Map)
+import Data.Map qualified as Map
+import Data.Maybe (fromMaybe)
 import Data.Text (Text)
 import Data.Text qualified as T
 import Data.Text.IO qualified as T
+import System.Directory (setCurrentDirectory)
+import System.Environment (lookupEnv)
 import System.Exit
 import System.Process
 
 data Branch
   = BranchLocal Text
   | BranchCurrent Text
+  | BranchWorktree Text
   | BranchRemote Text Text
   deriving (Eq)
 
 instance Show Branch where
   show (BranchLocal n) = T.unpack n
   show (BranchCurrent n) = T.unpack $ n <> "*"
+  show (BranchWorktree n) = T.unpack $ n <> "+"
   show (BranchRemote o n) = T.unpack $ o <> "/" <> n
 
 fetch :: IO Text
@@ -54,6 +62,7 @@
 toBranch line = mkBranch $ T.words $ T.dropWhile isSpace line
  where
   mkBranch ("*" : name : _) = BranchCurrent name
+  mkBranch ("+" : name : _) = BranchWorktree name
   mkBranch (name : _) = case T.stripPrefix "remotes/" name of
     Just rest -> parseRemoteBranch rest
     Nothing -> BranchLocal name
@@ -64,8 +73,20 @@
     name = T.drop 1 rest
 
 checkout :: Branch -> IO ExitCode
+checkout (BranchWorktree n) = do
+  mPath <- getWorktreePath n
+  case mPath of
+    Just path -> spawnShell path
+    Nothing -> spawnGit ["checkout", n]
 checkout branch = spawnGit ["checkout", branchName branch]
 
+spawnShell :: FilePath -> IO ExitCode
+spawnShell path = do
+  setCurrentDirectory path
+  userShell <- fromMaybe "/bin/sh" <$> lookupEnv "SHELL"
+  T.putStrLn $ "Worktree: " <> T.pack path
+  waitForProcess =<< spawnProcess userShell []
+
 rebaseInteractive :: Branch -> IO ExitCode
 rebaseInteractive branch = do
   T.putStrLn $ "Rebase onto " <> fullBranchName branch
@@ -78,6 +99,7 @@
 
 deleteBranch :: Branch -> IO ExitCode
 deleteBranch (BranchCurrent _) = error "Cannot delete current branch"
+deleteBranch (BranchWorktree _) = error "Cannot delete branch checked out in another worktree"
 deleteBranch (BranchLocal n) = spawnGit ["branch", "-D", n]
 deleteBranch (BranchRemote o n) = spawnGit ["push", o, "--delete", n]
 
@@ -87,6 +109,25 @@
 readGit :: [Text] -> IO Text
 readGit args = T.pack <$> readProcess "git" (T.unpack <$> args) []
 
+getWorktreePath :: Text -> IO (Maybe FilePath)
+getWorktreePath branch = do
+  output <- readGit ["worktree", "list", "--porcelain"]
+  let worktrees = parseWorktrees (T.lines output)
+  pure $ Map.lookup branch worktrees
+
+parseWorktrees :: [Text] -> Map Text FilePath
+parseWorktrees lines' = go lines' Map.empty Nothing
+ where
+  go [] m _ = m
+  go (l : ls) m currentPath
+    | "worktree " `T.isPrefixOf` l = go ls m (Just $ T.unpack $ T.drop 9 l)
+    | "branch " `T.isPrefixOf` l =
+        let branch = fromMaybe (T.drop 13 l) (T.stripPrefix "refs/heads/" (T.drop 7 l))
+         in case currentPath of
+              Just p -> go ls (Map.insert branch p m) Nothing
+              Nothing -> go ls m Nothing
+    | otherwise = go ls m currentPath
+
 isCommonBranch :: Branch -> Bool
 isCommonBranch b = branchName b `elem` commonBranchNames
  where
@@ -109,11 +150,13 @@
 
 branchName :: Branch -> Text
 branchName (BranchCurrent n) = n
+branchName (BranchWorktree n) = n
 branchName (BranchLocal n) = n
 branchName (BranchRemote _ n) = n
 
 fullBranchName :: Branch -> Text
 fullBranchName (BranchCurrent n) = n
+fullBranchName (BranchWorktree n) = n
 fullBranchName (BranchLocal n) = n
 fullBranchName (BranchRemote r n) = r <> "/" <> n
 
diff --git a/app/GitBrunch.hs b/app/GitBrunch.hs
--- a/app/GitBrunch.hs
+++ b/app/GitBrunch.hs
@@ -75,14 +75,17 @@
 main = do
   branches <- Git.listBranches `catch` gitFailed
   state <- M.defaultMain app $ syncBranchLists emptyState{_branches = branches}
-  let execGit = gitFunction (_gitCommand state)
-  exitCode <- maybe noBranchErr execGit (selectedBranch state)
-  when (exitCode /= ExitSuccess)
-    $ die ("Failed to " ++ show (_gitCommand state) ++ ".")
+  case selectedBranch state of
+    Nothing -> pure ()
+    Just branch -> do
+      let cmd = _gitCommand state
+      let execGit = gitFunction cmd
+      exitCode <- execGit branch
+      when (exitCode /= ExitSuccess)
+        $ die ("Failed to " ++ show cmd ++ ".")
  where
   gitFailed :: SomeException -> IO a
   gitFailed _ = exitFailure
-  noBranchErr = die "No branch selected."
   gitFunction = \case
     GitCheckout -> Git.checkout
     GitRebase -> Git.rebaseInteractive
@@ -181,6 +184,7 @@
  where
   maxPadding = if isListFocussed then padRight Max else id
   highlight (BranchCurrent _) = withAttr attrBranchCurrent
+  highlight (BranchWorktree _) = withAttr attrBranchWorktree
   highlight b | Git.isCommonBranch b = withAttr attrBranchCommon
   highlight _ = id
 
@@ -221,7 +225,10 @@
 
     confirmDelete :: Maybe Branch -> EventM Name State ()
     confirmDelete (Just (BranchCurrent _)) = pure ()
-    confirmDelete (Just _) = dialogL ?= createDialog GitDeleteBranch
+    confirmDelete (Just (BranchWorktree _)) = pure ()
+    confirmDelete (Just _) = do
+      gitCommandL .= GitDeleteBranch
+      dialogL ?= createDialog GitDeleteBranch
     confirmDelete Nothing = pure ()
 
     fetch = do
@@ -270,10 +277,29 @@
       dialogL .= Nothing
       gitCommandL .= GitCheckout
 
-    confirmDialog cmd = do
-      dialogL .= Nothing
-      gitCommandL .= cmd
-      halt
+    confirmDialog cmd =
+      if cmd == GitDeleteBranch
+        then do
+          dialogL .= Nothing
+          gitCommandL .= GitCheckout
+          state <- get
+          case selectedBranch state of
+            Nothing -> pure ()
+            Just branch -> M.suspendAndResume $ do
+              exitCode <- Git.deleteBranch branch
+              if exitCode == ExitSuccess
+                then do
+                  branches <- Git.listBranches
+                  pure $ syncBranchLists state{_branches = branches}
+                else do
+                  T.putStrLn $ "Failed to delete branch " <> Git.fullBranchName branch
+                  T.putStrLn "Press Enter to continue..."
+                  void getLine
+                  pure state
+        else do
+          dialogL .= Nothing
+          gitCommandL .= cmd
+          halt
    in
     case vimifiedKey e of
       EvKey KEnter [] -> do
@@ -325,7 +351,6 @@
 updateBranches branches =
   syncBranchLists
     . (branchesL .~ branches)
-    . (filterL .~ emptyFilter)
 
 syncBranchLists :: State -> State
 syncBranchLists state =
diff --git a/app/Theme.hs b/app/Theme.hs
--- a/app/Theme.hs
+++ b/app/Theme.hs
@@ -27,6 +27,7 @@
     , (attrTitle, withStyle (fg brightWhite) bold)
     , (attrTitleFocus, withStyle (fg yellow) bold)
     , (attrBranchCurrent, fg brightRed)
+    , (attrBranchWorktree, fg brightCyan)
     , (attrBranchCommon, fg brightBlue)
     ]
 
@@ -47,6 +48,9 @@
 
 attrBranchCurrent :: AttrName
 attrBranchCurrent = attrName "current-branch"
+
+attrBranchWorktree :: AttrName
+attrBranchWorktree = attrName "worktree-branch"
 
 attrBranchCommon :: AttrName
 attrBranchCommon = attrName "common-branch"
diff --git a/git-brunch.cabal b/git-brunch.cabal
--- a/git-brunch.cabal
+++ b/git-brunch.cabal
@@ -1,11 +1,11 @@
 cabal-version: 1.12
 
--- This file has been generated from package.yaml by hpack version 0.35.1.
+-- This file has been generated from package.yaml by hpack version 0.38.1.
 --
 -- see: https://github.com/sol/hpack
 
 name:           git-brunch
-version:        1.7.2.0
+version:        1.8.0
 synopsis:       git checkout command-line tool
 description:    Please see the README on GitHub at <https://github.com/andys8/git-brunch>
 category:       Git
@@ -45,6 +45,8 @@
   build-depends:
       base >=4.7 && <5
     , brick
+    , containers
+    , directory
     , extra
     , hspec
     , microlens
@@ -80,6 +82,8 @@
   build-depends:
       base >=4.7 && <5
     , brick
+    , containers
+    , directory
     , extra
     , hspec
     , microlens
diff --git a/test/Spec.hs b/test/Spec.hs
--- a/test/Spec.hs
+++ b/test/Spec.hs
@@ -14,6 +14,9 @@
     it "detects current branch by asterik" $ do
       toBranches "* master" `shouldBe` [BranchCurrent "master"]
 
+    it "detects worktree branch by plus" $ do
+      toBranches "+ master" `shouldBe` [BranchWorktree "master"]
+
     it "returns a local branch" $ do
       toBranches "master" `shouldBe` [BranchLocal "master"]
 
