A TODO.org file is one of the first things I create when starting a new project. I use this file to organize all of the project's milestones and tasks, as well as to track time spent on different items.

One disadvantage with this approach is that scheduled tasks will not appear in the org-agenda without adding the TODO.org's path to org-agenda-files. Doing this by hand can be tedious, especially with a lot of projects.

Thankfully there is a package to help with this: org-projectile. I already use projectile to navigate my projects; org-projectile sits on top of that and adds some useful features:

I made a couple of changes to integrate it better with my setup. By default org-projectile adds every registered projectile project, but not everything indexed by projectile has a TODO.org file.

This small function filter the list to only projects that exist:

(defun sodaware/org-projectile-todo-files ()
  "Fetch a list of org TODO files for projects that actually exist."
  (seq-filter #'file-exists-p (org-projectile-todo-files)))

;; Add org-projectile files to org.
(setq org-agenda-files
      (append org-agenda-files (sodaware/org-projectile-todo-files)))

I also created a helper function to open the TODO.org file for the current project:

(defun sodaware/org-projectile-goto-project-file ()
  "Open the TODO.org file for the current project."
  (org-projectile-goto-location-for-project (projectile-project-name)))

My org-projectile configuration looks like this:

(use-package org-projectile
  :after (org)
  (org-projectile-per-project-filepath "TODO.org"))

(use-package org-projectile-helm
  :after org-projectile
  :bind (("C-c n p" . org-projectile-helm-template-or-project)
	 ("C-c p O" . sodaware/org-projectile-goto-project-file)))