diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,10 @@
 # Changelog for [hledger-flow](https://github.com/apauley/hledger-flow)
 
+## 0.11.3
+
+- Detect the hledger-flow base directory correctly, even when in a subdirectory. Similar to how git behaves.
+- Change the version subcommand into a flag - thanks to [jecaro](https://github.com/apauley/hledger-flow/pull/38) for the contribution.
+
 ## 0.11.2
 
 - Improved display of external process output
diff --git a/README.org b/README.org
--- a/README.org
+++ b/README.org
@@ -129,7 +129,7 @@
 You can see the example imported financial transactions as it was
 generated by the step-by-step instructions here:
 
-[[https://github.com/apauley/hledger-flow-example-finances][https://github.com/apauley/hledger-flow-example-finances]]
+[[https://github.com/apauley/hledger-flow-example][https://github.com/apauley/hledger-flow-example]]
 
 * After Cloning This Repository
   :PROPERTIES:
diff --git a/app/Main.hs b/app/Main.hs
--- a/app/Main.hs
+++ b/app/Main.hs
@@ -21,19 +21,19 @@
                                          , sequential :: Bool
                                          }
                       deriving (Show)
-data Command = Version (Maybe Text) | Import SubcommandParams | Report SubcommandParams deriving (Show)
+data Command = Version | Import SubcommandParams | Report SubcommandParams deriving (Show)
 
 main :: IO ()
 main = do
   cmd <- options "An hledger workflow focusing on automated statement import and classification:\nhttps://github.com/apauley/hledger-flow#readme" parser
   case cmd of
-    Version _        -> stdout $ select versionInfo
+    Version          -> stdout $ select versionInfo
     Import subParams -> toImportOptions subParams >>= importCSVs
     Report subParams -> toReportOptions subParams >>= generateReports
 
 toImportOptions :: SubcommandParams -> IO IT.ImportOptions
 toImportOptions params = do
-  bd <- dirOrPwd $ maybeBaseDir params
+  bd <- determineBaseDir $ maybeBaseDir params
   hli <- hledgerInfoFromPath $ hledgerPathOpt params
   return IT.ImportOptions { IT.baseDir = bd
                           , IT.hledgerInfo = hli
@@ -43,7 +43,7 @@
 
 toReportOptions :: SubcommandParams -> IO RT.ReportOptions
 toReportOptions params = do
-  bd <- dirOrPwd $ maybeBaseDir params
+  bd <- determineBaseDir $ maybeBaseDir params
   hli <- hledgerInfoFromPath $ hledgerPathOpt params
   return RT.ReportOptions { RT.baseDir = bd
                           , RT.hledgerInfo = hli
@@ -54,7 +54,7 @@
 parser :: Parser Command
 parser = fmap Import (subcommand "import" "Converts CSV transactions into categorised journal files" subcommandParser)
   <|> fmap Report (subcommand "report" "Generate Reports" subcommandParser)
-  <|> fmap Version (subcommand "version" "Display version information" noArgs)
+  <|> flag' Version (long "version" <> short 'V' <> help "Display version information")
 
 subcommandParser :: Parser SubcommandParams
 subcommandParser = SubcommandParams
@@ -63,6 +63,3 @@
   <*> switch (long "verbose" <> short 'v' <> help "Print more verbose output")
   <*> switch (long "show-options" <> help "Print the options this program will run with")
   <*> switch (long "sequential" <> help "Disable parallel processing")
-
-noArgs :: Parser (Maybe Text)
-noArgs = optional (argText "" "")
diff --git a/hledger-flow.cabal b/hledger-flow.cabal
--- a/hledger-flow.cabal
+++ b/hledger-flow.cabal
@@ -4,10 +4,10 @@
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: 4192698e971b03566fe89299093f48fdb43d3a26f65a2ac17592ae7a294868c4
+-- hash: 2a75e18a525c30319738a863343f42c79804c552261cad30da8b396adcdab18b
 
 name:           hledger-flow
-version:        0.11.2.0
+version:        0.11.3.0
 synopsis:       An hledger workflow focusing on automated statement import and classification.
 description:    Please see the README on GitHub at <https://github.com/apauley/hledger-flow#readme>
 category:       Finance, Console
@@ -70,6 +70,7 @@
   type: exitcode-stdio-1.0
   main-is: Spec.hs
   other-modules:
+      Common.Integration
       Common.Unit
       CSVImport.Integration
       CSVImport.Unit
diff --git a/src/Hledger/Flow/Common.hs b/src/Hledger/Flow/Common.hs
--- a/src/Hledger/Flow/Common.hs
+++ b/src/Hledger/Flow/Common.hs
@@ -1,49 +1,6 @@
 {-# LANGUAGE OverloadedStrings #-}
 
-module Hledger.Flow.Common
-    ( docURL
-    , versionInfo
-    , hledgerPathFromOption
-    , hledgerVersionFromPath
-    , hledgerInfoFromPath
-    , showCmdArgs
-    , consoleChannelLoop
-    , terminateChannelLoop
-    , dummyLogger
-    , channelOut, channelOutLn
-    , channelErr, channelErrLn
-    , errExit
-    , logVerbose
-    , timeAndExitOnErr, timeAndExitOnErr'
-    , parAwareProc
-    , inprocWithErrFun
-    , verboseTestFile
-    , relativeToBase
-    , relativeToBase'
-    , lsDirs
-    , onlyFiles
-    , onlyDirs
-    , filterPaths
-    , changePathAndExtension
-    , basenameLine
-    , buildFilename
-    , shellToList
-    , firstExistingFile
-    , groupValuesBy
-    , groupIncludeFiles
-    , allYearIncludeFiles
-    , yearsIncludeMap
-    , extraIncludesForFile
-    , groupPairs
-    , pairBy
-    , includePreamble
-    , toIncludeFiles
-    , toIncludeLine
-    , groupAndWriteIncludeFiles
-    , writeIncludesUpTo
-    , dirOrPwd
-    , extractImportDirs
-    ) where
+module Hledger.Flow.Common where
 
 import Turtle
 import Prelude hiding (FilePath, putStrLn)
@@ -434,6 +391,35 @@
 changeOutputPath :: FilePath -> FilePath -> FilePath
 changeOutputPath newOutputLocation srcFile = mconcat $ map changeSrcDir $ splitDirectories srcFile
   where changeSrcDir file = if (file == "1-in/" || file == "2-preprocessed/") then newOutputLocation else file
+
+errorMessageBaseDir :: FilePath -> Text
+errorMessageBaseDir startDir = format ("Unable to find an hledger-flow import directory at '"%fp
+                                       %"' (or in any of its parent directories).\n\n"
+                                       %"Have a look at the documentation for more information:\n"%s)
+                               startDir (docURL "input-files")
+
+determineBaseDir :: Maybe FilePath -> IO FilePath
+determineBaseDir (Just suppliedDir) = determineBaseDir' suppliedDir
+determineBaseDir Nothing = pwd >>= determineBaseDir'
+
+determineBaseDir' :: FilePath -> IO FilePath
+determineBaseDir' startDir = do
+  ee <- determineBaseDir'' startDir startDir
+  case ee of
+    Right bd -> return bd
+    Left  t  -> die t
+
+determineBaseDir'' :: FilePath -> FilePath -> IO (Either Text FilePath)
+determineBaseDir'' startDir currentDir = do
+  foundBaseDir <- testdir $ currentDir </> "import"
+  if foundBaseDir
+    then return $ Right $ forceTrailingSlash currentDir
+    else
+    do
+      let doneSearching = (currentDir `elem` ["/", "./"])
+      if doneSearching
+        then return $ Left $ errorMessageBaseDir startDir
+        else determineBaseDir'' startDir $ parent currentDir
 
 dirOrPwd :: Maybe FilePath -> IO FilePath
 dirOrPwd maybeBaseDir = fmap forceTrailingSlash (fromMaybe pwd $ fmap realpath maybeBaseDir)
diff --git a/test/CSVImport/Integration.hs b/test/CSVImport/Integration.hs
--- a/test/CSVImport/Integration.hs
+++ b/test/CSVImport/Integration.hs
@@ -16,60 +16,6 @@
 import Hledger.Flow.Common
 import Control.Concurrent.STM
 
-testHiddenFiles = TestCase (
-  sh (
-      do
-        tmpdir <- using (mktempdir "." "hlflow")
-        let tmpJournals = map (tmpdir </>) journalFiles :: [FilePath]
-        let tmpExtras = map (tmpdir </>) extraFiles :: [FilePath]
-        let tmpHidden = map (tmpdir </>) hiddenFiles :: [FilePath]
-        let onDisk = List.sort $ tmpJournals ++ tmpExtras ++ tmpHidden
-        touchAll onDisk
-        filtered <- (fmap List.sort) $ shellToList $ onlyFiles $ select onDisk
-        let expected = List.sort $ tmpExtras ++ tmpJournals
-        liftIO $ assertEqual "Hidden files should be excluded" expected filtered
-     )
-  )
-
-testDirOrPwd = TestCase (
-  sh (
-      do
-        currentDir <- fmap (\p -> directory (p </> "t")) pwd
-        tmpdir <- using (mktempdir "." "hlflow")
-        let fooDir = collapse $ currentDir </> tmpdir </> "foo/"
-        let barDir = collapse $ currentDir </> tmpdir </> "bar/"
-        mkdir fooDir
-        mkdir barDir
-        d1 <- liftIO $ dirOrPwd Nothing
-        liftIO $ assertEqual "dirOrPwd returns pwd as a fallback" currentDir d1
-        liftIO $ assertEqual "dirOrPwd assumes the fallback is a directory" (directory d1) d1
-        d2 <- liftIO $ dirOrPwd $ Just $ tmpdir </> "foo"
-        liftIO $ assertEqual "dirOrPwd returns the supplied dir - no trailing slash supplied" fooDir d2
-        liftIO $ assertEqual "dirOrPwd assumes the supplied dir is a directory - no trailing slash supplied" (directory d2) d2
-        d3 <- liftIO $ dirOrPwd $ Just $ tmpdir </> "bar/"
-        liftIO $ assertEqual "dirOrPwd returns the supplied dir - trailing slash supplied" barDir d3
-        liftIO $ assertEqual "dirOrPwd assumes the supplied dir is a directory - trailing slash supplied" (directory d3) d3
-     )
-  )
-
-testFilterPaths = TestCase (
-  sh (
-      do
-        tmpdir <- using (mktempdir "." "hlflow")
-        let tmpJournals = map (tmpdir </>) journalFiles :: [FilePath]
-        let tmpExtras = map (tmpdir </>) extraFiles :: [FilePath]
-        let tmpHidden = map (tmpdir </>) hiddenFiles :: [FilePath]
-        let onDisk = List.sort $ tmpJournals ++ tmpExtras ++ tmpHidden
-        touchAll onDisk
-
-        let nonExistant = map (tmpdir </>) ["where", "is", "my", "mind"]
-        let toFilter = nonExistant ++ onDisk
-        filtered <- single $ filterPaths testfile toFilter
-        let actual = List.sort filtered
-        liftIO $ assertEqual "The filtered paths should exclude files not actually on disk" onDisk actual
-     )
-  )
-
 testExtraIncludesForFile = TestCase (
   sh (
       do
@@ -223,9 +169,7 @@
               <> "!include 3-journal/2018/2018-12-30.journal\n"
         actualJane7Contents <- liftIO $ readTextFile jane7
         liftIO $ assertEqual "Jane7: The include file contents should be the journal files" expectedJane7Contents actualJane7Contents
-
      )
   )
 
-tests = TestList [testDirOrPwd, testExtraIncludesForFile, testIncludesPrePost, testIncludesOpeningClosing,
-                  testHiddenFiles, testFilterPaths, testWriteIncludeFiles]
+tests = TestList [testExtraIncludesForFile, testIncludesPrePost, testIncludesOpeningClosing, testWriteIncludeFiles]
diff --git a/test/Common/Integration.hs b/test/Common/Integration.hs
new file mode 100644
--- /dev/null
+++ b/test/Common/Integration.hs
@@ -0,0 +1,135 @@
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE OverloadedLists #-}
+
+module Common.Integration (tests) where
+
+import Test.HUnit
+import Turtle
+import Prelude hiding (FilePath)
+import qualified Data.Map.Strict as Map
+import qualified Control.Foldl as Fold
+import qualified Data.Text as T
+import qualified Data.List as List (sort)
+
+import TestHelpers
+import Hledger.Flow.Import.Types
+import Hledger.Flow.Common
+import Control.Concurrent.STM
+
+testHiddenFiles = TestCase (
+  sh (
+      do
+        tmpdir <- using (mktempdir "." "hlflow")
+        let tmpJournals = map (tmpdir </>) journalFiles :: [FilePath]
+        let tmpExtras = map (tmpdir </>) extraFiles :: [FilePath]
+        let tmpHidden = map (tmpdir </>) hiddenFiles :: [FilePath]
+        let onDisk = List.sort $ tmpJournals ++ tmpExtras ++ tmpHidden
+        touchAll onDisk
+        filtered <- (fmap List.sort) $ shellToList $ onlyFiles $ select onDisk
+        let expected = List.sort $ tmpExtras ++ tmpJournals
+        liftIO $ assertEqual "Hidden files should be excluded" expected filtered
+     )
+  )
+
+testDirOrPwd = TestCase (
+  sh (
+      do
+        currentDir <- fmap (\p -> directory (p </> "t")) pwd
+        tmpdir <- using (mktempdir "." "hlflow")
+        let fooDir = collapse $ currentDir </> tmpdir </> "foo/"
+        let barDir = collapse $ currentDir </> tmpdir </> "bar/"
+        mkdir fooDir
+        mkdir barDir
+        d1 <- liftIO $ dirOrPwd Nothing
+        liftIO $ assertEqual "dirOrPwd returns pwd as a fallback" currentDir d1
+        liftIO $ assertEqual "dirOrPwd assumes the fallback is a directory" (directory d1) d1
+        d2 <- liftIO $ dirOrPwd $ Just $ tmpdir </> "foo"
+        liftIO $ assertEqual "dirOrPwd returns the supplied dir - no trailing slash supplied" fooDir d2
+        liftIO $ assertEqual "dirOrPwd assumes the supplied dir is a directory - no trailing slash supplied" (directory d2) d2
+        d3 <- liftIO $ dirOrPwd $ Just $ tmpdir </> "bar/"
+        liftIO $ assertEqual "dirOrPwd returns the supplied dir - trailing slash supplied" barDir d3
+        liftIO $ assertEqual "dirOrPwd assumes the supplied dir is a directory - trailing slash supplied" (directory d3) d3
+     )
+  )
+
+testDetermineBaseDir = TestCase (
+  sh (
+      do
+        error1 <- liftIO $ determineBaseDir'' "/path/to/dir" "/path/to/dir"
+        liftIO $ assertEqual "determineBaseDir produces an error message when given a non-existant dir" (Left $ errorMessageBaseDir "/path/to/dir") error1
+        tmpdir <- using (mktempdir "." "hlflow")
+
+        let unrelatedDir = collapse $ tmpdir </> "unrelated"
+        mkdir unrelatedDir
+
+        bdUnrelated <- liftIO $ determineBaseDir'' unrelatedDir unrelatedDir
+        liftIO $ assertEqual "determineBaseDir produces an error message when it cannot find a baseDir" (Left $ errorMessageBaseDir unrelatedDir) bdUnrelated
+
+        currentDir <- pwd
+        let baseDir = forceTrailingSlash $ collapse $ currentDir </> tmpdir </> "bd1"
+
+        let importDir = baseDir </> "import"
+        let ownerDir = importDir </> "john"
+        let bankDir = ownerDir </> "mybank"
+        let accDir = bankDir </> "myacc"
+        let inDir = accDir </> "1-in"
+        let yearDir = inDir </> "2019"
+        mktree yearDir
+
+        let reportDir = baseDir </> "report"
+        mkdir reportDir
+
+        cd baseDir
+        bd <- liftIO $ determineBaseDir Nothing
+        liftIO $ assertEqual "determineBaseDir searches from pwd upwards until it finds a dir containing 'import' - in the base dir" baseDir bd
+
+        cd reportDir
+        bdReport <- liftIO $ determineBaseDir Nothing
+        liftIO $ assertEqual "determineBaseDir searches from pwd upwards until it finds a dir containing 'import' - report dir" baseDir bdReport
+
+        cd yearDir
+        bdYear <- liftIO $ determineBaseDir Nothing
+        liftIO $ assertEqual "determineBaseDir searches from pwd upwards until it finds a dir containing 'import' - year dir" baseDir bdYear
+
+        cd inDir
+        bdIn <- liftIO $ determineBaseDir Nothing
+        liftIO $ assertEqual "determineBaseDir searches from pwd upwards until it finds a dir containing 'import' - input dir" baseDir bdIn
+
+        cd accDir
+        bdAcc <- liftIO $ determineBaseDir Nothing
+        liftIO $ assertEqual "determineBaseDir searches from pwd upwards until it finds a dir containing 'import' - account dir" baseDir bdAcc
+
+        cd bankDir
+        bdBank <- liftIO $ determineBaseDir Nothing
+        liftIO $ assertEqual "determineBaseDir searches from pwd upwards until it finds a dir containing 'import' - bank dir" baseDir bdBank
+
+        cd ownerDir
+        bdOwner <- liftIO $ determineBaseDir Nothing
+        liftIO $ assertEqual "determineBaseDir searches from pwd upwards until it finds a dir containing 'import' - owner dir" baseDir bdOwner
+
+        cd importDir
+        bdImport <- liftIO $ determineBaseDir Nothing
+        liftIO $ assertEqual "determineBaseDir searches from pwd upwards until it finds a dir containing 'import' - import dir" baseDir bdImport
+     )
+  )
+
+testFilterPaths = TestCase (
+  sh (
+      do
+        tmpdir <- using (mktempdir "." "hlflow")
+        let tmpJournals = map (tmpdir </>) journalFiles :: [FilePath]
+        let tmpExtras = map (tmpdir </>) extraFiles :: [FilePath]
+        let tmpHidden = map (tmpdir </>) hiddenFiles :: [FilePath]
+        let onDisk = List.sort $ tmpJournals ++ tmpExtras ++ tmpHidden
+        touchAll onDisk
+
+        let nonExistant = map (tmpdir </>) ["where", "is", "my", "mind"]
+        let toFilter = nonExistant ++ onDisk
+        filtered <- single $ filterPaths testfile toFilter
+        let actual = List.sort filtered
+        liftIO $ assertEqual "The filtered paths should exclude files not actually on disk" onDisk actual
+     )
+  )
+
+
+tests = TestList [testDirOrPwd, testDetermineBaseDir, testHiddenFiles, testFilterPaths]
diff --git a/test/Spec.hs b/test/Spec.hs
--- a/test/Spec.hs
+++ b/test/Spec.hs
@@ -8,10 +8,11 @@
 import Prelude hiding (FilePath)
 
 import qualified Common.Unit
+import qualified Common.Integration
 import qualified CSVImport.Unit
 import qualified CSVImport.Integration
 
-tests = TestList [Common.Unit.tests, CSVImport.Unit.tests, CSVImport.Integration.tests]
+tests = TestList [Common.Unit.tests, Common.Integration.tests, CSVImport.Unit.tests, CSVImport.Integration.tests]
 
 main :: IO Counts
 main = do
