[SOLVED] Using kid3 cli with KM

A few days ago I was having an issue with ffmpeg-normalize that worked with Terminal, but not KM, but that was then fixed with the help of some members here in the forum.
Now I'm experiencing something similar while trying to use kid3 cli.

Here's the script I ended up with:

kid3-cli -c "set title 'Old Boy'" \
	-c "set artist 'Danny Wyatt'" \
	-c "set albumartist 'Danny Wyatt'" \
	-c "set album 'Here we go'" \
	-c "set date '2023'" \
	-c "set comment 'www.iamdannywyatt.com'" \
	-c "set picture:'/Users/dannywyatt/My Files/Danny Wyatt - Galaxies - Cover Artwork.png' ''" \
	"/Users/dannywyatt/My Files/Drop Folder*"

When I run it I get this:
Execute a Shell Script failed with script error: text-script: line 1: kid3-cli: command not found

Any idea how to fix this?
The fix to the ffmpeg-normalize was to add this line to the beginning of each script using ffmpeg (maybe this helps understand what's happening?)
export PATH="/opt/anaconda3/bin:$PATH"

I don't know if this helps, but when I search for kid3, the only path I get is this:
/usr/local/Caskroom/kid3/3.9.4/kid3.app

Sounds like you either don’t have your environment path variable setup in KM or it needs to be updated.

See the following post, and if you need further help, don’t hesitate to reply and we can walk you through it.

KMF: Create a PATH Environment Variable for Keyboard Maestro and Add /usr/local/bin to the Default Path - Questions & Suggestions

1 Like

Thanks for sharing that link. I will read it now.
Meanwhile, on my other topic, @Tom mentioned this (which I still haven't researched enough):

Is this related to what you just said?
I'm very "clueless" when it comes to the whole command line world, so it's still very hard to understand some technicalities...

Ok so I read what you shared, but as I mentioned, this is all pretty hard to understand as I don't really use shell enough to fully understand how this works.
I am able to test a few scripts in Terminal until they work, but the "under the curtain" stuff, is pretty foreign to me, including the whole $PATH thing.

I was also reading this topic, which seems to include a tool to check the path in Terminal and KM, but how would the script know if I'm checking the path for ffmepg-normalize or kid3 cli?

Also, if I do create the ENV-PATH variable, would I be adding multiple paths to it much as the path for ffmpeg-normalize, kid3 cli, etc?

Can you walk me through and if possible, clarify what is happening?
Thanks

The short version is Terminal knows where your command line apps are located, and you don’t need to specify their path(s) when running commands. So when you run the following command kid-3cli, Terminal already knows that it’s located at /usr/local/Caskroom/kid3/3.9.4/kid3.app.

Keyboard Maestro does not know these paths however, unless you tell it where they are. The easiest way to do this is to just replicate your $PATH variable from Terminal (which is typically updated automatically when you install CLI tools/apps) to the Keyboard Maestro global variable called ENV_PATH.

For an easy way to do this, try the following macro. There are more eloquent options out there to do this, but this is just a simple one I wrote up real quick to walk you through it. Also, you should only have to do this when you install new CLI apps.

EDIT: As a safeguard, if you for some reason already have the ENV_PATH variable set in KM, then it is saved to a new variable called DND__Old_Env_Path so you can compare the two afterwards and restore any changes made if needed.

Download Macro(s): Save path from Terminal to Keyboard Maestro.kmmacros (4.8 KB)

Macro-Image

Macro-Notes
  • Macros are always disabled when imported into the Keyboard Maestro Editor.
  • The user must ensure the macro is enabled.
  • The user must also ensure the macro's parent macro-group is enabled.
System Information
  • macOS 13.6
  • Keyboard Maestro v11.0.1
1 Like

Ok so I ran your macro and now I have this:
image

I ran the macro to edit the tags and it seems to be working now :slight_smile:
Thank you so much!!!

So I have a few questions, if you don't mind answering, so I can learn a bit more:
1 - So I should run this macro every time I install a new command line? So you're saying that the path changes? It seems that it is a bunch of paths together separated by : so that means if I install a new command line, that will be appended to that list, is that it?
2 - Now that I have the variable, does it mean I can remove this from my macros?
export PATH="/opt/anaconda3/bin:$PATH"
3 - Can I also remove this from my scripts?
/opt/anaconda3/bin

So basically going from this:

export PATH="/opt/anaconda3/bin:$PATH"
/opt/anaconda3/bin/ffmpeg-normalize "$KMVAR_Local__basename - Dropbox".mp3 -f -c:a libmp3lame -b:a 320k -nt peak -t -1 --output "$KMVAR_LOCAL__frontWindowPath/_Normalized/$KMVAR_Local__filename - Dropbox".mp3

To this:

ffmpeg-normalize "$KMVAR_Local__basename - Dropbox".mp3 -f -c:a libmp3lame -b:a 320k -nt peak -t -1 --output "$KMVAR_LOCAL__frontWindowPath/_Normalized/$KMVAR_Local__filename - Dropbox".mp3

Techically, with that ENV_VAR, whatever I type in Terminal, would be equally valid with KM, without any extra paths or workarounds. Is that right?

4 - From what I got from another topic, this path:
/opt/anaconda3/bin:/opt/anaconda3/condabin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/Apple/usr/bin is all a bunch of paths, divided by a colon.

So what I have here is all paths where KM is looking at, trying to find the command lines?
/opt/anaconda3/bin
/opt/anaconda3/condabin
/usr/local/bin
/usr/bin
/bin
/usr/sbin
/sbin
/Library/Apple/usr/bin

If that's the case, since the path to kid3 is
/usr/local/Caskroom/kid3/3.9.4/kid3.app
shouldn't at least /usr/local be there as well? The one I see using "local" also has "bin" in front of it, which the kid3 path doesn't have.

I mean, the macro is now working. I'm just trying to understand a bit more of what this means.

That would depend on where the new CLI tool is installed. Some of them may be installed in paths that already exist in your KM variable, and thus not warrant an update. Most CLI tasks installed via HomeBrew are located in the same location, so if you install them via that method, you probably won’t have to update this very often. FWIW, I got a new MacBook back in July, setup my path once and haven’t touched it since.

Should be fine, but to be sure, just comment out the export PATH portion (prepend that line with a pound sign #) and run each macro in question once or twice to make sure they work without it.

Same as above.

That’s correct.

I would think so, but, I know only the basics of shell scripts myself, so I’m not 100% certain why it would work without that path in the variable.

1 Like

Ok so basically, if a new path is indeed added, it will always be added to that list, meaning that old paths will not be removed, so old macros will not be affected, right?
So if I had
path 1 : path 2 : path 3
and now I installed a new command line that indeed had another path and my new macro using that new command line isn't working, when I run your macro, it updates the list like
path 1 : path 2 : path 3 : path 4
Correct?

If so, that means that I don't have to worry about old macros, unless, of course, I delete those command lines completely.

So the variable ENV_PATH would now be
path 1 : path 2 : path 3 : path 4
and the DND__Old_Env_Path would be
path 1 : path 2 : path 3
Correct?

Sounds good. I will do that. Thanks for the tip!

I mean, it is working now, regardless, so I guess the ENV_PATH variable is doing its job :wink:

Thank you so much for your time and help!
This really helps me save some extra time and work on some macros I need.
And it's always good when I can at least understand a bit more of what I'm adding, instead of just copying and pasting.
Appreciate it!

This is a very simple ENV_PATH, as I'm using it for years:

~/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin

The ~/bin is a personal thing, I have some custom programs there. The other paths are standard paths.

The order is important, because when you install something via package managers like Homebrew, then it usually goes into /usr/local/, and you want to give preference to that, because the binaries are usually more up-to-date than the ones from Apple in /bin or /usr/bin.

If you have a package manager that installs binaries into /opt (I think Homebrew did this a decade ago, or MacPorts, not sure), or you have installed something there for other reasons, then you want to add /opt. But normally™️ you don't need "exact" paths like /opt/anaconda3/bin.

2 Likes

That is correct, because package managers will typically add any new paths to the existing $PATH variable in your shell. I’m not sure if the order changes because I’ve never paid that much attention to it, but the point is, running that macro again will include any new paths that have been added to your $PATH shell variable.

1 Like

Thank you again for your help.
Super useful!

That is all a lot of information to digest as a "newbie".
I will maybe try your example, without the ~/bin option and then retry my macros to see how it goes.
I also noticed that my path contains this, which yours doesn't:
/Library/Apple/usr/bin

Mine right now is:
/opt/anaconda3/bin:/opt/anaconda3/condabin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/Apple/usr/bin

Should I keep that?
Or maybe use yours, try my macros, and if it works like that, leave it as simple as possible?

I also noticed that my path contains this, which yours doesn't: /Library/Apple/usr/bin

On my (Ventura) system, /Library/Apple/usr/bin contains just one binary: rvictl. According to this, it is something that was installed by Xcode.

Whatever, it looks to me like that path is meant for "internals" (binaries used by Apple programs, such as Xcode). The linked info says that it was added to the default shell path in 10.15, but that doesn't mean that this path is something you would ever need in KM. --> I would not add it. (But it doesn't harm either.)

Even if you need it someday for something, remember that you can always prepend the path (like you did before) for any "special" thing. It will overwrite the paths in ENV_PATH for that particular script action.

/opt/anaconda3/bin:/opt/anaconda3/condabin

As said, I would prefer the less detailed path here: just /opt.

You might insist on using /opt/anaconda3 for disambiguation because, for example, you have an older binary in /opt/anaconda2. But this means that you keep the older binary for a reason, and this would be a perfect use case where you want to prepend the path in the particular script action (e.g. in a script where you explicitly want to use anaconda3 and not anaconda2 or anaconda1, or want to use anaconda2 and not 3 or 1).

Using the more generic /opt has the advantage that it would grab also other binaries that you installed there (or that a package manager installed there).

Only valid use cases to use /opt/anaconda3 would be – IMO:

  • You have indeed multiple anaconda versions in /opt, but in 95% of the cases you want to use anaconda3 (but still need to have anaconda2 around).
  • anaconda3 is your only binary in /opt that you ever want to use. But in that case it doesn't matter if you use /opt or /opt/anaconda3.

So, I would give this a try:

/usr/local/bin:/opt:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin

If you have other anaconda versions (that you don't want to use) in /usr/local/bin, then you would have to put /opt first. (But then probably it would be wiser to clean up your anaconda installations :wink: )

without the ~/bin

A custom path like ~/bin (but basically it can be anywhere in your home folder) is useful for example if you download a binary manually (i.e. not with a package manager) and just want to test it.

Just drop it in this folder and it will not get "lost" somewhere in the depths of /usr, but will still be found automatically by KM.

(I also have this path for the interactive shell. For .zshrc or .bashrc or .profile you might have to use $HOME instead of the tilde ~, for /private/etc/paths you might have to use the explicit path.)

2 Likes

Sorry for the late reply.
Thank you so much for all the extra info. This is still a bit confusing to me, but I understand what you explained and I will use the suggested path
/usr/local/bin:/opt:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin

and see if all my macros using the shell script action work as expected.
I also saved the old path on a variable just in case.

Appreciate your time and help!

1 Like