diff --git a/changelog.md b/changelog.md
new file mode 100644
--- /dev/null
+++ b/changelog.md
@@ -0,0 +1,3 @@
+# 0.10.1.0
+
+* Convert to Polysemy
diff --git a/chiasma.cabal b/chiasma.cabal
--- a/chiasma.cabal
+++ b/chiasma.cabal
@@ -1,11 +1,11 @@
 cabal-version: 2.2
 
--- This file has been generated from package.yaml by hpack version 0.34.7.
+-- This file has been generated from package.yaml by hpack version 0.35.2.
 --
 -- see: https://github.com/sol/hpack
 
 name:           chiasma
-version:        0.10.0.0
+version:        0.10.1.0
 synopsis:       A tmux client for Polysemy
 description:    See https://hackage.haskell.org/package/chiasma/docs/Chiasma.html
 category:       Terminal
@@ -13,10 +13,13 @@
 bug-reports:    https://github.com/tek/chiasma/issues
 author:         Torsten Schmits
 maintainer:     hackage@tryp.io
-copyright:      2022 Torsten Schmits
+copyright:      2023 Torsten Schmits
 license:        BSD-2-Clause-Patent
 license-file:   LICENSE
 build-type:     Simple
+extra-source-files:
+    readme.md
+    changelog.md
 
 source-repository head
   type: git
@@ -126,72 +129,44 @@
   hs-source-dirs:
       lib
   default-extensions:
-      ImpredicativeTypes
       AllowAmbiguousTypes
       ApplicativeDo
-      BangPatterns
-      BinaryLiterals
       BlockArguments
-      ConstraintKinds
       DataKinds
       DefaultSignatures
       DeriveAnyClass
-      DeriveDataTypeable
-      DeriveFoldable
-      DeriveFunctor
-      DeriveGeneric
-      DeriveLift
-      DeriveTraversable
       DerivingStrategies
       DerivingVia
       DisambiguateRecordFields
-      DoAndIfThenElse
       DuplicateRecordFields
-      EmptyCase
-      EmptyDataDecls
-      ExistentialQuantification
-      FlexibleContexts
-      FlexibleInstances
       FunctionalDependencies
       GADTs
-      GeneralizedNewtypeDeriving
-      InstanceSigs
-      KindSignatures
       LambdaCase
       LiberalTypeSynonyms
-      MultiParamTypeClasses
       MultiWayIf
-      NamedFieldPuns
       OverloadedLabels
       OverloadedLists
       OverloadedStrings
       PackageImports
       PartialTypeSignatures
-      PatternGuards
       PatternSynonyms
-      PolyKinds
       QuantifiedConstraints
       QuasiQuotes
-      RankNTypes
       RecordWildCards
       RecursiveDo
       RoleAnnotations
-      ScopedTypeVariables
-      StandaloneDeriving
       TemplateHaskell
-      TupleSections
-      TypeApplications
       TypeFamilies
       TypeFamilyDependencies
-      TypeOperators
-      TypeSynonymInstances
       UndecidableInstances
       UnicodeSyntax
       ViewPatterns
-  ghc-options: -Wall -Wredundant-constraints -Wincomplete-uni-patterns -Wmissing-deriving-strategies -Widentities -Wunused-packages -fplugin=Polysemy.Plugin
+      OverloadedRecordDot
+      NoFieldSelectors
+  ghc-options: -fplugin=Polysemy.Plugin -Wall -Widentities -Wincomplete-uni-patterns -Wmissing-deriving-strategies -Wredundant-constraints -Wunused-type-patterns -Wunused-packages
   build-depends:
       attoparsec >=0.13
-    , base >=4.12 && <5
+    , base ==4.*
     , bytestring
     , composition >=1.0
     , containers
@@ -208,7 +183,7 @@
     , polysemy-plugin
     , polysemy-process >=0.9
     , polysemy-time >=0.5
-    , prelate >=0.2
+    , prelate >=0.6 && <0.8
     , prettyprinter >=1.6
     , prettyprinter-ansi-terminal >=1.1
     , random >=1.1
@@ -220,4 +195,4 @@
       base hiding (Prelude)
     , prelate (Prelate as Prelude)
     , prelate hiding (Prelate)
-  default-language: Haskell2010
+  default-language: GHC2021
diff --git a/lib/Chiasma/Codec/Data/Pane.hs b/lib/Chiasma/Codec/Data/Pane.hs
--- a/lib/Chiasma/Codec/Data/Pane.hs
+++ b/lib/Chiasma/Codec/Data/Pane.hs
@@ -16,4 +16,4 @@
   deriving anyclass (TmuxCodec)
 
 instance HasPaneId Pane where
