diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,11 @@
 This file covers only non-trivial user-visible changes;
 see the git log for full gory details.
 
+# 0.1.11
+* Drop targets of "log" from queues
+* Preserve history when using relative links (e.g. "2?foo")
+* Document backslash escapes in query
+
 # 0.1.10
 * Allow pre-fetched items in queue, with new "fetch" command to add them
 * Add named queues, e.g. foo~
diff --git a/Command.hs b/Command.hs
--- a/Command.hs
+++ b/Command.hs
@@ -447,7 +447,17 @@
             , "Unlike TARGET?QUERY, this command does not require spaces to be escaped,"
             , "and it can be aliased; e.g. if 'search is a mark set to a search engine:"
             , "  alias S 'search query"
-            , "  S ascii art cat" ]
+            , "  S ascii art cat"
+            , ""
+            , "The following backslash escape sequences will be interpreted"
+            , "(these can also be used with TARGET?QUERY by escaping the backslash):"
+            , "  \\n   : newline"
+            , "  \\r   : carriage return"
+            , "  \\e   : escape"
+            , "  \\t   : tab"
+            , "  \\xHH : byte with given hex encoding"
+            , "  \\\\   : backslash"
+            ]
         "repl" -> [ "TARGET {repl}: enter read-eval-print-loop,"
             , "in which each line of input is used as a query string at the target."
             , "To return to normal command mode, enter an empty query or ^C or ^D." ]
diff --git a/Makefile b/Makefile
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-VERSION=0.1.10
+VERSION=0.1.11
 
 GHCOPTS=-threaded -DICONV -DMAGIC -ignore-package regex-compat-tdfa
 
diff --git a/Marks.hs b/Marks.hs
--- a/Marks.hs
+++ b/Marks.hs
@@ -17,6 +17,7 @@
 import           Control.Exception  (handle)
 import           Control.Monad      (guard, msum)
 import           Data.Bifunctor     (second)
+import           Data.Char          (isAlphaNum)
 import           Data.Either        (partitionEithers)
 import           Data.List          (isPrefixOf)
 import           System.Directory
@@ -77,10 +78,14 @@
                     "Failed to decode uri in:" ++ show filepath)
                 (Right . (filename,)) . readUriWithId . TS.strip . TS.decodeUtf8 <$> BS.readFile filepath
 
+markNameValid :: String -> Bool
+markNameValid = all isAlphaNum
+
 saveMark :: FilePath -> String -> URIWithIdName -> IO ()
-saveMark path mark uriId =
+saveMark path mark uriId | markNameValid mark =
     let filepath = path </> mark
     in isSubPath path filepath >>? mkdirhierto filepath >> writeFile filepath (showUriWithId uriId)
+saveMark _ _ _ = pure ()
 
 marksWithUri :: URI -> Marks -> [(String,URIWithIdName)]
 marksWithUri uri = Map.toList . Map.filter ((==uri) . uriIdUri)
diff --git a/Pager.hs b/Pager.hs
--- a/Pager.hs
+++ b/Pager.hs
@@ -32,7 +32,7 @@
     | otherwise = execWriterT . printLinesPaged' perpage Nothing
     where
     printLinesPaged' :: Int -> Maybe Int -> [T.Text] -> WriterT [String] IO ()
-    printLinesPaged' _ mcol [] =
+    printLinesPaged' n mcol [] | n > 0 =
         when (isJust mcol) . liftIO $ putStrLn ""
     printLinesPaged' n mcol (l:ls) | n > 0 = do
         let physLines = (+ 1) . max 0 $ (visibleLength l - 1) `div` termWidth
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import           Distribution.Simple
+main = defaultMain
diff --git a/Version.hs b/Version.hs
--- a/Version.hs
+++ b/Version.hs
@@ -16,4 +16,4 @@
 programName = "diohsc"
 
 version :: String
-version = "0.1.10"
+version = "0.1.11"
diff --git a/diohsc.1.md b/diohsc.1.md
--- a/diohsc.1.md
+++ b/diohsc.1.md
@@ -39,7 +39,7 @@
 -p, \-\-prompt
 : Interactively read diohsc commands from stdin,
 : after any commands given as arguments have been executed.
-: This is the default unless "-e" or "-f" is used.
+: This is the default unless "-e" or "-f" or "-b" is used.
 
 -i, \-\-interact
 : When processing commands, prompt for further input where appropriate.
diff --git a/diohsc.cabal b/diohsc.cabal
--- a/diohsc.cabal
+++ b/diohsc.cabal
@@ -1,6 +1,6 @@
 cabal-version:      1.18
 name:               diohsc
