org-customize has a node for startup folded, with options no fold, fold, content, and show everything. There doesn't seem to be an option for "remember last folded state". For such a customisable major mode, I think this is a glaring omission. I was even pointed toward the undocumented var org-inhibit-startup-visibility-stuff, but this just gives the completely open mode.

  • 1
    While that does sound useful, it is a very different problem then choosing a default display style. You might need to annotate every node to save its current state, or write that state somewhere else. (Saving state outside the org file might require unique ids, too.)
    – glucas
    Commented Apr 20, 2016 at 14:49
  • I see. Annotating it in every node sounds messy, but I wouldn't mind having another global cache file like recentf or save-place, as long as it works. What do you mean by it might require unique ids?
    – sooheon
    Commented Apr 20, 2016 at 14:56
  • Just my first reaction, haven't thought it through and there may be a solution out there already. But an org file can have multiples nodes with the same text, in different fold states. You would need some way to uniquely identify each visible node.
    – glucas
    Commented Apr 20, 2016 at 15:02
  • Ah I see. I was thinking just top to bottom traversal like org-next-visible-heading, open or closed. So if all are closed it would be a list as long as the number of top level headers. Anyways this is just speculation, I hope someone else knows a previous solution.
    – sooheon
    Commented Apr 20, 2016 at 15:07

1 Answer 1


You need to add a function to one of the save-buffer hooks that serializes the contents of (point) and (org-outline-overlay-data) somewhere, perhaps as a local file variable, and also add a local variable to eval a function to restore state. Here is an example that almost does what you want:

(defvar org-outline-state () "State data for outline visibility")
(make-variable-buffer-local  'org-outline-state)
(put 'org-outline-state 'safe-local-variable #'listp)

(defun load-org-outline-state ()
  "Load the last point and outline state stored in this file and apply them.
This function is usually run from a local file variable."
  (org-set-outline-overlay-data (cadr org-outline-state))
  (add-hook 'before-save-hook 'save-org-outline-state nil t)
  ;; we need visibility changes to modify the buffer so we can save them.
  (add-hook 'org-cycle-hook
        (lambda (arg)
          (set-buffer-modified-p t))
        nil t)
  (add-hook 'find-file-hook
        (lambda ()
          (when (and (boundp 'org-outline-state) org-outline-state)
        (goto-char (car org-outline-state))))))

(defun save-org-outline-state ()
  "Write point and outline state to the file.
The first time you run this it sets up the file to save the state
  (add-hook 'before-save-hook 'save-org-outline-state nil t)
  (add-hook 'org-cycle-hook
        (lambda (arg)
          (set-buffer-modified-p t))
        nil t)
  (add-hook 'find-file-hook
        (lambda ()
          (when (and (boundp 'org-outline-state) org-outline-state)
        (goto-char (car org-outline-state)))))

  ;; Save the data
     (list (point) (org-outline-overlay-data)))

    ;; Make sure we have a load local variable and add it if not.
     (goto-char (point-min))
     ;; we do this search because otherwise we will add a new eval line on every
     ;; save.
     (unless (re-search-forward "^# eval: (load-org-outline-state)" nil 'mv)
       (add-file-local-variable 'eval '(load-org-outline-state)))))) 

(add-to-list 'safe-local-eval-forms

It will modify the contents of your file (adding local variables and data to the end).

Alternatively, you could store the visibility in each headline via a similar save-buffer hook, and then in a similar load function map over them to set the visibility. It is just another way to do it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.