-  paneId = paneId
+  paneId = (.paneId)
diff --git a/lib/Chiasma/Codec/Data/PaneCoords.hs b/lib/Chiasma/Codec/Data/PaneCoords.hs
--- a/lib/Chiasma/Codec/Data/PaneCoords.hs
+++ b/lib/Chiasma/Codec/Data/PaneCoords.hs
@@ -14,4 +14,4 @@
   deriving anyclass (TmuxCodec)
 
 instance HasPaneId PaneCoords where
-  paneId = paneId
+  paneId = (.paneId)
diff --git a/lib/Chiasma/Codec/Data/PaneMode.hs b/lib/Chiasma/Codec/Data/PaneMode.hs
--- a/lib/Chiasma/Codec/Data/PaneMode.hs
+++ b/lib/Chiasma/Codec/Data/PaneMode.hs
@@ -13,4 +13,4 @@
   deriving anyclass (TmuxCodec)
 
 instance HasPaneId PaneMode where
-  paneId = paneId
+  paneId = (.paneId)
diff --git a/lib/Chiasma/Codec/Data/PanePid.hs b/lib/Chiasma/Codec/Data/PanePid.hs
--- a/lib/Chiasma/Codec/Data/PanePid.hs
+++ b/lib/Chiasma/Codec/Data/PanePid.hs
@@ -13,4 +13,4 @@
   deriving anyclass (TmuxCodec)
 
 instance HasPaneId PanePid where
-  paneId = paneId
+  paneId = (.paneId)
diff --git a/lib/Chiasma/Command/Pane.hs b/lib/Chiasma/Command/Pane.hs
--- a/lib/Chiasma/Command/Pane.hs
+++ b/lib/Chiasma/Command/Pane.hs
@@ -1,3 +1,4 @@
+{-# OPTIONS_GHC -Wno-ambiguous-fields #-}
 module Chiasma.Command.Pane where
 
 import Prelude hiding (output)
diff --git a/lib/Chiasma/Data/SessionParams.hs b/lib/Chiasma/Data/SessionParams.hs
--- a/lib/Chiasma/Data/SessionParams.hs
+++ b/lib/Chiasma/Data/SessionParams.hs
@@ -63,7 +63,7 @@
     <>
     identOption "-s" name
     <>
-    optionWith "-t" unSessionGroupId target
+    optionWith "-t" (.unSessionGroupId) target
     <>
     optionWith "-x" show width
     <>
diff --git a/lib/Chiasma/Data/TmuxCommand.hs b/lib/Chiasma/Data/TmuxCommand.hs
--- a/lib/Chiasma/Data/TmuxCommand.hs
+++ b/lib/Chiasma/Data/TmuxCommand.hs
@@ -3,7 +3,7 @@
 import Data.List (dropWhileEnd)
 import qualified Data.Text as Text
 import Exon (exon)
-import Text.Show (Show (showsPrec), showParen, showString, shows)
+import Text.Show (shows)
 
 import Chiasma.Class.CmdArgs (cmdArgs)
 import qualified Chiasma.Codec as Codec
diff --git a/lib/Chiasma/Data/TmuxId.hs b/lib/Chiasma/Data/TmuxId.hs
--- a/lib/Chiasma/Data/TmuxId.hs
+++ b/lib/Chiasma/Data/TmuxId.hs
@@ -1,5 +1,6 @@
 module Chiasma.Data.TmuxId where
 
+import Data.Data (Data)
 import Prettyprinter (Pretty (..))
 
 newtype ClientId =
@@ -8,7 +9,7 @@
   deriving newtype (IsString)
 
 instance Pretty ClientId where
-  pretty = pretty . unClientId
+  pretty = pretty . (.unClientId)
 
 sessionPrefix :: Text
 sessionPrefix = "$"
@@ -37,7 +38,7 @@
 
 newtype PaneId =
   PaneId Int
-  deriving stock (Eq, Show, Generic)
+  deriving stock (Eq, Show, Generic, Data)
   deriving newtype (Num, Ord)
 
 instance Pretty PaneId where
diff --git a/lib/Chiasma/Data/View.hs b/lib/Chiasma/Data/View.hs
--- a/lib/Chiasma/Data/View.hs
+++ b/lib/Chiasma/Data/View.hs
@@ -1,21 +1,19 @@
 module Chiasma.Data.View where
 
-import Chiasma.Data.Ident (Ident, Identifiable(..))
-import Control.Lens (makeClassy_)
 import qualified Control.Lens as Lens (set)
 
+import Chiasma.Data.Ident (Ident, Identifiable (..))
+
 data View a =
   View {
-    viewIdent :: Ident,
-    viewId :: Maybe a
+    ident :: Ident,
+    id :: Maybe a
   }
-  deriving stock (Eq, Show)
-
-makeClassy_ ''View
+  deriving stock (Eq, Show, Generic)
 
 instance Identifiable (View a) where
-  identify = viewIdent
+  identify = (.ident)
 
 setViewId :: a -> View a -> View a
 setViewId =
-  Lens.set _viewId . Just
+  Lens.set #id . Just
diff --git a/lib/Chiasma/Data/WithPaneId.hs b/lib/Chiasma/Data/WithPaneId.hs
--- a/lib/Chiasma/Data/WithPaneId.hs
+++ b/lib/Chiasma/Data/WithPaneId.hs
@@ -17,7 +17,7 @@
   deriving stock (Eq, Show, Generic)
 
 instance HasPaneId (WithPaneId a) where
-  paneId = paneId
+  paneId = (.paneId)
 
 safeBreakOn :: Text -> Text -> Maybe (Text, Text)
 safeBreakOn n = \case
diff --git a/lib/Chiasma/Interpreter/TmuxClient.hs b/lib/Chiasma/Interpreter/TmuxClient.hs
--- a/lib/Chiasma/Interpreter/TmuxClient.hs
+++ b/lib/Chiasma/Interpreter/TmuxClient.hs
@@ -1,6 +1,6 @@
 module Chiasma.Interpreter.TmuxClient where
 
-import Conc (interpretAtomic, interpretScopedResumableWith_, interpretScopedResumable_)
+import Conc (interpretAtomic)
 import Data.Sequence ((|>))
 import qualified Data.Text as Text
 import Exon (exon)
diff --git a/lib/Chiasma/Lens/Tree.hs b/lib/Chiasma/Lens/Tree.hs
--- a/lib/Chiasma/Lens/Tree.hs
+++ b/lib/Chiasma/Lens/Tree.hs
@@ -1,29 +1,12 @@
 module Chiasma.Lens.Tree where
 
-import Control.Lens (
-  Fold,
-  Index,
-  IxValue,
-  Ixed (ix),
-  Plated (..),
-  cosmos,
-  makeClassy_,
-  preview,
-  transform,
-  )
+import Control.Lens (Fold, Index, IxValue, Ixed (ix), Plated (..), cosmos, makeClassy_, preview, transform, lens)
 import Data.Data (Data)
 import Data.Foldable (foldrM)
 import Prelude hiding (ix, transform)
 
 import Chiasma.Data.Ident (Ident, Identifiable (..))
-import Chiasma.Ui.Data.View (
-  HasTree (_treeSubs),
-  HasTreeSub (leafData),
-  LayoutView,
-  PaneView,
-  Tree (Tree),
-  TreeSub (TreeNode),
-  )
+import Chiasma.Ui.Data.View (LayoutView, PaneView, Tree (Tree), TreeSub (TreeNode))
 import Chiasma.Ui.Lens.Ident (matchIdentP)
 
 newtype NodeIndexTree l p =
@@ -49,10 +32,10 @@
     g tree' = unconsWrapper <$> f (consWrapper tree')
 
 instance (Data l, Data p) => Plated (NodeIndexTree l p) where
