How to update tampermonkey script to a local file programmatically?

I've answered this in another question. I think someone should merge them, but in the meantime, since it's very similar and frustrating, I'll put it here for the next person looking for help.

Set up

We'll configure just a couple of items so that you can code in your editor and see the changes reflected in the browser without a nuisance.

  1. Go to Chrome -> Extensions (or paste 'chrome://extensions' to your URL bar) and find the TamperMonkey 'card'. Click details. On the page that opens, allow it access to file URLs:

enter image description here

  1. Save your script file wherever you want in your filesystem. Save the entire thing, including the ==UserScript== header. I'm using macOS, so my path is: /Users/me/Scripts/SameWindowHref.user.js

  2. Now, go to the TM's dashboard in your browser, open the script in question in its TM editor and delete everything except the entire ==UserScript== header

  3. Add to the header a @require property pointing to the script's absolute path.

At this point, TM's editor should look something like this:

enter image description here

Possible gotcha: Using the file:// URI scheme at the beginning of your @require path is now required. On windows systems would be:

// @require      file://C:\path\to\userscript.user.js

For macOS and *nix, we'll need three slashes in a row:

// @require      file:///path/to/userscript.user.js

Execution Contexts

If you have multiple JavaScript files, each specified with a @require key, it is important to understand how and when each script is executed. This is important when using external libraries (like jQuery), or when segmenting your scripts as good coding practice.

The @require paths can reference *.user.js or simply *.js files, and any UserScript-style comment headers in these files have no effect.

From the main script's ==UserScript== header, all @require files are text-concatenated in the order specified, with a single newline separating each file. This amalgamation is then executed as one large script. Note that this means any function or variable declared in the outermost scope of any file behaves as if it was declared in the outermost scope of every file, and certain syntactic errors in one file may influence how subsequent files are interpreted. Additionally, to enable Strict mode on all of your files, 'use strict'; must be the first statement of the first file listed with @require.

After all @require files are run, the primary UserScript (the one accessed by TamperMonkey's editor) is run in a separate context. If Strict mode is desired, it must also be enabled here.

Given such opportunity for confusion, it is good practice for each file to wrap all code within an IIFE (and a function-level 'use strict';) in order to limit scope to individual files.

Workflow

Now every time that script matches (@match), TamperMonkey will directly load and run the code straight from the file on disk, whichever path is in @require.

I use VSCode (arguably the best multiplatform code editor ever. 100% free and open-source), so that's where I work on the script, but any text editor will do. It should look like this:

enter image description here

Notice how TM's editor and your IDE/Editor have the same header. You can now close the TM's editor. If everything is correct, you won't need it open anymore.

Now, every change in the code is saved automatically by this particular editor. If yours doesn't autosave, remember to save before going to the browser to test it.

Lastly, you'll have to reload the website to see the changes.

If you're not using git, you should consider using it with your userscripts, beneficial tool for a sane development process, and GitHub to release new updates to your users for free automatically!

And please share all your creations :)

Bonus tips!

Working with GitHub or other SCMs

You have to add an @updateURL tag followed by the URL with the raw file from GitHub or whatever provider you chose. GitHub's example:

enter image description here

Note that a @version tag is required to make update checks work. The vast majority of users won't need the @downloadURL tag, so unless your script has a massive follower base, use @updateURL.

TM will check for updates as often as it's configured; from the settings tab:

enter image description here

Externals, sets how often the scripts called from your script's @require are checked to update (e.g., jQuery).

You can also "force" an update check:

enter image description here

Using external libraries (like jQuery)

It must be present at least in TM's editor for Chrome to load it. However, I recommend keeping both headers (the TM's and the file on disk's header) the same to avoid confusion. Then, you just @require it like this:

// @require      https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js