diff --git a/init.el b/init.el
index d219fa04c601677e347d35774a2842fbc51be6b8..9692f34366b7103e8d5fdcbb711d8b76de169060 100644
--- a/init.el
+++ b/init.el
@@ -84,6 +84,7 @@
 
   (require 'editor)
   (require 'completion)
+  (require 'search)
 
 ;;; Keybinding
   (use-package evil
diff --git a/lisp/completion.el b/lisp/completion.el
index 090f3fd7fc3129aeeeef623d657b2a2667524f2c..ad1e51cf78e96a906ee11022d5388591016f7181 100644
--- a/lisp/completion.el
+++ b/lisp/completion.el
@@ -13,24 +13,6 @@
 ;;
 ;;
 ;;; Code:
-(use-package projectile
-  :ensure t
-  :init
-  (progn
-    (setq projectile-indexing-method 'alien
-    projectile-generic-command "find . -type f")
-    (setq projectile-sort-order 'recentf
-    projectile-cache-file user/projectile-cache-file
-    projectile-known-projects-file user/projectile-known-projects-file)
-    )
-  :config
-  (projectile-mode +1)
-  :diminish projectile-mode
-  :bind (("C-c p f" . 'counsel-projectile-find-file)
-   ("C-c p p" . 'counsel-projectile-switch-project)
-   ("C-c p b" . 'counsel-projectile-switch-to-buffer)
-   ("C-c p k" . 'projectile-kill-buffers))
-  )
 
 (use-package ivy
   :ensure t
@@ -141,5 +123,59 @@
 ;;           (min-height . ,ivy-height)))
 ;;   )
 
+(cl-defun ivy-file-search (&key query in all-files (recursive t) prompt args)
+  "Conduct a file search using ripgrep.
+
+:query STRING
+  Determines the initial input to search for.
+:in PATH
+  Sets what directory to base the search out of. Defaults to the current
+  project's root.
+:recursive BOOL
+  Whether or not to search files recursively from the base directory."
+  (declare (indent defun))
+  (unless (executable-find "rg")
+    (user-error "Couldn't find ripgrep in your PATH"))
+  (require 'counsel)
+  (let* ((this-command 'counsel-rg)
+         (project-root (or (doom-project-root) default-directory))
+         (directory (or in project-root))
+         (args (concat (if all-files " -uu")
+                       (unless recursive " --maxdepth 1")
+                       " --hidden -g!.git "
+                       (mapconcat #'shell-quote-argument args " "))))
+    (setq deactivate-mark t)
+    (counsel-rg
+     ;; (or query
+     ;;     (when (doom-region-active-p)
+     ;;       (replace-regexp-in-string
+     ;;        "[! |]" (lambda (substr)
+     ;;                  (cond ((and (string= substr " ")
+     ;;                              (not (featurep! +fuzzy)))
+     ;;                         "  ")
+     ;;                        ((string= substr "|")
+     ;;                         "\\\\\\\\|")
+     ;;                        ((concat "\\\\" substr))))
+     ;;        (rxt-quote-pcre (doom-thing-at-point-or-region)))))
+     query
+     directory args
+     (or prompt
+         (format "rg%s [%s]: "
+                 args
+                 (cond ((equal directory default-directory)
+                        "./")
+                       ((equal directory project-root)
+                        (projectile-project-name))
+                       ((file-relative-name directory project-root))))))))
+
+
+(defun ivy/project-search (&optional arg initial-query directory)
+  "Performs a live project search from the project root using ripgrep.
+
+If ARG (universal argument), include all files, even hidden or compressed ones,
+in the search."
+  (interactive "P")
+  (ivy-file-search :query initial-query :in directory :all-files arg))
+
 (provide 'completion)
 ;;; completion.el ends here
diff --git a/lisp/search.el b/lisp/search.el
new file mode 100644
index 0000000000000000000000000000000000000000..810afbf7735815f1521de6812cf82728b7111830
--- /dev/null
+++ b/lisp/search.el
@@ -0,0 +1,79 @@
+;;; search.el --- Search configs -*- lexical-binding: t; -*-
+;;
+;; Copyright (C) 2020 John Doe
+;;
+;; Author: John Doe <http://github/l>
+;; Maintainer: John Doe <john@doe.com>
+;; Version: 0.0.1
+;; Keywords:
+;; Package-Requires: ((emacs 27.1) (cl-lib "0.5"))
+;;
+;; This file is not part of GNU Emacs.
+;;
+;;; Commentary:
+;;
+;;
+;;
+;;; Code:
+(use-package projectile
+  :ensure t
+  :defer t
+  :commands (projectile-project-root
+             projectile-project-name
+             projectile-project-p
+             )
+  :init
+  (progn
+    (setq projectile-indexing-method 'alien
+          projectile-generic-command "find . -type f"
+          projectile-ignored-projects '("~/" "/tmp")
+          projectile-globally-ignored-files '(".DS_Store" "TAGS")
+          projectile-globally-ignored-directories '(".ccls-cache")
+          projectile-kill-buffers-filter 'kill-only-files)
+
+    (setq projectile-sort-order 'recentf
+          projectile-cache-file user/projectile-cache-file
+          projectile-known-projects-file user/projectile-known-projects-file)
+    )
+  :config
+  (projectile-mode +1)
+
+  (setq projectile-project-root-files-bottom-up
+        (append '(".projectile"         ; projctiles's root marker
+                  ".project"            ; doom project marker
+                  ".git")               ; Git
+                )
+        ;; This will be filled by other pakages
+        projectile-project-root-files '()
+        projectile-project-root-files-top-down-recurring '("Makefile"))
+
+  ;; Per-project compilation buffers
+  (setq compilation-buffer-name-function #'projectile-compilation-buffer-name
+        compilation-save-buffers-predicate #'projectile-current-project-buffer-p)
+
+  :diminish projectile-mode
+  :bind (("C-c p f" . 'counsel-projectile-find-file)
+         ("C-c p p" . 'counsel-projectile-switch-project)
+         ("C-c p b" . 'counsel-projectile-switch-to-buffer)
+         ("C-c p k" . 'projectile-kill-buffers))
+  )
+
+(defun user/search-project (&optional arg)
+  "Conduct a text search in the current project root.
+If prefix ARG is set, include ignored/hidden files."
+  (interactive "P")
+  (let* ((projectile-project-root nil)
+         (disabled-command-function nil)
+         (current-prefix-arg (unless (eq arg 'other) arg))
+         (default-directory
+           (if (eq arg 'other)
+               (if-let (projects (projectile-relevant-known-projects))
+                   (completing-read "Search project: " projects nil t)
+                 (user-error "There are no known projects"))
+             default-directory)))
+    (call-interactively
+     #'ivy/project-search)
+    ))
+
+(provide 'search)
+;;; search.el ends here