-  plate = plateWrap NodeIndexTree nitTree
+  plate = plateWrap NodeIndexTree (.nitTree)
 
 instance (Data l, Data p) => Plated (LeafIndexTree l p) where
-  plate = plateWrap LeafIndexTree litTree
+  plate = plateWrap LeafIndexTree (.litTree)
 
 type LayoutIndexTree = NodeIndexTree LayoutView PaneView
 type PaneIndexTree = LeafIndexTree LayoutView PaneView
@@ -63,29 +46,98 @@
 type instance IxValue (NodeIndexTree l _) = l
 type instance IxValue (LeafIndexTree _ p) = p
 
+nodeTraversal :: Traversal' (Tree l p) l
+nodeTraversal = #treeSubs . each . #_TreeNode . #treeData
+
+nodeByIdentTraversal :: Identifiable l => Ident -> Traversal' (Tree l p) l
+nodeByIdentTraversal ident = nodeTraversal . matchIdentP ident
+
 leafDataTraversal :: Traversal' (Tree l p) p
-leafDataTraversal = _treeSubs . each . leafData
+leafDataTraversal = #treeSubs . each . #_TreeLeaf
 
 leafByIdentTraversal :: Identifiable p => Ident -> Traversal' (Tree l p) p
-leafByIdentTraversal ident' = leafDataTraversal . matchIdentP ident'
+leafByIdentTraversal ident = leafDataTraversal . matchIdentP ident
 
