TLDR:

hs -c "hs.pasteboard.readStyledText():convert('html')" | pandoc -f html -t gfm-raw_html+hard_line_breaks

Or bind it to a keyboard shortcut like ⌘-⌥-C to achieve “copy-as-Markdown” like the following:

hs.hotkey.bind({ 'cmd', 'alt' }, 'c', function()
  -- Sometimes a single cmd+c has no effect
  hs.eventtap.keyStroke({ 'cmd' }, 'c')
  hs.eventtap.keyStroke({ 'cmd' }, 'c')

  local task = hs.task.new(
    os.getenv('HOME') .. '/.nix-profile/bin/pandoc',
    --[[callbackFn=]] function(task, stdOut, stdErr)
      hs.pasteboard.setContents(stdOut)
      hs.alert('Copied as Markdown')
    end,
    --[[arguments=]] { '-f', 'html', '-t', 'gfm-raw_html+hard_line_breaks' }
  )

  task:setInput(hs.pasteboard.readStyledText():convert('html'))
  task:start()
end)

Similarly, this can achieve “paste-as-Markdown”:

hs.hotkey.bind({ 'cmd', 'alt' }, 'v', function()
  local task = hs.task.new(
    os.getenv('HOME') .. '/.nix-profile/bin/pandoc',
    --[[callbackFn=]] function(task, stdOut, stdErr)
      hs.eventtap.keyStrokes(stdOut)
    end,
    --[[arguments=]] { '-f', 'html', '-t', 'gfm-raw_html+hard_line_breaks' }
  )

  task:setInput(hs.pasteboard.readStyledText():convert('html'))
  task:start()
end)

You might need to change the path to pandoc depending on how its installed.

This requires:

  • Hammerspoon (the hs CLI needs IPC installed) for reading RTF clipboard content and exporting it as HTML
  • Pandoc for converting HTML to Markdown

TODO:

  • Copying with hs.eventtap.keyStroke({ 'cmd' }, 'c') doesn’t work in Notes.app for some reasons
  • Pasting with hs.eventtap.keyStrokes(stdOut) is a bit slower than ideal, an alternative is to hs.pasteboard.setContents(stdOut) then hs.eventtap.keyStroke({ 'cmd' }, 'v'), but that only works if you are pasting once

Notes

Note on the gfm-raw_html part: :convert('html') produces HTML like the following:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="Content-Style-Type" content="text/css">
<title></title>
<meta name="Generator" content="Cocoa HTML Writer">
<meta name="CocoaVersion" content="2299.74">
<style type="text/css">
p.p1 {margin: 0.0px 0.0px 12.0px 0.0px; font: 12.0px Times; -webkit-text-stroke: #000000}
span.s1 {font-kerning: none}
span.s2 {text-decoration: underline ; font-kerning: none; color: #0000e9; -webkit-text-stroke: 0px #0000e9}
span.s3 {font: 13.0px Courier; text-decoration: underline ; font-kerning: none; color: #0000e9; -webkit-text-stroke: 0px #0000e9}
</style>
</head>
<body>
<p class="p1"><span class="s1">Pandoc can convert between numerous markup and word processing formats, including, but not limited to, various flavors of <a href="https://daringfireball.net/projects/markdown/"><span class="s2">Markdown</span></a>, <a href="https://www.w3.org/html/"><span class="s2">HTML</span></a>, <a href="https://www.latex-project.org/"><span class="s2">LaTeX</span></a> and <a href="https://en.wikipedia.org/wiki/Office_Open_XML"><span class="s2">Word docx</span></a>. For the full lists of input and output formats, see the <a href="https://pandoc.org/MANUAL.html#option--from"><span class="s3">--from</span></a> and <a href="https://pandoc.org/MANUAL.html#option--to"><span class="s3">--to</span></a> <a href="https://pandoc.org/MANUAL.html#general-options"><span class="s2">options below</span></a>. Pandoc can also produce <a href="https://www.adobe.com/pdf/"><span class="s2">PDF</span></a> output: see <a href="https://pandoc.org/MANUAL.html#creating-a-pdf"><span class="s2">creating a PDF</span></a>, below.</span></p>
</body>
</html>

If you just convert it to markdown or gfm, you’ll get:

[Pandoc can convert between numerous markup and word processing formats,
including, but not limited to, various flavors of
[[Markdown]{.s2}](https://daringfireball.net/projects/markdown/),
[[HTML]{.s2}](https://www.w3.org/html/),
[[LaTeX]{.s2}](https://www.latex-project.org/) and [[Word
docx]{.s2}](https://en.wikipedia.org/wiki/Office_Open_XML). For the full
lists of input and output formats, see the
[[\--from]{.s3}](https://pandoc.org/MANUAL.html#option--from) and
[[\--to]{.s3}](https://pandoc.org/MANUAL.html#option--to) [[options
below]{.s2}](https://pandoc.org/MANUAL.html#general-options). Pandoc can
also produce [[PDF]{.s2}](https://www.adobe.com/pdf/) output: see
[[creating a PDF]{.s2}](https://pandoc.org/MANUAL.html#creating-a-pdf),
below.]{.s1}

Note the s1, s2 tags.

Using gfm-raw_html as per https://stackoverflow.com/a/62963659 strips those tags.

Pandoc can convert between numerous markup and word processing formats,
including, but not limited to, various flavors of
[Markdown](https://daringfireball.net/projects/markdown/),
[HTML](https://www.w3.org/html/),
[LaTeX](https://www.latex-project.org/) and [Word
docx](https://en.wikipedia.org/wiki/Office_Open_XML). For the full lists
of input and output formats, see the
[--from](https://pandoc.org/MANUAL.html#option--from) and
[--to](https://pandoc.org/MANUAL.html#option--to) [options
below](https://pandoc.org/MANUAL.html#general-options). Pandoc can also
produce [PDF](https://www.adobe.com/pdf/) output: see [creating a
PDF](https://pandoc.org/MANUAL.html#creating-a-pdf), below.