diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@
 Usage
 -----
 
-Cgrep 6.4.1 Usage: cgrep [OPTION] [PATTERN] files...
+Cgrep 6.4.3 Usage: cgrep [OPTION] [PATTERN] files...
 
 cgrep [OPTIONS] [ITEM]
 
diff --git a/cgrep.cabal b/cgrep.cabal
--- a/cgrep.cabal
+++ b/cgrep.cabal
@@ -1,6 +1,6 @@
 Name:                cgrep
 Description:         Cgrep: a context-aware grep for source codes
-Version:             6.4.2
+Version:             6.4.3
 Synopsis:            Command line tool
 Homepage:            http://awgn.github.io/cgrep/
 License:             GPL-2
diff --git a/src/CGrep/Filter.hs b/src/CGrep/Filter.hs
--- a/src/CGrep/Filter.hs
+++ b/src/CGrep/Filter.hs
@@ -202,6 +202,7 @@
     (Cpp,        mkFilterFunction [("/*", "*/"), ("//", "\n")]  [("\"", "\"")] ),
     (Csharp,     mkFilterFunction [("/*", "*/"), ("//", "\n")]  [("\"", "\"")] ),
     (Chapel,     mkFilterFunction [("/*", "*/"), ("//", "\n")]  [("\"", "\"")] ),
+    (Coffee,     mkFilterFunction [("###", "###"), ("#", "\n")]  [("\"", "\"")] ),
     (D,          mkFilterFunction [("/*", "*/"), ("//", "\n")]  [("\"", "\"")] ),
     (Go,         mkFilterFunction [("/*", "*/"), ("//", "\n")]  [("\"", "\"")] ),
     (Java,       mkFilterFunction [("/*", "*/"), ("//", "\n")]  [("\"", "\"")] ),
diff --git a/src/CGrep/Lang.hs b/src/CGrep/Lang.hs
--- a/src/CGrep/Lang.hs
+++ b/src/CGrep/Lang.hs
@@ -28,7 +28,7 @@
 import Options
 import Util
 
-data Lang = Awk | C | Cpp | Csharp | Chapel | Css | CMake | D | Erlang | Fsharp | Go | Haskell |
+data Lang = Awk | C | Cpp | Csharp | Chapel | Coffee | Css | CMake | D | Erlang | Fsharp | Go | Haskell |
                 Html | Java | Javascript | Latex | Lua | Make | OCaml | ObjectiveC |
                 Perl | PHP | Python | Ruby | Scala | Tcl | Text | Shell | Verilog | VHDL | Vim
                     deriving (Read, Show, Eq, Ord, Bounded)
@@ -52,6 +52,7 @@
             (C,         [Ext "c", Ext "C"]),
             (Cpp,       [Ext "cpp", Ext "CPP", Ext "cxx", Ext "cc", Ext "cp", Ext "tcc", Ext "h", Ext "H", Ext "hpp", Ext "ipp", Ext "HPP", Ext "hxx", Ext "hh", Ext "hp"]),
             (Csharp,    [Ext "cs", Ext "CS"]),
+            (Coffee,    [Ext "coffee"]),
             (Chapel,    [Ext "chpl"]),
             (Css,       [Ext "css"]),
             (CMake,     [Name "CMakeLists.txt", Ext "cmake"]),
diff --git a/src/CmdOptions.hs b/src/CmdOptions.hs
--- a/src/CmdOptions.hs
+++ b/src/CmdOptions.hs
@@ -60,7 +60,8 @@
 
                 jobs   = 1                 &= help "Number of jobs",
                 multiline = 1              &= help "Enable multi-line matching",
-                recursive = False          &= help "Enable recursive search",
+                recursive = False           &= help "Enable recursive search (don't follow symlinks)" &= explicit &= name "recursive" &= name "r",
+                deference_recursive = False &= help "Recursive, follow symlinks" &= explicit &= name "deference-recursive" &= name "R",
                 invert_match = False       &= help "Select non-matching lines" &= explicit &= name "invert-match" &= name "v",
                 show_match = False         &= help "Show list of matching tokens" &= explicit &= name "show-match",
                 color = False              &= help "Use colors to highlight the matching strings" &= explicit &= name "color",