+instance Identifiable l => Ixed (NodeIndexTree l p) where
+  ix ident = _nitTree . nodeByIdentTraversal ident
+
+nodesByIdentRecursive :: (Identifiable l, Data l, Data p) => Ident -> Fold (NodeIndexTree l p) l
+nodesByIdentRecursive ident = cosmos . ix ident
+
+nodesIdent ::
+  ∀ l p .
+  Identifiable l =>
+  Data l =>
+  Data p =>
+  Ident ->
+  Fold (Tree l p) l
+nodesIdent ident = lens coerce (const (.nitTree)) . nodesByIdentRecursive ident
+
+nodeByIdent ::
+  ∀ l p .
+  Identifiable l =>
+  Data l =>
+  Data p =>
+  Ident ->
+  Tree l p ->
+  Maybe l
+nodeByIdent ident = preview (nodesIdent ident)
+
+nodesByIdent ::
+  ∀ l p .
+  Identifiable l =>
+  Data l =>
+  Data p =>
+  Ident ->
+  Tree l p ->
+  [l]
+nodesByIdent ident = toListOf (nodesIdent ident)
+
 instance Identifiable p => Ixed (LeafIndexTree l p) where
-  ix ident' = _litTree . leafByIdentTraversal ident'
+  ix ident = _litTree . leafByIdentTraversal ident
 
-leavesByIdentRecursive :: (Identifiable p, Data l, Data p) => Ident -> Fold (LeafIndexTree l p) p
-leavesByIdentRecursive ident' = cosmos . ix ident'
+leavesByIdentRecursive ::
+  ∀ l p .
+  Identifiable p =>
+  Data l =>
+  Data p =>
+  Ident ->
+  Fold (LeafIndexTree l p) p
+leavesByIdentRecursive ident = cosmos . ix ident
 
-leafByIdent :: (Identifiable p, Data l, Data p) => Ident -> Tree l p -> Maybe p
-leafByIdent ident' = preview (leavesByIdentRecursive ident') . LeafIndexTree
+leavesIdent ::
+  ∀ l p .
+  Identifiable p =>
+  Data l =>
+  Data p =>
+  Ident ->
+  Fold (Tree l p) p
+leavesIdent ident = lens coerce (const (.litTree)) . leavesByIdentRecursive ident
 
-leavesByIdent :: (Identifiable p, Data l, Data p) => Ident -> Tree l p -> [p]
-leavesByIdent ident' = toListOf (leavesByIdentRecursive ident') . LeafIndexTree
+leafByIdent ::
+  ∀ l p .
+  Identifiable p =>
+  Data l =>
+  Data p =>
+  Ident ->
+  Tree l p ->
+  Maybe p
+leafByIdent ident = preview (leavesIdent ident)
 
+leavesByIdent ::
+  ∀ l p .
+  Identifiable p =>
+  Data l =>
+  Data p =>
+  Ident ->
+  Tree l p ->
+  [p]
+leavesByIdent ident = toListOf (leavesIdent ident)
+
 modifyLeafByIdent :: (Identifiable p, Data l, Data p) => Ident -> (p -> p) -> Tree l p -> Tree l p
