This implements display-line-numbers-offset, and adds info, NEWS, etc. Better wording welcome, as always. The variable is automatically buffer-local because I don't imagine that there's a good default value (other than zero) and each buffer that uses it will want its own.

I've done some testing, but more eyes would be great.

As an aside, this allows some dirty tricks, like numbering from 0 (by setting it to -1), or this funny monstrosity, which allows to reverse-count the buffer:

  (let ((old nil)
        (buf (current-buffer)))
    (add-hook 'before-change-functions
              (lambda (beg end)
                (when (eq buf (current-buffer))
                  (setq old (count-lines beg end)))))
    (add-hook 'after-change-functions
              (lambda (beg end _len)
                (when (and (eq buf (current-buffer))
                           old
                           (/= old (count-lines beg end)))
                  (setq display-line-numbers-offset (- -1
                                                     (count-lines (point-min)
                                                                  (point-max)))
                        old nil)))))

Of course, if the buffer is immutable, this is just

  (setq display-line-numbers-offset (- -1 (count-lines (point-min) (point-max))))

in some mode hook.