Working on a Mac

How to open a file from Terminal on a Mac

You can do this with Note My straight from a shell, using the path you already have. Here is every supported way to hand it a file without touching a file dialog.

You are in a shell, you have a path, and you want it on screen. Perhaps a build step just wrote a report you need to read. Opening a file dialog and navigating back to a directory you are already standing in is a small, repeated waste, and it is avoidable.

Note My can be handed files two ways from the command line: the ordinary macOS open command, and a local URL scheme, notemy://, with three verbs. This guide covers both, with commands you can paste straight into a script, a shell function that handles awkward paths for you, and the shortcuts that carry you back out to a shell when you are done reading.

The plain way: the open command

Note My opens the file types it edits — source code, scripts, shell scripts, plain text, JSON, XML, YAML, HTML and CSS. It appears in the Open With menu for those files, and it will not make itself your default for any of them. It does not put itself forward for arbitrary files either, so nothing you already rely on changes when you install it.

That has one practical consequence: a bare open file.txt hands the file to whatever your Mac already considers the default for that type. Name the application in the command and there is no ambiguity about where it lands.

shell
# By bundle identifier — exact, and unaffected by renaming the app.
open -a "Note My" ./server.log

# Several files at once. Each arrives in its own tab.
open -a "Note My" src/*.swift

open -a works too and takes the application's name as it appears in your Applications folder. -b takes the bundle identifier and is the safer form in a script that other people will run.

Note

Note My contains no networking code of its own; the only network activity is performed by Apple’s own system services, to establish purchases and transactions state. A path you hand it stays on your Mac and goes nowhere else. There is no account to sign in to, and nothing is uploaded.

Each file opens in its own tab, ready to read. Our advanced language identifier sets the language for you and our syntax engine colours it, so a log, a Swift file and a Makefile each come up looking the way you would expect, with no flag on the command line and nothing to configure. Run the same script tomorrow and you get the same result.

If you want a different language for a particular file — a config file with an unhelpful extension, or a template you would rather read as HTML — set it yourself once the file is on screen. Click the Identify pill in the status bar to open the Language Inspector, then pick what you want from the override pop-up.

The notemy:// URL scheme

The scheme is the app's scriptable surface, and it is the same route you take from the Finder: the Note My ▸ items that open or compare give you from a right-click exactly what the URLs below give you from a shell. Three verbs cover it — open, openfolder and compare — and the same Finder menu sits alongside them with copy-path and new-file items for the moments you are already looking at a window.

The three verbs of the notemy URL scheme, their parameters and what each one takes
VerbFormWhat it doesTakes
opennotemy://open?paths=…Opens each path as a tabAs many paths as you give it
openfoldernotemy://openfolder?path=…Opens a folder's filesOne folder, up to 50 files
comparenotemy://compare?paths=…Opens both, then comparesTwo paths

Every verb is read-into-editor only. Nothing in the scheme writes a file, runs a command, or changes a setting.

open — one path, or many

The paths parameter is a list of filesystem paths joined by newlines and percent-encoded. One path is simply a list of one.

shell
open "notemy://open?paths=%2Fvar%2Flog%2Fsystem.log"

Use absolute paths. The URL is handed to macOS rather than to your shell, so spell the path out in full — or let the shell spell it out for you with $PWD and $HOME, which expand before the URL is built.

Percent-encoding paths so they survive the trip

Spaces, accents and every other awkward character have to be encoded, and the newline between paths becomes %0A. Doing that by hand is miserable, so wrap it once. This shell function takes any number of paths and opens them all.

~/.zshrc
notemy_open() {
  local encoded
  encoded=$(printf '%s\n' "$@" | python3 -c \
    'import sys, urllib.parse; print(urllib.parse.quote(sys.stdin.read().rstrip("\n")), end="")')
  open "notemy://open?paths=$encoded"
}

# Spaces, accents, anything — it survives.
notemy_open /var/log/system.log "$HOME/Projects/My App/notes.md"

Forward slashes need no encoding inside a query value, so the URL stays roughly readable.

openfolder — a whole folder in one command

Point it at a directory and you get the files inside it, in sort order, each in its own tab. Hidden files and packages sit it out, and what arrives is the top level of that folder — the source directory, the drafts folder, the day's logs — rather than everything nested beneath it.

shell
open "notemy://openfolder?path=%2FUsers%2Fyou%2FProjects%2Fapi%2Fsrc"

One call brings up to 50 files to the screen in sort order, which covers most working directories in a single line. For a larger folder, or when you want a particular slice of one, do the choosing in the shell and hand the paths to open, which takes as many as you give it. A glob you have written yourself is the more predictable tool: *.swift, *.log, or whatever the day calls for, and every match arrives in its own tab.

compare — two files and a straight answer

The compare verb takes the same paths parameter with exactly two entries. It opens both files and compares them in one command.

shell
open "notemy://compare?paths=%2Ftmp%2Fbefore.txt%0A%2Ftmp%2Fafter.txt"

This is the question a script usually wants settled: are these the same? Note My puts the answer on screen as a count across every open document, phrased as "Compared N files • M differing line(s)." — so a single line in a build has the answer up and waiting, with no file dialog and no menu in between. This verb and the Finder extension's compare item both ask for the same summary, one from a script and one from a right-click.

When the answer is yes, something differs, and you want to see where, our comparison view paints the two documents side by side with the changed lines marked. Reach for it from the toolbar's Compare menu once the files are open.

Important

The count covers every open document, so tabs you already had open are included in the result. For a comparison of exactly two files, close the rest first, or use Compare Files… from the toolbar's Compare menu, which pairs exactly two documents and paints the differences in place.

Going the other way, from the editor to a shell

The traffic runs both directions. Right-click a tab and you get Open in Terminal and Save and Open in Terminal — the second writes the file first, which is the one you want before running what you have just edited. ⌥⇧⌘C copies the active file's path to the clipboard, and the same menu offers Copy File Name and Copy Containing Folder Path. ⇧⌘R reveals the file in the Finder.

There is also a macOS Service, Open in Note My, which accepts file URLs from any application's Services menu. Launch the app once and the Service is there, with no logging out and back in: select a file anywhere in macOS, choose it from the Services menu, and the file arrives in a tab like any other.

Troubleshooting

The command runs and nothing opens

macOS needs to have seen the app before it will send a notemy:// URL to it. If the app has never been launched, or has just been moved or replaced, launch it once from the Finder, then try the command again.

The file opened in a different application

That is expected: Note My never makes itself your default, so a bare open somefile.json goes to whichever application your Mac already prefers. Pass -a "Note My" to be explicit, or use a notemy://open URL, which names the application by definition.

A path with a space in it opens the wrong file, or nothing

An unencoded space ends the URL early. Percent-encode the whole path — the shell function above does it for you. Quote the URL in your shell as well, so the shell does not try to interpret ? or &.

Only some of the folder's files opened

What a folder call brings up is the regular files at that level, in sort order, up to fifty of them: hidden files and packages sit it out by design, so a folder of source arrives without its dot-files. For a bigger folder, glob the paths you want in the shell and pass them to open, which takes as many as you hand it.

The comparison reported more files than I passed it

Expected. The count this verb reports covers every open document, not only the two paths you passed it. Close the tabs you do not want counted, then run the command again.

Saving fails after opening from a script

Ordinary editing and saving work on a path you handed it: a file opened from a script takes edits and saves back with ⌘S like any other tab. Where a write is refused — our macro recorder replaying a save into a folder you have never opened, for instance — you are told so plainly rather than left guessing, and the message points you at File ▸ Save As…, which grants access to that folder. Choose the destination there once and the write goes through, with the file landing exactly where the script meant to put it.

macOS says the file is not text

Open the file with ⇧⌘O, File ▸ Open Anything as Text…, which brings a file up regardless of what the system thinks it is. A log with an odd extension, a config file with none at all, a payload the system has guessed wrong about — each comes up as text you can read and edit.

Putting it to work in a script

Any of these lines is small on its own. What makes them worth wiring in is that anything able to run a shell command can use them, so the moment a file matters you can have it on screen without leaving what you were doing. A build step that writes a report can show it the instant it lands. A test run that fails can put the log up at the point you would have gone looking for it anyway. A Makefile target, a git hook, an alias you type twenty times a day — all of them take the same one-liner.

shell
# Open the report a build just wrote, once the build has succeeded.
make report && open -a "Note My" build/report.html

# Put the log on screen when a test run fails.
run_tests || notemy_open "$PWD/test.log"

# Keep a working folder one word away.
alias drafts='open "notemy://openfolder?path=%2FUsers%2Fyou%2FDocuments%2FDrafts"'

Because open hands the URL to macOS and returns straight away, a line like these costs the script nothing: it does not block, and it will not hold up the step behind it. Put one at the end of a target and the file is waiting for you by the time you look up from the shell.

Every verb reads files into the editor and stops there. Nothing in the scheme executes anything, writes over your work or changes a setting, so a line you paste into a script a colleague also runs does the same calm thing on their Mac as it does on yours. Your files stay where they are, on the machine they are already on.

Once a file is up you have the whole editor rather than a preview of one. ⌘L goes to a line, pre-filled with the line you are on. The Identify pill in the status bar opens the Language Inspector, where an override pop-up lets you set the language yourself when an extension is unhelpful. Edits save back to the same path with ⌘S, and the shortcuts in the section above return you to a shell in the right directory with the file already written. Shell to editor and back again, with no file dialog in either direction.

Frequently asked questions

How do I call this from a script or an alias?

Wrap it in a shell function. The four-line notemy_open function above builds the URL and calls open, so once it is in your ~/.zshrc you can write notemy_open ./server.log from any shell, alias, Makefile or hook. For a single named file, open -a "Note My" is enough on its own.

How do I get to a particular line after opening a file?

⌘L opens Go to Line, pre-filled with the line you are on and selected, so a number typed straight over it takes you there. Out-of-range numbers are refused rather than silently clamped to the end, so a line number carried over from a stack trace either lands exactly where you meant or says so plainly.

Will opening files this way change my default text editor?

Your defaults stay exactly as you set them. The app is built to show up in Open With for the files it edits without becoming anyone's default, and it does not put itself forward for other file types at all. Naming it in an open command is a one-off choice for that command, not a system change.

Can I use this from a Makefile or a build step?

Yes — it is just open, so anything that can run a shell command can use it. It is fire-and-forget: the command returns immediately, so put it at the end of a target and let the rest of the build carry on while the file arrives on screen.

How do I open a whole project folder at once?

Use notemy://openfolder?path=… with the folder percent-encoded. It opens the non-hidden, non-package files in sorted order, up to fifty. For anything larger or more selective, glob the files yourself and pass them to the open verb.

Does opening a file from Terminal send anything anywhere?

Nothing leaves your Mac. Note My contains no networking code of its own; the only network activity is performed by Apple’s own system services, to establish purchases and transactions state. There is no telemetry, no update checker and no analytics. A path handed to it is opened on your Mac, there is no account anywhere, and the file never leaves the machine.