-modifyLeafByIdent ident' f tree' =
-  litTree $ (transform $ over (ix ident') f) (LeafIndexTree tree')
+modifyLeafByIdent ident f tree' =
+  (.litTree) $ (transform $ over (ix ident) f) (LeafIndexTree tree')
 
--- subtreesWithLayout :: Traversal' (Tree l p) (l, TreeSub l p)
 subtreesWithLayout :: ∀ l p m. Monad m => ((l, TreeSub l p) -> m (l, TreeSub l p)) -> Tree l p -> m (Tree l p)
 subtreesWithLayout f (Tree l0 sub) = do
   (newL, newSub) <- foldrM applySub (l0, []) sub
diff --git a/lib/Chiasma/Native/TmuxOutputBlock.hs b/lib/Chiasma/Native/TmuxOutputBlock.hs
--- a/lib/Chiasma/Native/TmuxOutputBlock.hs
+++ b/lib/Chiasma/Native/TmuxOutputBlock.hs
@@ -9,24 +9,24 @@
 
 import Chiasma.Data.TmuxOutputBlock (End (EndError, EndSuccess), TmuxOutputBlock (Error, Success))
 
-tillEol :: (Alternative m, CharParsing m) => m Text
+tillEol :: (CharParsing m) => m Text
 tillEol = decodeUtf8 . packChars <$> manyTill anyChar newline
 
-beginLine :: (Alternative m, CharParsing m, Monad m) => m ()
+beginLine :: (CharParsing m, Monad m) => m ()
 beginLine = void $ string "%begin" >> tillEol
 
-endLine :: (Alternative m, CharParsing m) => m End
+endLine :: (CharParsing m) => m End
 endLine = do
   end <- choice [EndSuccess <$ string "%end", EndError <$ string "%error"]
   _ <- tillEol
   pure end
 
-notBeginLine :: (Alternative m, CharParsing m, Monad m) => m ()
+notBeginLine :: (CharParsing m, Monad m) => m ()
 notBeginLine = void $ notFollowedBy (string "%begin") >> tillEol
 
 -- |Parse a sequence of lines between a %start and a %end line.
 -- Tmux pads output lines with a single space on both sides, so strip those if the leading one is present.
-parseBlock :: (Alternative m, CharParsing m, Monad m, LookAheadParsing m) => m TmuxOutputBlock
+parseBlock :: (CharParsing m, Monad m, LookAheadParsing m) => m TmuxOutputBlock
 parseBlock = do
   _ <- skipMany notBeginLine
   _ <- beginLine
@@ -36,7 +36,7 @@
     EndSuccess -> Success dataLines
     EndError -> Error dataLines
 
-parseBlocks :: (Alternative m, CharParsing m, Monad m, LookAheadParsing m) => m [TmuxOutputBlock]
+parseBlocks :: (CharParsing m, Monad m, LookAheadParsing m) => m [TmuxOutputBlock]
 parseBlocks = do
   result <- many (try parseBlock)
   skipMany tillEol
diff --git a/lib/Chiasma/Session.hs b/lib/Chiasma/Session.hs
--- a/lib/Chiasma/Session.hs
+++ b/lib/Chiasma/Session.hs
@@ -1,6 +1,7 @@
 module Chiasma.Session where
 
 import Exon (exon)
+
 import qualified Chiasma.Codec.Data.Session as Codec (Session (Session))
 import qualified Chiasma.Codec.Data.Window as Codec (Window (Window))
 import Chiasma.Command.Session (existingSessionId, newSession)
@@ -8,7 +9,7 @@
 import Chiasma.Data.Ident (Ident)
 import Chiasma.Data.LayoutError (LayoutError)
 import Chiasma.Data.TmuxId (SessionId, WindowId)
-import qualified Chiasma.Data.View as Tmux (View (viewId, viewIdent), setViewId)
+import qualified Chiasma.Data.View as Tmux
 import Chiasma.Data.Views (Views)
 import Chiasma.Effect.TmuxApi (Tmux)
 import Chiasma.View (findOrCreateView, viewsLogS)
@@ -27,7 +28,7 @@
   Tmux.View WindowId ->
   Sem r (SessionId, WindowId)
 spawnSession session' window = do
-  Codec.Session sid _ <- newSession (Tmux.viewIdent session')
+  Codec.Session sid _ <- newSession session'.ident
   atomicModify' (Views.updateSession (Tmux.setViewId sid session'))
   Codec.Window wid _ _ <- newSessionWindow sid
   atomicModify' (Views.updateWindow (Tmux.setViewId wid window))
@@ -40,7 +41,7 @@
   Tmux.View WindowId ->
   Sem r (SessionId, Maybe WindowId)
 ensureSession session' window = do
-  existing <- join <$> traverse existingSessionId (Tmux.viewId session')
+  existing <- join <$> traverse existingSessionId session'.id
   case existing of
     Just sid -> pure (sid, Nothing)
     Nothing -> second Just <$> spawnSession session' window
diff --git a/lib/Chiasma/Ui/Data/View.hs b/lib/Chiasma/Ui/Data/View.hs
--- a/lib/Chiasma/Ui/Data/View.hs
+++ b/lib/Chiasma/Ui/Data/View.hs
@@ -1,9 +1,10 @@
 module Chiasma.Ui.Data.View where
 
-import Control.Lens (Index, IxValue, Ixed (ix), makeClassy, makeClassy_)
+import Control.Lens (Fold, Index, IxValue, Ixed (ix), cosmos, preview)
 import Control.Lens.Plated (Plated)
 import Data.Bifoldable (Bifoldable (bifoldMap))
 import Data.Data (Data)
+import Prelude hiding (ix)
 import Prettyprinter (Doc, Pretty (..), emptyDoc, nest, space, vsep, (<+>))
 
 import Chiasma.Data.Axis (Axis (Horizontal, Vertical))
@@ -14,14 +15,12 @@
 
 data Pane =
   Pane {
-    _open :: Bool,
-    _pin :: Bool,
-    _cwd :: Maybe Text
+    open :: Bool,
+    pin :: Bool,
+    cwd :: Maybe Text
   }
   deriving stock (Eq, Show, Data, Generic)
 
-makeClassy ''Pane
-
 instance Default Pane where
   def = Pane False False Nothing
 
@@ -32,19 +31,15 @@
   deriving stock (Eq, Show, Data, Generic)
   deriving newtype (Default)
 
-makeClassy_ ''Layout
-
 data View a =
   View {
-    _ident :: Ident,
-    _state :: ViewState,
-    _geometry :: ViewGeometry,
-    _extra :: a
+    ident :: Ident,
+    state :: ViewState,
+    geometry :: ViewGeometry,
+    extra :: a
   }
   deriving stock (Eq, Show, Data, Generic)
 
-makeClassy ''View
-
 instance Default a => Default (View a) where
   def = View def def def def
 
@@ -89,7 +84,7 @@
   consLayoutAs Vertical
 
 instance Identifiable (View a) where
-  identify = _ident
+  identify = (.ident)
 
 -- split in two so there can be no lone leaves (panes without layout) as type 'Tree'
 data Tree l p =
@@ -109,9 +104,9 @@
   bifoldMap fl fr (Tree l sub) = mappend (fl l) (foldMap (bifoldMap fl fr) sub)
 
 data TreeSub l p =
-  TreeNode { _subTree :: Tree l p }
+  TreeNode { subTree :: Tree l p }
   |
-  TreeLeaf { _leafData :: p }
+  TreeLeaf { leafData :: p }
   deriving stock (Eq, Show, Data, Generic)
 
 instance Bifunctor TreeSub where
@@ -127,9 +122,6 @@
 
 instance (Data l, Data p) => Plated (Tree l p)
 
-makeClassy_ ''Tree
-makeClassy ''TreeSub
-
 type ViewTree = Tree LayoutView PaneView
 type ViewTreeSub = TreeSub LayoutView PaneView
 
@@ -140,8 +132,7 @@
 type instance IxValue (Tree l p) = Tree l p
 
 instance Identifiable l => Ixed (Tree l p) where
-  ix i =
-    matchIdentP i
+  ix i = matchIdentP i
 
 instance (Pretty l, Pretty p) => Pretty (TreeSub l p) where
   pretty (TreeNode a) =
@@ -152,3 +143,50 @@
 instance (Pretty l, Pretty p) => Pretty (Tree l p) where
   pretty (Tree l sub) =
     nest 2 . vsep $ pretty l : (pretty <$> sub)
+
+treeTraversal :: Traversal' (Tree l p) (Tree l p)
+treeTraversal = #treeSubs . each . #_TreeNode
+
+treeByIdentTraversal :: Identifiable l => Ident -> Traversal' (Tree l p) (Tree l p)
+treeByIdentTraversal ident' = treeTraversal . ix ident'
+
+treesIdent ::
+  ∀ l p .
+  Identifiable l =>
+  Data l =>
+  Data p =>
+  Ident ->
+  Fold (Tree l p) (Tree l p)
+treesIdent ident' = cosmos . ix ident'
+
+treeByIdent ::
+  ∀ l p .
+  Identifiable l =>
+  Data l =>
+  Data p =>
+  Ident ->
+  Tree l p ->
+  Maybe (Tree l p)
+treeByIdent ident' = preview (treesIdent ident')
+
+treesByIdent ::
+  ∀ l p .
+  Identifiable l =>
+  Data l =>
+  Data p =>
+  Ident ->
+  Tree l p ->
+  [Tree l p]
+treesByIdent ident' = toListOf (treesIdent ident')
+
+-- | All subtrees including self.
+trees :: (Data l, Data p) => Fold (Tree l p) (Tree l p)
+trees = cosmos
+
+-- | All transitive leaves in the tree.
+leaves :: (Data l, Data p) => Fold (Tree l p) p
+leaves = cosmos . #treeSubs . each . #_TreeLeaf
+
+-- | All transitive nodes in the tree.
+nodes :: (Data l, Data p) => Fold (Tree l p) l
+nodes = cosmos . #treeData
diff --git a/lib/Chiasma/Ui/Measure.hs b/lib/Chiasma/Ui/Measure.hs
--- a/lib/Chiasma/Ui/Measure.hs
+++ b/lib/Chiasma/Ui/Measure.hs
@@ -14,11 +14,11 @@
 import Chiasma.Ui.Measure.Weights (viewWeights)
 
 minimizedSizeOrDefault :: ViewGeometry -> Float
