A Reverse Engineering Question

If I try to compile or run it, it immed brings up a syntax error in a dialog box:

Error on line 1: SyntaxError: Unexpected token ')'

and it selects the first line:

(() => {

Hi Peter, Did my answer clarify? There's one trigger in particular - the one I referred to earlier, 'Clear.'

It's strange...the macro is just a simple toggle:I have an icon that executes the trigger file. Click the icon once and everything (including palettes, get info, finder boxes, apps...)immediately hide. Click it again, and they reappear. I'm sure I can reconstruct it.

Today, I was thinking, I somehow used the F11 or F12 key to switch to another desktop but the thing is, all my desktop icons remain stay in tact and so, I' must be in the same desktop. I'll figure it out....

That's what prompted me to ask the Q. I wondered, can I take the trigger file and somehow retrace my steps to find the macro....but that's turning out to be more work than just creating a new one.

Any thoughts, mind if I ask?

My OS: Yosemite: 10.10.5

Is my OS too ancient for your macro?

Addendum: I figured out the one trigger file that was bugging me, that I couldn't trace to a macro (Named 'Clear'). The macro clears everything that's hiding the desktop (except DT icons). Also, it's a toggle: The second time you execute it, everything reappears.

I feel silly: It's just one simple simulate-keystroke: Command/F8 is part of the Yosemite OS--Clear Desktop. Anyway, at least I learned a ton, thx again for the help.

...it would be interesting to know, is it possible to recreate a macro from the trigger file but I'm not as concerned as before....thx again.

A kmtrigger file is just a UUID of a macro to execute. It contains no actions to reverse engineer. It is just another way to execute a macro.

thanks...someone else said that as well...that makes sense. Is there a way to get the UUID from the trigger file?

I think so : -)

(It assumes macOS Sierra onwards)

Here is an automatic translation to a Classical ES5 JS by Babel – if you find that it works on your system in Script Editor, you could paste it into the JS action in that macro:

(function() {
    'use strict';

    // Name(s) of macro(s) for .kmtrigger file(s) selected in Finder
    // Rob Trew 2019
    // Ver 0.1B (Automatic translation to Classical ES5 by Babel JS)
    // main :: IO ()

    var main = function main() {
        return unlines(concatMap(function(fp) {
            return fp.endsWith('.kmtrigger') ? [takeFileName(fp) + ' -> ' +
            ] : [];
        }, selectedPaths()));

    // KEYBOARD MAESTRO FUNCTIONS -------------------------
    // kmMacroFromUUIDLR :: String -> String -> Either String Dict
    var kmMacroFromUUIDLR = function kmMacroFromUUIDLR(strUUID) {
        var js = ObjC.unwrap,
            ms = concatMap(function(group) {
                return maybe([], function(x) {
                    return x;
                }, foldl(function(m, x) {
                    return m.Nothing ? strUUID === x.UID ? Just(x) : m : m;
                }, Nothing(), group.Macros || []));
            }, ObjC.deepUnwrap(
                            $.NSUserDomainMask))[0].path) +
                    '/Keyboard Maestro/Keyboard Maestro Macros.plist')
        return 0 < ms.length ? (
        ) : Left('No match found for ' + strUUID);

    // kmMacroNameFromUUID :: UUID String -> Either Name Message
    var kmMacroNameFromUUID = function kmMacroNameFromUUID(uuid) {
        return either(function(x) {
            return 'Error :: ' + x;
        }, function(x) {
            return x;
        }, bindLR(kmMacroFromUUIDLR(uuid), function(m) {
            return Right(m.Name);

    // JAVASCRIPT FOR AUTOMATION --------------------------

    // selectedPaths :: () -> [pathString]
    var selectedPaths = function selectedPaths() {
        return Application('Finder').selection().map(function(x) {
            return decodeURI(x.url()).slice(7);

    // GENERIC FUNCTIONS ----------------------------

    // https://github.com/RobTrew/prelude-jxa
    // Just :: a -> Maybe a
    var Just = function Just(x) {
        return {
            type: 'Maybe',
            Nothing: false,
            Just: x
    }; // Left :: a -> Either a b

    var Left = function Left(x) {
        return {
            type: 'Either',
            Left: x
    }; // Nothing :: Maybe a

    var Nothing = function Nothing() {
        return {
            type: 'Maybe',
            Nothing: true
    }; // Right :: b -> Either a b

    var Right = function Right(x) {
        return {
            type: 'Either',
            Right: x
    }; // bindLR (>>=) :: Either a -> (a -> Either b) -> Either b

    var bindLR = function bindLR(m, mf) {
        return undefined !== m.Left ? m : mf(m.Right);
    }; // concatMap :: (a -> [b]) -> [a] -> [b]

    var concatMap = function concatMap(f, xs) {
        return xs.reduce(function(a, x) {
            return a.concat(f(x));
        }, []);
    }; // Briefer but slower:
    // concatMap :: (a -> [b]) -> [a] -> [b]
    // const concatMap = (f, xs) =>
    //     [].concat(...xs.map(f))
    // either :: (a -> c) -> (b -> c) -> Either a b -> c

    var either = function either(fl, fr, e) {
        return 'Either' === e.type ? undefined !== e.Left ? (
        ) : fr(e.Right) : undefined;
    }; // foldl :: (a -> b -> a) -> a -> [b] -> a

    var foldl = function foldl(f, a, xs) {
        return xs.reduce(f, a);
    }; // maybe :: b -> (a -> b) -> Maybe a -> b

    var maybe = function maybe(v, f, m) {
        return m.Nothing ? v : f(m.Just);
    }; // readFile :: FilePath -> IO String

    var readFile = function readFile(fp) {
        var e = $(),
            uw = ObjC.unwrap,
            s = uw($.NSString.stringWithContentsOfFileEncodingError($(fp)
                .stringByStandardizingPath, $.NSUTF8StringEncoding, e));
        return undefined !== s ? s : uw(e.localizedDescription);
    }; // strip :: String -> String

    var strip = function strip(s) {
        return s.trim();
    }; // takeFileName :: FilePath -> FilePath

    var takeFileName = function takeFileName(strPath) {
        return '' !== strPath ? '/' !== strPath[strPath.length - 1] ? (
        ) : '' : '';
    }; // unlines :: [String] -> String

    var unlines = function unlines(xs) {
        return xs.join('\n');
    }; // MAIN ---

    return main();

(It assumes macOS Sierra onwards)

out of my league...thanks tho...I'll stash it away... :yum:

I was wondering: Is there a way to un-trigger a trigger file such that it reverts to its original bare KM macro format? Thank you much.....

Maybe I am missing a very huge elephant in the room, but…

I don’t get the problem/question.

As already pointed out by others, a KM trigger file (for example MyMacro.kmtrigger) contains nothing more than the UUID of a macro. The filename extension makes the system launch the corresponding macro.

So, what could be reverse-engineered here? If you want to change the UUID, just open the file in the text editor or hex editor of your choice and replace the UUID with the UUID of the macro you wish to point to. (The name of the trigger file is irrelevant.)

(If you are using a text editor, make sure it doesn’t auto-add a line break, like for example with well-intentioned nonsense features/options like BBEdit’s “Ensure file ends with a line break”.)

1 Like

Maybe I am missing a very huge elephant in the room

Correct. You are missing the elephant.

Give me a little hint: is it pink or rather white?

It doesn't answer to a colour, but it does have a UUID.

OK, this was helpful :slight_smile: Slowly but steadily I’m getting what @Clint wanted. Seems I was to much focused on “Is there a way to get the UUID from the trigger file?”.

Should have payed more attention to the function names in your script :wink:

1 Like

Slowly but steadily I’m getting what he wanted.

it's impolite to refer to elephants' colors, in the third person, especially when they're standing right there in the living room...just kidding. I'm getting tired and my NYC humor is :slight_smile:

1 Like

I corrected my grammar/style. I apologize. My excuse is that these days I’m posting from an iPhone, and I was simply too lazy to type it the correct way. :innocent:

no worries...just kidding. I think I'll change my icon to Ghandi or Mother Teresa...the Clint thing is too scary.

Yoko Ono would be a nice compromise :upside_down_face:

thanks...I'll consider it...especially since, after several decades, I'm finally warming up to her. Recently saw a YouTube vid where Yoko, her son, Sean, Julian Lennon (Sean's Brother) and Julian's mother - after years of bitterness, "gave peace a chance." They hung out, hugged & were openly affectionate at Julian's 1st photo exhibition. It was really quite touching (but 9 years old: 2010)