diff --git a/src/Config.hs b/src/Config.hs
--- a/src/Config.hs
+++ b/src/Config.hs
@@ -31,7 +31,7 @@
 cgreprc = "cgreprc"
 
 version :: String
-version = "6.4.2"
+version = "6.4.3"
 
 data Config = Config
               {
diff --git a/src/Main.hs b/src/Main.hs
--- a/src/Main.hs
+++ b/src/Main.hs
@@ -19,6 +19,7 @@
 module Main where
 
 import Data.List
+import qualified Data.Set as Set
 import Data.Maybe
 import Data.Char
 import Data.Data()
@@ -36,6 +37,7 @@
 import System.Directory
 import System.FilePath ((</>), takeFileName)
 import System.Environment
+import System.Posix.Files
 import System.IO
 import System.Exit
 
@@ -53,21 +55,24 @@
 
 -- push file names in TChan...
 
-putRecursiveContents :: Options -> TChan (Maybe FilePath) -> FilePath -> [Lang] -> [String] -> IO ()
-putRecursiveContents opts inchan topdir langs prunedir = do
+putRecursiveContents :: Options -> TChan (Maybe FilePath) -> FilePath -> [Lang] -> [String] -> Set.Set FilePath -> IO ()
+putRecursiveContents opts inchan topdir langs prunedir visited = do
     dir <-  doesDirectoryExist topdir
     if dir then do
             names <- liftM (filter (`notElem` [".", ".."])) $ getDirectoryContents topdir
             forM_ names $ \n -> do
                 let path = topdir </> n
                 let filename = takeFileName path
-                isDirectory <- doesDirectoryExist path
-                if isDirectory
-                    then unless (filename `elem` prunedir) $
-                         putRecursiveContents opts inchan path langs prunedir
-                    else case getLang opts filename >>= (\f -> f `elemIndex` langs <|> toMaybe 0 (null langs) ) of
-                            Nothing -> return ()
-                            _       -> atomically $ writeTChan inchan (Just path)
+                cpath  <- canonicalizePath path
+                status  <- getFileStatus path
+                lstatus <- getSymbolicLinkStatus path
+                unless (cpath `Set.member` visited) $
+                    if isDirectory status && (not (isSymbolicLink lstatus) || deference_recursive opts)
+                       then unless (filename `elem` prunedir)  $
+                           putRecursiveContents opts inchan path langs prunedir (Set.insert cpath visited)
+                       else case getLang opts filename >>= (\f -> f `elemIndex` langs <|> toMaybe 0 (null langs) ) of
+                               Nothing -> return ()
+                               _       -> atomically $ writeTChan inchan (Just path)
            else atomically $ writeTChan inchan (Just topdir)
 
 
@@ -173,8 +178,8 @@
 
     _ <- forkIO $ do
 
-        if recursive opts
-            then forM_ paths $ \p -> putRecursiveContents opts in_chan p lang_enabled (pruneDirs conf)
+        if recursive opts || deference_recursive opts
+            then forM_ paths $ \p -> putRecursiveContents opts in_chan p lang_enabled (pruneDirs conf) (Set.singleton p)
             else do
                 files <- liftM (\l -> if null l && not isTerm then [""] else l) $ filterM doesFileExist paths
                 forM_ files (atomically . writeTChan in_chan . Just)
diff --git a/src/Options.hs b/src/Options.hs
--- a/src/Options.hs
+++ b/src/Options.hs
@@ -63,6 +63,7 @@
                 jobs         :: Int,
                 multiline    :: Int,
                 recursive    :: Bool,
+                deference_recursive :: Bool,
                 invert_match :: Bool,
                 max_count    :: Int,
                 count        :: Bool,