-minimizedSizeOrDefault = fromMaybe 2 . minSize
+minimizedSizeOrDefault = fromMaybe 2 . (.minSize)
 
 effectiveFixedSize :: ViewState -> ViewGeometry -> Maybe Float
 effectiveFixedSize (ViewState minimized) viewGeom =
-  if minimized then Just (minimizedSizeOrDefault viewGeom) else fixedSize viewGeom
+  if minimized then Just (minimizedSizeOrDefault viewGeom) else viewGeom.fixedSize
 
 actualSize :: (ViewGeometry -> Maybe Float) ->  ViewState -> ViewGeometry -> Maybe Float
 actualSize getter viewState viewGeom =
@@ -26,11 +26,11 @@
 
 actualMinSizes :: NonEmpty (ViewState, ViewGeometry) -> NonEmpty Float
 actualMinSizes =
-  fmap (fromMaybe 0.0 . uncurry (actualSize minSize))
+  fmap (fromMaybe 0.0 . uncurry (actualSize (.minSize)))
 
 actualMaxSizes :: NonEmpty (ViewState, ViewGeometry) -> NonEmpty (Maybe Float)
 actualMaxSizes =
-  fmap (uncurry $ actualSize maxSize)
+  fmap (uncurry $ actualSize (.maxSize))
 
 isMinimized :: ViewState -> ViewGeometry -> Bool
 isMinimized (ViewState minimized) _ = minimized