-version:            0.1.10
+version:            0.1.11
 license:            GPL-3
 license-file:       COPYING
 maintainer:         mbays@sdf.org
@@ -84,7 +84,7 @@
         asn1-types >=0.3.4 && <0.4,
         bytestring >=0.10.4.0 && <0.12,
         containers >=0.5.5.1 && <0.7,
-        cryptonite >=0.26 && <0.30,
+        cryptonite >=0.26 && <0.31,
         data-default-class >=0.1.2.0 && <0.2,
         data-hash >=0.2.0.1 && <0.3,
         directory >=1.2.1.0 && <1.4,
@@ -94,8 +94,8 @@
         haskeline ==0.8.*,
         hourglass >=0.2.12 && <0.3,
         mime >=0.4.0.2 && <0.5,
-        mtl >=2.1.3.1 && <2.3,
-        memory >=0.14 && <0.17,
+        mtl >=2.1.3.1 && <2.4,
+        memory >=0.14 && <0.18,
         network >=2.4.2.3 && <3.2,
         network-simple >=0.4.3 && <0.5,
         network-uri >=2.6.3.0 && <2.8,
@@ -107,9 +107,9 @@
         safe >=0.3.19 && <0.4,
         temporary ==1.3.*,
         terminal-size >=0.3.2.1 && <0.4,
-        text >=1.1.0.0 && <1.3,
+        text >=1.1.0.0 && <2.1,
         tls >=1.5.4 && <1.6,
-        transformers >=0.3.0.0 && <0.6,
+        transformers >=0.3.0.0 && <0.7,
         x509 >=1.7.5 && <1.8,
         x509-store >=1.6.7 && <1.7,
         x509-validation >=1.6.11 && <1.7
diff --git a/diohsc.hs b/diohsc.hs
--- a/diohsc.hs
+++ b/diohsc.hs
@@ -238,7 +238,7 @@
         argCommands (OptCommand c) = return [c]
         argCommands _ = return []
     optCommands <- concat <$> mapM argCommands opts
-    let repl = null optCommands || Prompt `elem` opts
+    let repl = (null optCommands && Batch `notElem` opts) || Prompt `elem` opts
     let interactive = Batch `notElem` opts && (repl || Interactive `elem` opts)
 
     let argToUri arg = doesPathExist arg >>= \case
@@ -564,10 +564,11 @@
     marksDir = userDataDir </> "marks"
 
     setMark :: String -> URIWithIdName -> ClientM ()
-    setMark mark uriId = do
+    setMark mark uriId | markNameValid mark = do
         modify $ \s -> s { clientMarks = insertMark mark uriId $ clientMarks s }
         unless (mark `elem` tempMarks) . liftIO .
             handle printIOErr $ saveMark marksDir mark uriId
+    setMark mark _ = printErr $ "Invalid mark name " ++ mark
 
     promptInput = if ghost then promptLine else promptLineWithHistoryFile inputHistPath
         where inputHistPath = userDataDir </> "inputHistory"
@@ -688,6 +689,7 @@
                 where
                 relTarget (TargetHistory item) = TargetFrom (HistoryOrigin item Nothing) $
                     ref `relativeTo` historyUri item
+                relTarget (TargetFrom o uri) = TargetFrom o $ relativeTo ref uri
                 relTarget t = TargetUri . relativeTo ref $ targetUri t
 
     resolveTarget (PTargetAbs s) = case parseUriAsAbsolute . escapeIRI $ escapeQueryPart s of
@@ -719,7 +721,8 @@
         | interactive = do
         (height,width) <- liftIO getTermSize
         let pageWidth = min maxWrapWidth (width - 4)
-        queued <- liftIO $ printLinesPaged pageWidth width (height - 2) ls
+        let perPage = height - min 3 (height `div` 4)
+        queued <- liftIO $ printLinesPaged pageWidth width perPage ls
         modify $ \s -> s { clientQueuedCommands = clientQueuedCommands s ++ queued }
         | otherwise = liftIO $ mapM_ T.putStrLn ls
 
@@ -963,7 +966,7 @@
         handleUriCommand uri ("repl",_) = repl Nothing uri
         handleUriCommand uri ("query", CommandArg _ str : _) =
                     goUri True Nothing . setQuery ('?':escapeQuery str) $ uri
-        handleUriCommand uri ("log",_) = addToLog uri
+        handleUriCommand uri ("log",_) = addToLog uri >> dropUriFromQueues uri
 
         handleUriCommand _ (c,_) = printErr $ "Bad arguments to command " <> c
 
