diff --git a/.nix-helpers/nixpkgs.nix b/.nix-helpers/nixpkgs.nix
--- a/.nix-helpers/nixpkgs.nix
+++ b/.nix-helpers/nixpkgs.nix
@@ -20,9 +20,9 @@
     if isNull nixpkgs
       then
         builtins.fetchTarball {
-          # Recent version of nixpkgs-19.03 as of 2019-06-25.
-          url = "https://github.com/NixOS/nixpkgs/archive/8634c3b619909db7fc747faf8c03592986626e21.tar.gz";
-          sha256 = "sha256:0hcpy4q64vbqmlmnfcavfxilyygyzpwdsss8g3p73ikpic0j6ziq";
+          # Recent version of nixpkgs-19.09 as of 2019-09-16.
+          url = "https://github.com/NixOS/nixpkgs/archive/64e38f246aebc1fcd800952322c08f92d1420660.tar.gz";
+          sha256 = "sha256:16cjhck691f8dhb996rx0xvcwsqxrxs4lfajgqjnv0zfr8f76srm";
         }
       else nixpkgs;
 
diff --git a/.nix-helpers/stack-fhs-env.nix b/.nix-helpers/stack-fhs-env.nix
--- a/.nix-helpers/stack-fhs-env.nix
+++ b/.nix-helpers/stack-fhs-env.nix
@@ -13,12 +13,27 @@
 
 with (import ./nixpkgs.nix {});
 
+# stack needs to be version 1.9.3, because versions greater than two can't be
+# re-execed in a nix shell:
+#
+#https://github.com/commercialhaskell/stack/issues/5000
+
 let
+  nixpkgs-19-03-tarball = builtins.fetchTarball {
+    # Channel nixos-19.03 as of 2019/08/12.
+    url = "https://github.com/NixOS/nixpkgs/archive/56d94c8c69f8cac518027d191e2f8de678b56088.tar.gz";
+    sha256 = "1c812ssgmnmh97sarmp8jcykk0g57m8rsbfjg9ql9996ig6crsmi";
+  };
+
+  nixpkgs-19-03 = import nixpkgs-19-03-tarball {};
+
+  stack = nixpkgs-19-03.stack;
+
   fhsStack =
     buildFHSUserEnv {
       name = "stack";
       runScript = "stack";
-      targetPkgs = pkgs: with pkgs; [
+      targetPkgs = pkgs: (with pkgs; [
           binutils
           cairo
           cairo.dev
@@ -35,9 +50,11 @@
           pango
           pcre2
           pkgconfig
-          stack
+          # stack
           termonadKnownWorkingHaskellPkgSet.ghc
           zlib
+      ]) ++ [
+        stack
       ] ++
         stdenv.lib.optional
           (stdenv.hostPlatform.libc == "glibc")
diff --git a/.nix-helpers/stack-shell.nix b/.nix-helpers/stack-shell.nix
--- a/.nix-helpers/stack-shell.nix
+++ b/.nix-helpers/stack-shell.nix
@@ -14,7 +14,4 @@
     zlib
   ];
   ghc = termonadKnownWorkingHaskellPkgSet.ghc;
-  extraArgs = [
-    "--stack-yaml stack-lts-13.yaml"
-  ];
 }
diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 2.1.0.0
+
+* Add a menu option to set preferences for a running Termonad session.  The preferences you have set are lost when you end the Termonad session. [#130](https://github.com/cdepillabout/termonad/pull/130)  Thanks @jecaro!
+
 ## 2.0.0.0
 
 * Added menu option to search for a regex within the terminal output.
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -62,7 +62,7 @@
 First, you must install the required GTK system libraries:
 
 ```sh
-$ pacman -S vte3
+$ pacman -S vte3 gobject-introspection
 ```
 
 In order to install Termonad, clone this repository and run `stack install`.
@@ -79,7 +79,7 @@
 First, you must install the required GTK system libraries:
 
 ```sh
-$ apt-get install gobject-introspection libgirepository1.0-dev libgtk-3-dev libvte-2.91-dev
+$ apt-get install gobject-introspection libgirepository1.0-dev libgtk-3-dev libvte-2.91-dev libpcre2-dev
 ```
 
 In order to install Termonad, clone this repository and run `stack install`.
@@ -298,6 +298,12 @@
 
 There are other example configuration files in the
 [example-config/](./example-config) directory.
+
+If you want to test what all the colors look like, you may find it convenient
+to use the
+[`print-console-colors`](http://hackage.haskell.org/package/print-console-colors)
+package, which provides an executable called `print-console-colors` that prints
+all of the colors for your terminal.
 
 ### Compiling Local Settings
 
diff --git a/glade/README.md b/glade/README.md
new file mode 100644
--- /dev/null
+++ b/glade/README.md
@@ -0,0 +1,15 @@
+
+# Termonad Glade Files
+
+This directory contains [Glade](https://wiki.gnome.org/Apps/Glade) files used
+by Termonad to define how the GTK interfaces should look.
+
+Glade is an visual interface designer.  The Glade files are just XML files.
+They can be edited in the Glade program, or directly by hand.
+
+If you're new to Glade, you may be interested in going through a
+[tutorial](https://wiki.gnome.org/Apps/Glade/Tutorials).
+
+If you use the [shell.nix](../shell.nix) file, it should pull in `glade` for
+you, so you can just run it directly after entering into the Nix shell.  Or,
+you can just install `glade` through your package-manager-of-choice.
diff --git a/glade/preferences.glade b/glade/preferences.glade
new file mode 100644
--- /dev/null
+++ b/glade/preferences.glade
@@ -0,0 +1,271 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface>
+  <requires lib="gtk+" version="3.20"/>
+  <object class="GtkDialog" id="preferences">
+    <property name="can_focus">False</property>
+    <property name="title" translatable="yes">Termonad Preferences</property>
+    <property name="window_position">center-on-parent</property>
+    <property name="type_hint">dialog</property>
+    <child type="titlebar">
+      <placeholder/>
+    </child>
+    <child internal-child="vbox">
+      <object class="GtkBox">
+        <property name="can_focus">False</property>
+        <property name="margin_left">8</property>
+        <property name="margin_right">8</property>
+        <property name="margin_top">8</property>
+        <property name="margin_bottom">8</property>
+        <property name="hexpand">True</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">10</property>
+        <child internal-child="action_area">
+          <object class="GtkButtonBox">
+            <property name="can_focus">False</property>
+            <property name="layout_style">end</property>
+            <child>
+              <placeholder/>
+            </child>
+            <child>
+              <object class="GtkButton" id="ok">
+                <property name="label">gtk-ok</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_stock">True</property>
+              </object>
+              <packing>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkGrid">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="hexpand">True</property>
+            <property name="border_width">0</property>
+            <property name="row_spacing">6</property>
+            <property name="column_spacing">6</property>
+            <child>
+              <object class="GtkFontButton" id="font">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="tooltip_text" translatable="yes">Font to use in the terminal.</property>
+                <property name="hexpand">True</property>
+                <property name="vexpand">False</property>
+                <property name="font">Sans 12</property>
+                <property name="language">en-us</property>
+                <property name="preview_text"/>
+              </object>
+              <packing>
+                <property name="left_attach">1</property>
+                <property name="top_attach">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="halign">end</property>
+                <property name="label" translatable="yes">Font:</property>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkSpinButton" id="scrollbackLen">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="tooltip_text" translatable="yes">Number of lines to keep in the output of the terminal.</property>
+              </object>
+              <packing>
+                <property name="left_attach">1</property>
+                <property name="top_attach">2</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="halign">end</property>
+                <property name="label" translatable="yes">Scrollback length:</property>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">2</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkCheckButton" id="confirmExit">
+                <property name="label" translatable="yes">Confirm exit</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">False</property>
+                <property name="tooltip_text" translatable="yes">Whether or not to pop-up a dialog asking if you are sure you want to exit when you close a tab or exit out of Termonad.</property>
+                <property name="halign">center</property>
+                <property name="draw_indicator">True</property>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">3</property>
+                <property name="width">2</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="halign">end</property>
+                <property name="label" translatable="yes">Word char exceptions:</property>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">4</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkEntry" id="wordCharExceptions">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="tooltip_text" translatable="yes">When double-clicking on text in the terminal with the mouse, Termonad will use these characters to determine what to highlight.  Characters in this list will be counted as part of a word.  This makes it easy to highlight things like URLs or file paths.</property>
+              </object>
+              <packing>
+                <property name="left_attach">1</property>
+                <property name="top_attach">4</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkCheckButton" id="showMenu">
+                <property name="label" translatable="yes">Show menu</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">False</property>
+                <property name="tooltip_text" translatable="yes">Whether or not to show the menubar.  (This is the bar at the top that has the "File", "Edit", "View", etc buttons.)</property>
+                <property name="halign">center</property>
+                <property name="draw_indicator">True</property>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">5</property>
+                <property name="width">2</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="halign">end</property>
+                <property name="label" translatable="yes">Cursor blink mode:</property>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">7</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="halign">end</property>
+                <property name="label" translatable="yes">Show tabbar:</property>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">6</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="halign">end</property>
+                <property name="label" translatable="yes">Show scrollbar:</property>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkComboBoxText" id="showScrollbar">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="tooltip_text" translatable="yes">Whether or not to show a scrollbar on the terminal.  "If Needed" only shows the scrollbar if the text on the terminal goes off the screen.</property>
+              </object>
+              <packing>
+                <property name="left_attach">1</property>
+                <property name="top_attach">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkComboBoxText" id="showTabBar">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="tooltip_text" translatable="yes">Whether or not to show the tab bar.  "If Needed" only shows the tab bar when you have multiple tabs.</property>
+              </object>
+              <packing>
+                <property name="left_attach">1</property>
+                <property name="top_attach">6</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkComboBoxText" id="cursorBlinkMode">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="tooltip_text" translatable="yes">Set whether the cursor in the terminal should blink.  "System" sets this to the system-level GTK setting.</property>
+              </object>
+              <packing>
+                <property name="left_attach">1</property>
+                <property name="top_attach">7</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkLabel">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="margin_left">5</property>
+                <property name="margin_right">5</property>
+                <property name="margin_top">5</property>
+                <property name="margin_bottom">5</property>
+                <property name="label" translatable="yes">Warning: these settings will be used for current session only. To make them permanent, set them in ~/.config/termonad/termonad.hs</property>
+                <property name="justify">fill</property>
+                <property name="wrap">True</property>
+                <property name="max_width_chars">30</property>
+                <attributes>
+                  <attribute name="foreground" value="#ffff00000000"/>
+                </attributes>
+              </object>
+              <packing>
+                <property name="left_attach">0</property>
+                <property name="top_attach">8</property>
+                <property name="width">2</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
+            <property name="padding">3</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <action-widgets>
+      <action-widget response="-3">ok</action-widget>
+    </action-widgets>
+  </object>
+</interface>
diff --git a/shell.nix b/shell.nix
--- a/shell.nix
+++ b/shell.nix
@@ -35,11 +35,15 @@
   # Nix-shell environment for hacking on termonad.
   termonadEnv = haskPkgSet.termonad.env;
 
-  # Haskell build tools that are nice to have.  It is okay to get these from
-  # any Haskell package set, since they do not depend on the GHC version we are
-  # using.  We get these from the normal haskellPackages pkg set because then
-  # they don't have to be compiled from scratch.
-  nativeBuildTools = with haskellPackages; [ cabal-install ghcid ];
+  # Build tools that are nice to have.  It is okay to get Haskell build tools
+  # from any Haskell package set, since they do not depend on the GHC version
+  # we are using.  We get these from the normal haskellPackages pkg set because
+  # then they don't have to be compiled from scratch.
+  nativeBuildTools = [
+    cabal-install
+    gnome3.glade
+    haskellPackages.ghcid
+  ];
 in
 
 if indexTermonad
diff --git a/src/Termonad/App.hs b/src/Termonad/App.hs
--- a/src/Termonad/App.hs
+++ b/src/Termonad/App.hs
@@ -5,7 +5,7 @@
 import Termonad.Prelude
 
 import Config.Dyre (defaultParams, projectName, realMain, showError, wrapMain)
-import Control.Lens ((&), (.~), (^.), (^..))
+import Control.Lens ((&), (.~), (^.), (^..), over, set)
 import Data.FocusList (focusList, moveFromToFL, updateFocusFL)
 import Data.Sequence (findIndexR)
 import GI.Gdk (castTo, managedForeignPtr, screenGetDefault)
@@ -24,18 +24,30 @@
   ( Application
   , ApplicationWindow(ApplicationWindow)
   , Box(Box)
+  , CheckButton(CheckButton)
+  , ComboBoxText(ComboBoxText)
+  , Dialog(Dialog)
+  , Entry(Entry)
+  , FontButton(FontButton)
+  , PolicyType(PolicyTypeAutomatic)
   , PositionType(PositionTypeRight)
-  , ResponseType(ResponseTypeNo, ResponseTypeYes)
+  , ResponseType(ResponseTypeAccept, ResponseTypeNo, ResponseTypeYes)
   , ScrolledWindow(ScrolledWindow)
+  , SpinButton(SpinButton)
   , pattern STYLE_PROVIDER_PRIORITY_APPLICATION
   , aboutDialogNew
+  , adjustmentNew
   , applicationAddWindow
   , applicationGetActiveWindow
   , applicationSetAccelsForAction
   , applicationSetMenubar
+  , applicationWindowSetShowMenubar
   , boxPackStart
   , builderNewFromString
   , builderSetApplication
+  , comboBoxGetActiveId
+  , comboBoxSetActiveId
+  , comboBoxTextAppend
   , containerAdd
   , cssProviderLoadFromData
   , cssProviderNew
@@ -44,8 +56,13 @@
   , dialogNew
   , dialogResponse
   , dialogRun
+  , entryBufferGetText
+  , entryBufferSetText
   , entryGetText
   , entryNew
+  , fontChooserSetFontDesc
+  , fontChooserGetFontDesc
+  , getEntryBuffer
   , gridAttachNextTo
   , gridNew
   , labelNew
@@ -56,8 +73,14 @@
   , onNotebookPageReordered
   , onNotebookSwitchPage
   , onWidgetDeleteEvent
+  , scrolledWindowSetPolicy
   , setWidgetMargin
+  , spinButtonGetValueAsInt
+  , spinButtonSetAdjustment
+  , spinButtonSetValue
   , styleContextAddProviderForScreen
+  , toggleButtonGetActive
+  , toggleButtonSetActive
   , widgetDestroy
   , widgetGrabFocus
   , widgetSetCanFocus
@@ -72,6 +95,7 @@
 import GI.Pango
   ( FontDescription
   , pattern SCALE
+  , fontDescriptionGetFamily
   , fontDescriptionGetSize
   , fontDescriptionGetSizeIsAbsolute
   , fontDescriptionNew
@@ -80,7 +104,8 @@
   , fontDescriptionSetAbsoluteSize
   )
 import GI.Vte
-  ( catchRegexError
+  ( CursorBlinkMode(..)
+  , catchRegexError
   , regexNewForSearch
   , terminalCopyClipboard
   , terminalPasteClipboard
@@ -88,7 +113,10 @@
   , terminalSearchFindPrevious
   , terminalSearchSetRegex
   , terminalSearchSetWrapAround
+  , terminalSetCursorBlinkMode
   , terminalSetFont
+  , terminalSetScrollbackLines
+  , terminalSetWordCharExceptions
   )
 
 import Paths_termonad (getDataFileName)
@@ -96,21 +124,37 @@
 import Termonad.Keys (handleKeyPress)
 import Termonad.Lenses
   ( lensConfirmExit
+  , lensCursorBlinkMode
   , lensFontConfig
   , lensOptions
   , lensShowMenu
-  , lensTMNotebookTabTerm
+  , lensShowScrollbar
+  , lensShowTabBar
+  , lensScrollbackLen
+  , lensTMNotebook
+  , lensTMNotebookTabTermContainer
   , lensTMNotebookTabs
+  , lensTMNotebookTabTerm
   , lensTMStateApp
+  , lensTMStateAppWin
   , lensTMStateConfig
   , lensTMStateFontDesc
   , lensTMStateNotebook
   , lensTerm
+  , lensWordCharExceptions
   )
-import Termonad.Term (createTerm, relabelTabs, termExitFocused, setShowTabs)
+import Termonad.Term
+  ( createTerm
+  , relabelTabs
+  , termExitFocused
+  , setShowTabs
+  , showScrollbarToPolicy
+  )
 import Termonad.Types
-  ( FontConfig(fontFamily, fontSize)
+  ( FontConfig(..)
   , FontSize(FontSizePoints, FontSizeUnits)
+  , ShowScrollbar(..)
+  , ShowTabBar(..)
   , TMConfig
   , TMNotebookTab
   , TMState
@@ -123,7 +167,7 @@
   , tmStateApp
   , tmStateNotebook
   )
-import Termonad.XML (interfaceText, menuText)
+import Termonad.XML (interfaceText, menuText, preferencesText)
 
 setupScreenStyle :: IO ()
 setupScreenStyle = do
@@ -189,14 +233,7 @@
 
 adjustFontDescSize :: (FontSize -> FontSize) -> FontDescription -> IO ()
 adjustFontDescSize f fontDesc = do
-  currSize <- fontDescriptionGetSize fontDesc
-  currAbsolute <- fontDescriptionGetSizeIsAbsolute fontDesc
-  let currFontSz =
-        if currAbsolute
-          then FontSizeUnits $ fromIntegral currSize / fromIntegral SCALE
-          else
-            let fontRatio :: Double = fromIntegral currSize / fromIntegral SCALE
-            in FontSizePoints $ round fontRatio
+  currFontSz <- fontSizeFromFontDescription fontDesc
   let newFontSz = f currFontSz
   setFontDescSize fontDesc newFontSz
 
@@ -214,6 +251,22 @@
           lensTerm
   foldMap (\vteTerm -> terminalSetFont vteTerm (Just fontDesc)) terms
 
+fontSizeFromFontDescription :: FontDescription -> IO FontSize
+fontSizeFromFontDescription fontDesc = do
+  currSize <- fontDescriptionGetSize fontDesc
+  currAbsolute <- fontDescriptionGetSizeIsAbsolute fontDesc
+  return $ if currAbsolute
+             then FontSizeUnits $ fromIntegral currSize / fromIntegral SCALE
+             else
+               let fontRatio :: Double = fromIntegral currSize / fromIntegral SCALE
+               in FontSizePoints $ round fontRatio
+
+fontConfigFromFontDescription :: FontDescription -> IO (Maybe FontConfig)
+fontConfigFromFontDescription fontDescription = do
+  fontSize <- fontSizeFromFontDescription fontDescription
+  maybeFontFamily <- fontDescriptionGetFamily fontDescription
+  return $ (`FontConfig` fontSize) <$> maybeFontFamily
+
 compareScrolledWinAndTab :: ScrolledWindow -> TMNotebookTab -> Bool
 compareScrolledWinAndTab scrollWin flTab =
   let ScrolledWindow managedPtrFLTab = tmNotebookTabTermContainer flTab
@@ -391,6 +444,10 @@
   actionMapAddAction app pasteAction
   applicationSetAccelsForAction app "app.paste" ["<Shift><Ctrl>V"]
 
+  preferencesAction <- simpleActionNew "preferences" Nothing
+  void $ onSimpleActionActivate preferencesAction (const $ showPreferencesDialog mvarTMState)
+  actionMapAddAction app preferencesAction
+
   enlargeFontAction <- simpleActionNew "enlargefont" Nothing
   void $ onSimpleActionActivate enlargeFontAction $ \_ ->
     modifyFontSizeForAllTerms (modFontSize 1) mvarTMState
@@ -422,10 +479,11 @@
   void $ onSimpleActionActivate aboutAction $ \_ -> showAboutDialog app
   actionMapAddAction app aboutAction
 
-  when (tmConfig ^. lensOptions . lensShowMenu) $ do
-    menuBuilder <- builderNewFromString menuText $ fromIntegral (length menuText)
-    menuModel <- objFromBuildUnsafe menuBuilder "menubar" MenuModel
-    applicationSetMenubar app (Just menuModel)
+  menuBuilder <- builderNewFromString menuText $ fromIntegral (length menuText)
+  menuModel <- objFromBuildUnsafe menuBuilder "menubar" MenuModel
+  applicationSetMenubar app (Just menuModel)
+  let showMenu = tmConfig ^. lensOptions . lensShowMenu
+  applicationWindowSetShowMenubar win showMenu
 
   windowSetTitle win "Termonad"
 
@@ -580,6 +638,181 @@
       _matchFound <- terminalSearchFindNext terminal
       -- putStrLn $ "was match found: " <> tshow matchFound
       pure ()
+
+setShowMenuBar :: Application -> Bool -> IO ()
+setShowMenuBar app visible = do
+  void $ runMaybeT $ do
+    win <- MaybeT $ applicationGetActiveWindow app
+    appWin <- MaybeT $ castTo ApplicationWindow win
+    lift $ applicationWindowSetShowMenubar appWin visible
+
+-- | Fill a combo box with ids and labels
+--
+-- The ids are stored in the combobox as 'Text', so their type should be an
+-- instance of the 'Show' type class.
+comboBoxFill :: forall a. Show a => ComboBoxText -> [(a, Text)] -> IO ()
+comboBoxFill comboBox = mapM_ go
+  where
+    go :: (a, Text) -> IO ()
+    go (value, textId) =
+      comboBoxTextAppend comboBox (Just $ tshow value) textId
+
+-- | Set the current active item in a combobox given an input id.
+comboBoxSetActive :: Show a => ComboBoxText -> a -> IO ()
+comboBoxSetActive cb item = void $ comboBoxSetActiveId cb (Just $ tshow item)
+
+-- | Get the current active item in a combobox
+--
+-- The list of values to be searched in the combobox must be given as a
+-- parameter. These values are converted to Text then compared to the current
+-- id.
+comboBoxGetActive
+  :: forall a. (Show a, Enum a) => ComboBoxText -> [a] -> IO (Maybe a)
+comboBoxGetActive cb values = findEnumFromMaybeId <$> comboBoxGetActiveId cb
+  where
+    findEnumFromMaybeId :: Maybe Text -> Maybe a
+    findEnumFromMaybeId maybeId = maybeId >>= findEnumFromId
+
+    findEnumFromId :: Text -> Maybe a
+    findEnumFromId label = find (\x -> tshow x == label) values
+
+applyNewPreferences :: TMState -> IO ()
+applyNewPreferences mvarTMState = do
+  tmState <- readMVar mvarTMState
+  let appWin = tmState ^. lensTMStateAppWin
+      config = tmState ^. lensTMStateConfig
+      notebook = tmState ^. lensTMStateNotebook ^. lensTMNotebook
+      tabFocusList = tmState ^. lensTMStateNotebook ^. lensTMNotebookTabs
+      showMenu = config  ^. lensOptions ^. lensShowMenu
+  applicationWindowSetShowMenubar appWin showMenu
+  setShowTabs config notebook
+  -- Sets the remaining preferences to each tab
+  foldMap (applyNewPreferencesToTab mvarTMState) tabFocusList
+
+applyNewPreferencesToTab :: TMState -> TMNotebookTab -> IO ()
+applyNewPreferencesToTab mvarTMState tab = do
+  tmState <- readMVar mvarTMState
+  let fontDesc = tmState ^. lensTMStateFontDesc
+      term = tab ^. lensTMNotebookTabTerm ^. lensTerm
+      scrolledWin = tab ^. lensTMNotebookTabTermContainer
+      options = tmState ^. lensTMStateConfig ^. lensOptions
+  terminalSetFont term (Just fontDesc)
+  terminalSetCursorBlinkMode term (options ^. lensCursorBlinkMode)
+  terminalSetWordCharExceptions term (options ^. lensWordCharExceptions)
+  terminalSetScrollbackLines term (fromIntegral (options ^. lensScrollbackLen))
+  let vScrollbarPolicy = showScrollbarToPolicy (options ^. lensShowScrollbar)
+  scrolledWindowSetPolicy scrolledWin PolicyTypeAutomatic vScrollbarPolicy
+
+-- | Show the preferences dialog.
+--
+-- When the user clicks on the Ok button, it copies the new settings to TMState.
+-- Then apply them to the current terminals.
+showPreferencesDialog :: TMState -> IO ()
+showPreferencesDialog mvarTMState = do
+  -- Get app out of mvar
+  tmState <- readMVar mvarTMState
+  let app = tmState ^. lensTMStateApp
+
+  -- Create the preference dialog and get some widgets
+  preferencesBuilder <-
+    builderNewFromString preferencesText $ fromIntegral (length preferencesText)
+  preferencesDialog <-
+    objFromBuildUnsafe preferencesBuilder "preferences" Dialog
+  confirmExitCheckButton <-
+    objFromBuildUnsafe preferencesBuilder "confirmExit" CheckButton
+  showMenuCheckButton <-
+    objFromBuildUnsafe preferencesBuilder "showMenu" CheckButton
+  wordCharExceptionsEntryBuffer <-
+    objFromBuildUnsafe preferencesBuilder "wordCharExceptions" Entry >>=
+      getEntryBuffer
+  fontButton <- objFromBuildUnsafe preferencesBuilder "font" FontButton
+  showScrollbarComboBoxText <-
+    objFromBuildUnsafe preferencesBuilder "showScrollbar" ComboBoxText
+  comboBoxFill
+    showScrollbarComboBoxText
+    [ (ShowScrollbarNever, "Never")
+    , (ShowScrollbarAlways, "Always")
+    , (ShowScrollbarIfNeeded, "If needed")
+    ]
+  showTabBarComboBoxText <-
+    objFromBuildUnsafe preferencesBuilder "showTabBar" ComboBoxText
+  comboBoxFill
+    showTabBarComboBoxText
+    [ (ShowTabBarNever, "Never")
+    , (ShowTabBarAlways, "Always")
+    , (ShowTabBarIfNeeded, "If needed")
+    ]
+  cursorBlinkModeComboBoxText <-
+    objFromBuildUnsafe preferencesBuilder "cursorBlinkMode" ComboBoxText
+  comboBoxFill
+    cursorBlinkModeComboBoxText
+    [ (CursorBlinkModeSystem, "System")
+    , (CursorBlinkModeOn, "On")
+    , (CursorBlinkModeOff, "Off")
+    ]
+  scrollbackLenSpinButton <-
+    objFromBuildUnsafe preferencesBuilder "scrollbackLen" SpinButton
+  adjustmentNew 0 0 (fromIntegral (maxBound :: Int)) 1 10 0 >>=
+    spinButtonSetAdjustment scrollbackLenSpinButton
+
+  -- Make the dialog modal
+  maybeWin <- applicationGetActiveWindow app
+  windowSetTransientFor preferencesDialog maybeWin
+
+  -- Init with current state
+  fontChooserSetFontDesc fontButton (tmState ^. lensTMStateFontDesc)
+  let options = tmState ^. lensTMStateConfig . lensOptions
+  comboBoxSetActive showScrollbarComboBoxText $ options ^. lensShowScrollbar
+  comboBoxSetActive showTabBarComboBoxText $ options ^. lensShowTabBar
+  comboBoxSetActive cursorBlinkModeComboBoxText $ options ^. lensCursorBlinkMode
+  spinButtonSetValue
+    scrollbackLenSpinButton
+    (fromIntegral $ options ^. lensScrollbackLen)
+  toggleButtonSetActive confirmExitCheckButton $ options ^. lensConfirmExit
+  toggleButtonSetActive showMenuCheckButton $ options ^. lensShowMenu
+  entryBufferSetText
+    wordCharExceptionsEntryBuffer
+    (options ^. lensWordCharExceptions)
+    (-1)
+
+  -- Run dialog then close
+  res <- dialogRun preferencesDialog
+
+  -- When closing the dialog get the new settings
+  when (toEnum (fromIntegral res) == ResponseTypeAccept) $ do
+    maybeFontDesc <- fontChooserGetFontDesc fontButton
+    maybeFontConfig <-
+      liftM join $ mapM fontConfigFromFontDescription maybeFontDesc
+    maybeShowScrollbar <-
+      comboBoxGetActive showScrollbarComboBoxText [ShowScrollbarNever ..]
+    maybeShowTabBar <-
+      comboBoxGetActive showTabBarComboBoxText [ShowTabBarNever ..]
+    maybeCursorBlinkMode <-
+      comboBoxGetActive cursorBlinkModeComboBoxText [CursorBlinkModeSystem ..]
+    scrollbackLen <-
+      fromIntegral <$> spinButtonGetValueAsInt scrollbackLenSpinButton
+    confirmExit <- toggleButtonGetActive confirmExitCheckButton
+    showMenu <- toggleButtonGetActive showMenuCheckButton
+    wordCharExceptions <- entryBufferGetText wordCharExceptionsEntryBuffer
+
+    -- Apply the changes to mvarTMState
+    modifyMVar_ mvarTMState $ pure
+      . over lensTMStateFontDesc (`fromMaybe` maybeFontDesc)
+      . over (lensTMStateConfig . lensOptions)
+        ( set lensConfirmExit confirmExit
+        . set lensShowMenu showMenu
+        . set lensWordCharExceptions wordCharExceptions
+        . over lensFontConfig (`fromMaybe` maybeFontConfig)
+        . set lensScrollbackLen scrollbackLen
+        . over lensShowScrollbar (`fromMaybe` maybeShowScrollbar)
+        . over lensShowTabBar (`fromMaybe` maybeShowTabBar)
+        . over lensCursorBlinkMode (`fromMaybe` maybeCursorBlinkMode)
+        )
+
+    -- Update the app with new settings
+    applyNewPreferences mvarTMState
+
+  widgetDestroy preferencesDialog
 
 appStartup :: Application -> IO ()
 appStartup _app = pure ()
diff --git a/src/Termonad/Config/Colour.hs b/src/Termonad/Config/Colour.hs
--- a/src/Termonad/Config/Colour.hs
+++ b/src/Termonad/Config/Colour.hs
@@ -12,7 +12,14 @@
 -- import this module. Create a new 'ColourExtension' with the 'createColourExtension' function.
 -- Then add the 'ColourExtension' to your 'TMConfig' with the 'addColourExtension' function.
 --
--- See <https://github.com/cdepillabout/termonad/blob/master/example-config/ExampleColourExtension.hs this code> for a simple example.
+-- See
+-- <https://github.com/cdepillabout/termonad/blob/master/example-config/ExampleColourExtension.hs this code>
+-- for a simple example.
+--
+-- When setting colors, you may find it convenient to use the
+-- <http://hackage.haskell.org/package/print-console-colors print-console-colors>
+-- package, which provides an executable called @print-console-colors@ that prints
+-- all of the colors for your terminal.
 
 module Termonad.Config.Colour
   ( -- * Colour Config
@@ -199,7 +206,6 @@
 defaultLightColours :: (Ord b, Floating b) => Vec N8 (AlphaColour b)
 defaultLightColours = coloursFromBits 192 63
 
-
 -- | Convert an 'AlphaColour' to a 'Colour'.
 --
 -- >>> sRGB24show $ pureColour (opaque green)
@@ -534,7 +540,7 @@
     -- ^ Background color of the cursor.  This is the color of the cursor
     -- itself.
   , foregroundColour :: !(Option c)
-    -- ^ Color of the default default foreground text in the terminal.
+    -- ^ Color of the default foreground text in the terminal.
   , backgroundColour :: !(Option c)
     -- ^ Background color for the terminal
   , palette :: !(Palette c)
diff --git a/src/Termonad/Prelude.hs b/src/Termonad/Prelude.hs
--- a/src/Termonad/Prelude.hs
+++ b/src/Termonad/Prelude.hs
@@ -5,6 +5,7 @@
   ) where
 
 import Control.Lens as X ((&))
+import Control.Monad.Trans.Maybe as X (MaybeT(MaybeT), runMaybeT)
 import ClassyPrelude as X
 import Data.Proxy as X
 import qualified Data.Text.IO as TextIO
diff --git a/src/Termonad/Types.hs b/src/Termonad/Types.hs
--- a/src/Termonad/Types.hs
+++ b/src/Termonad/Types.hs
@@ -347,7 +347,7 @@
                         -- needed.
   | ShowScrollbarIfNeeded -- ^ Only show the scrollbar if there are too many
                           -- lines on the terminal to show all at once.
-  deriving (Eq, Show)
+  deriving (Enum, Eq, Show)
 
 -- | Whether or not to show the tab bar for switching tabs.
 data ShowTabBar
@@ -355,7 +355,7 @@
                     -- open.  This may be confusing if you plan on using multiple tabs.
   | ShowTabBarAlways -- ^ Always show the tab bar, even if you only have one tab open.
   | ShowTabBarIfNeeded  -- ^ Only show the tab bar if you have multiple tabs open.
-  deriving (Eq, Show)
+  deriving (Enum, Eq, Show)
 
 -- | Configuration options for Termonad.
 --
diff --git a/src/Termonad/XML.hs b/src/Termonad/XML.hs
--- a/src/Termonad/XML.hs
+++ b/src/Termonad/XML.hs
@@ -1,10 +1,12 @@
 {-# LANGUAGE QuasiQuotes #-}
+{-# LANGUAGE TemplateHaskell #-}
 
 module Termonad.XML where
 
 import Termonad.Prelude
 
 import Data.Default (def)
+import Data.FileEmbed (embedFile)
 import Text.XML (renderText)
 import Text.XML.QQ (Document, xmlRaw)
 
@@ -78,6 +80,10 @@
             <attribute name="label" translatable="yes">_Paste</attribute>
             <attribute name="action">app.paste</attribute>
           </item>
+          <item>
+            <attribute name="label" translatable="yes">_Preferences</attribute>
+            <attribute name="action">app.preferences</attribute>
+          </item>
         </submenu>
         <submenu>
           <attribute name="label" translatable="yes">View</attribute>
@@ -253,3 +259,6 @@
 
 closeTabText :: Text
 closeTabText = toStrict $ renderText def closeTabDoc
+
+preferencesText :: Text
+preferencesText = decodeUtf8 $(embedFile "glade/preferences.glade")
diff --git a/termonad.cabal b/termonad.cabal
--- a/termonad.cabal
+++ b/termonad.cabal
@@ -1,5 +1,5 @@
 name:                termonad
-version:             2.0.0.0
+version:             2.1.0.0
 synopsis:            Terminal emulator configurable in Haskell
 description:         Please see <https://github.com/cdepillabout/termonad#readme README.md>.
 homepage:            https://github.com/cdepillabout/termonad
@@ -14,6 +14,8 @@
 extra-source-files:  README.md
                    , CHANGELOG.md
                    , default.nix
+                   , glade/preferences.glade
+                   , glade/README.md
                    , img/termonad.png
                    , .nix-helpers/nixops.nix
                    , .nix-helpers/nixpkgs.nix
@@ -62,6 +64,7 @@
                      , directory >= 1.3.1.0
                      , distributive
                      , dyre
+                     , file-embed
                      , filepath
                      , focuslist
                      , gi-gdk
@@ -78,6 +81,7 @@
                      , QuickCheck
                      , singletons
                      , text
+                     , transformers
                      , xml-conduit
                      , xml-html-qq
   default-language:    Haskell2010
diff --git a/test/readme/README.lhs b/test/readme/README.lhs
--- a/test/readme/README.lhs
+++ b/test/readme/README.lhs
@@ -62,7 +62,7 @@
 First, you must install the required GTK system libraries:
 
 ```sh
-$ pacman -S vte3
+$ pacman -S vte3 gobject-introspection
 ```
 
 In order to install Termonad, clone this repository and run `stack install`.
@@ -79,7 +79,7 @@
 First, you must install the required GTK system libraries:
 
 ```sh
-$ apt-get install gobject-introspection libgirepository1.0-dev libgtk-3-dev libvte-2.91-dev
+$ apt-get install gobject-introspection libgirepository1.0-dev libgtk-3-dev libvte-2.91-dev libpcre2-dev
 ```
 
 In order to install Termonad, clone this repository and run `stack install`.
@@ -298,6 +298,12 @@
 
 There are other example configuration files in the
 [example-config/](./example-config) directory.
+
+If you want to test what all the colors look like, you may find it convenient
+to use the
+[`print-console-colors`](http://hackage.haskell.org/package/print-console-colors)
+package, which provides an executable called `print-console-colors` that prints
+all of the colors for your terminal.
 
 ### Compiling Local Settings
 