diff --git a/lib/Chiasma/Ui/Measure/Balance.hs b/lib/Chiasma/Ui/Measure/Balance.hs
--- a/lib/Chiasma/Ui/Measure/Balance.hs
+++ b/lib/Chiasma/Ui/Measure/Balance.hs
@@ -3,10 +3,7 @@
 import Data.List (zipWith3)
 import qualified Data.List.NonEmpty as NonEmpty
 
-import Chiasma.Ui.Measure.Weights (
-  amendAndNormalizeWeights,
-  normalizeWeights,
-  )
+import Chiasma.Ui.Measure.Weights (amendAndNormalizeWeights, normalizeWeights)
 
 zipWith3NE :: (a -> b -> c -> d)  ->  NonEmpty a -> NonEmpty b -> NonEmpty c -> NonEmpty d
 zipWith3NE z ~(a :| as) ~(b :| bs) ~(c :| cs) =
@@ -114,17 +111,17 @@
 
 hasUnbounded :: Balance -> Bool
 hasUnbounded =
-  any isNothing . balanceMax
+  any isNothing . (.balanceMax)
 
 distributeSizes :: Balance -> NonEmpty Float
 distributeSizes balance =
   handler balance
   where
     handler =
-      if (maxTotal < balanceTotal balance) && hasUnbounded balance
+      if (maxTotal < balance.balanceTotal) && hasUnbounded balance
       then distributeOnUnbounded
       else distributeOnAll
-    maxTotal = sum (catMaybes $ NonEmpty.toList $ balanceMax balance)
+    maxTotal = sum (catMaybes $ NonEmpty.toList $ (.balanceMax) balance)
 
 roundSizes :: NonEmpty Float -> NonEmpty Int
 roundSizes (h :| t) =
diff --git a/lib/Chiasma/Ui/ViewTree.hs b/lib/Chiasma/Ui/ViewTree.hs
--- a/lib/Chiasma/Ui/ViewTree.hs
+++ b/lib/Chiasma/Ui/ViewTree.hs
@@ -10,11 +10,7 @@
 import Prelude hiding (ix, tell)
 
 import Chiasma.Data.Ident (Ident)
-import Chiasma.Lens.Tree (
-  LeafIndexTree (..),
-  _litTree,
-  leafDataTraversal,
-  )
+import Chiasma.Lens.Tree (LeafIndexTree (..), _litTree, leafDataTraversal)
 import Chiasma.Ui.Data.TreeModError (TreeModError (AmbiguousLayout, AmbiguousPane, LayoutMissing, PaneMissing))
 import Chiasma.Ui.Data.View (
   Pane (Pane),
@@ -25,9 +21,6 @@
   ViewTree,
   ViewTreeSub,
   )
-import qualified Chiasma.Ui.Data.View as Pane (open)
-import qualified Chiasma.Ui.Data.View as TreeSub (leafData)
-import qualified Chiasma.Ui.Data.View as View (extra)
 import Chiasma.Ui.Data.ViewState (ViewState (ViewState))
 import Chiasma.Ui.Pane (paneSetOpen, paneToggleOpen)
 
@@ -61,7 +54,7 @@
   let st = (transformM $ mapMOf (ix ident) (modCounted f)) (LeafIndexTree tree)
   (result, Sum count) <- lift $ runWriterT st
   case count of
-    1 -> pure $ litTree result
+    1 -> pure $ (.litTree) result
     0 -> ExceptT (pure (Left (PaneMissing ident)))
     n -> ExceptT (pure (Left (AmbiguousPane ident n)))
 
@@ -252,7 +245,7 @@
 
 isOpenPaneNode :: ViewTreeSub -> Bool
 isOpenPaneNode =
-  anyOf (TreeSub.leafData . View.extra . Pane.open) id
+  anyOf (#_TreeLeaf . #extra . #open) id
 
 openPinnedPaneView :: PaneView -> (ToggleStatus, PaneView)
 openPinnedPaneView (View i s g (Pane False True c)) =
diff --git a/lib/Chiasma/View.hs b/lib/Chiasma/View.hs
--- a/lib/Chiasma/View.hs
+++ b/lib/Chiasma/View.hs
@@ -7,7 +7,8 @@
 
 import Chiasma.Data.Ident (Ident, identText, sameIdent)
 import Chiasma.Data.TmuxId (PaneId, SessionId, WindowId)
-import Chiasma.Data.View (View (View), viewIdent)
+import qualified Chiasma.Data.View
+import Chiasma.Data.View (View (View))
 import Chiasma.Data.Views (Views, ViewsError (..))
 import qualified Chiasma.Data.Views as Views (log, panes, sessions, windows)
 import Chiasma.Lens.Where (where1)
@@ -27,9 +28,15 @@
 insertView :: Lens' Views [View a] -> View a -> Views -> Views
 insertView viewsL newView = over viewsL (newView :)
 
-updateView :: Lens' Views [View a] -> (Ident -> ViewsError) -> View a -> Views -> Views
+updateView ::
+  ∀ a .
+  Lens' Views [View a] ->
+  (Ident -> ViewsError) ->
+  View a ->
+  Views ->
+  Views
 updateView viewsL _ newView =
-  set (viewsL . where1 (sameIdent (viewIdent newView))) newView
+  set (viewsL . where1 (sameIdent newView.ident)) newView
 
 session :: Ident -> Views -> Either ViewsError (View SessionId)
 session = view Views.sessions NoSuchSession
diff --git a/lib/Chiasma/Window.hs b/lib/Chiasma/Window.hs
--- a/lib/Chiasma/Window.hs
+++ b/lib/Chiasma/Window.hs
@@ -5,7 +5,7 @@
 import Prettyprinter (line, pretty, vsep, (<+>))
 
 import qualified Chiasma.Codec.Data.Pane as Pane
-import qualified Chiasma.Codec.Data.Pane as Codec (Pane (Pane, paneId))
+import qualified Chiasma.Codec.Data.Pane as Codec (Pane (Pane))
 import Chiasma.Codec.Data.Pane (Pane (Pane))
 import qualified Chiasma.Codec.Data.Window as Codec (Window (Window, windowId))
 import qualified Chiasma.Command.Pane as Cmd (closePane, firstWindowPane, windowPanes)
@@ -21,13 +21,7 @@
 import Chiasma.Data.WindowState (WindowState (..))
 import Chiasma.Effect.TmuxApi (Tmux)
 import Chiasma.Pane (addPane)
-import Chiasma.Ui.Data.RenderableTree (
-  RLayout (..),
-  RPane (..),
-  Renderable (..),
-  RenderableNode,
-  RenderableTree,
-  )
+import Chiasma.Ui.Data.RenderableTree (RLayout (..), RPane (..), Renderable (..), RenderableNode, RenderableTree)
 import qualified Chiasma.Ui.Data.Tree as Tree (Node (Leaf, Sub), Tree (Tree))
 import Chiasma.Ui.Data.View (Tree (..), TreeSub (..), ViewTree, ViewTreeSub)
 import qualified Chiasma.Ui.Data.View as Ui (Layout (..), Pane (Pane), PaneView, View (View))
@@ -107,7 +101,7 @@
 ensureWindow sid (Tmux.View ident mayWid) newSessionWid tree = do
   preexisting <- join <$> traverse Cmd.window (newSessionWid <|> mayWid)
   window <- maybe (spawnWindow sid ident) pure preexisting
-  syncPrincipal (Codec.windowId window) tree
+  syncPrincipal ((.windowId) window) tree
   pure window
 
 findOrCreatePane ::
@@ -135,7 +129,7 @@
   Sem r Pane
 openPane dir windowId = do
   detail <- Cmd.splitWindowInDir dir windowId
-  viewsLogS $ "opened pane " <> show (Pane.paneId detail) <> " in window " <> show windowId
+  viewsLogS $ "opened pane " <> show ((.paneId) detail) <> " in window " <> show windowId
   pure detail
 
 ensurePaneOpen ::
@@ -170,7 +164,7 @@
   updatedPane <-
     if open then Just <$> ensurePaneOpen dir existingPane windowId
     else Nothing <$ ensurePaneClosed existingPane
-  atomicModify' $ Views.updatePane (Tmux.View paneIdent (Pane.paneId <$> updatedPane))
+  atomicModify' $ Views.updatePane (Tmux.View paneIdent ((.paneId) <$> updatedPane))
   pure $ cons <$> updatedPane
   where
     dir = fromMaybe cwd (parseAbsDir . toString =<< customDir)
@@ -226,5 +220,5 @@
   RenderableTree ->
   Sem r WindowState
 windowState windowIdent window tree = do
-  nativeRef <- Cmd.firstWindowPane (Codec.windowId window)
-  pure $ WindowState window nativeRef windowIdent tree (Codec.paneId nativeRef)
+  nativeRef <- Cmd.firstWindowPane window.windowId
+  pure $ WindowState window nativeRef windowIdent tree nativeRef.paneId
diff --git a/readme.md b/readme.md
new file mode 100644
--- /dev/null
+++ b/readme.md
@@ -0,0 +1,3 @@
+# Intro
+
+**Chiasma** is a [tmux](https://github.com/tmux/tmux) api client for [Haskell](https://www.haskell.org/).
