1 Introduction
I usually use Obsidian (Markdown) to write blogs under macOS. It is inevitable to insert pictures during the writing process, so the image hosting solution becomes an unavoidable issue.
My blog's final image hosting is Cloudflare R2 But in order to achieve Disaster recovery backupThe actual process is a little more complicated: when I write, the pictures will first be uploaded to the home data center. Chevereto Image Hosting(Reference article:Chevereto+PicGo+Obsidian is a series of tricks to achieve efficient image upload and image URL acquisition), and then use rclone to copy the pictures in Chevereto image storage to R2 (reference article:Home Data Center Series Use rclone and cloudflare R2 to build Chevereto's remote disaster recovery image bed).
In other words, when I write locally, I always rely on the Chevereto image hosting in the local network, and How to upload the images inserted by Obsidian to Chevereto smoothly and generate links, it depends on the Obsidian Image Auto Upload Plug-in coordination PicGo App To complete:

This is the key roleImage Auto UploadIf you select "PicGo (App)" as the default uploader in the plugin settings (see the picture above), it will work normally in most cases. But the problem is that it occasionally reports an inexplicable error:
upload failed, check dev console
As shown below:

This problem is not uncommon. A Google search yields a lot of similar feedback:

Common "solutions" are nothing more than: restarting Obsidian, disabling/enabling plugins, or even restarting the entire system, or simply uninstalling and reinstalling the PicGo App. But in essence, this is Unstable communication between the Image Auto Upload plugin and the PicGo appI have encountered this problem several times before, and I can recover by restarting macOS, so I am too lazy to investigate it further.
However, recently after upgrading the m4pro macmini OS version to Tahoe 26, this familiar bug appeared again:"upload failed, check dev console"To be honest, this little problem has happened more than once. Every time I have to restart or reinstall the plug-in, it is very annoying. In this case, I simply stopped fighting with PicGo App and switched to another upload mode supported by the plug-in:PicGo-Core.
This method completely bypasses the desktop app and does not rely on the local loopback interface. Instead, it directly calls the core upload logic of Node.js. It is purer and reduces the intermediate links that may cause problems.
💡 Additional Notes:
PicGo-Core It can be understood as the "command line core version" of PicGo: it is not a desktop application with an interface, but a Node.js-based upload engine. All image upload logic is executed by it, and plug-ins only need to be called directly.
In contrast,PicGo App It's more like a UI encapsulation layer for PicGo-Core, and plugins must communicate with it through the local loopback interface. This brings two problems: first, some systems/browsers restrict local communication; second, the communication chain has an extra layer, which is more prone to errors.
Therefore, the advantages of PicGo-Core are: lightweight, direct, independent of local apps, and can even run in a headless server environment, with higher stability.
2 Install PicGo-Core under macOS
2.1 Overview
Generally speaking, the advantage of global installation (sudo npm install -g picgo) is that the command is available everywhere, and you can directly type picgo in any directory. However, the disadvantage is also obvious. The configuration path and dependency path are scattered in the system directory. Once the system or Node.js version is upgraded, permission problems may occur or the path may not be found.
Installing locally (to your user directory, such as ~/.picgo/) is more self-sufficient: configuration files, plugins, and core programs are all in one place, making them relatively unaffected by system upgrades and permission changes. The only trade-off is that you need to remember the full path to the plugin (e.g., ~/.picgo/node_modules/.bin/picgo), but this can be easily resolved with plugin settings or aliases.
Especially in macOS with M series chips (such as my m4pro Mac mini) On the other hand, global installation often leads to pitfalls:
- The system has tightened write permissions on directories such as /usr/local/lib. The sudo npm install -g command either directly reports an error or installs the Obsidian plugin but the plugin cannot be found.
- The Obsidian plug-in runs in the Electron sandbox, and sometimes it cannot read the global PATH of your shell environment, resulting in the plug-in still reporting "cannot find picgo" even though it is installed.
- Even if it can barely run, it is easy to encounter the situation where the global path becomes invalid after upgrading Node or macOS.
for example:

So, after stepping on the pit of "global installation" for a long time, I finally choseLocal installationThis is more stable and more in line with macOS's trend of "gradually tightening permissions."
2.2 Install brew and node.js (optional)
Since npm is needed to install picgo-core and related plug-ins, and npm is the package manager of node.js, macOS does not integrate node.js by default, so it needs to be installed first.
- Install brew(Optional, skip if already installed)
MacOS official page link directly on its github (https://github.com/Homebrew/brew/releases/download/)Download the pkg installation package. The current latest version is 4.5.15. After downloading, just click to install.
Note: I am used to using brew to install node.js. If brew is already installed, you can skip this step.
- Install Node.js
To install Node.js version 20, run the following command:
brew install node@20
Currently, some of PicGo's dependencies are still based on CommonJS, while newer versions of Node.js have a stricter ESM module loading strategy. In Node 22+ environments, an ERR_REQUIRE_ESM error may occur. Therefore, using Node.js 20 LTS version can avoid this problem.
If you have Node 22+ installed and encounter the error ERR_REQUIRE_ESM when starting PicGo, the solution is to install Node.js 20 LTS. You can refer to the following steps:
brew install node@20 brew link node@20 --force --overwrite
Then use the following steps to confirm:
node -v which node
If successful, the output will look like the following:
v20.20.1 /opt/homebrew/bin/node
2.3 Local installation method to install picgo-core and chevereto plug-ins
- Create a directory
The local mode of PicGo-Core is recommended to be placed in the user's home directory .picgo Folder:
mkdir ~/.picgo
- Create a valid package.json file
Directly~/.picgoCreate a new package.json file in the folder:
touch ~/.picgo/package.json
The content is as follows:
{ "name": "picgo", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC", "type": "commonjs", "dependencies": { "picgo": "^1.5.9", "picgo-plugin-chevereto": "^1.1.0" } }
Note: The reason for not usingnpm init -ycommand to initialize package.json, because in the new version of Node.js / npm (such as Node 24 with npm 11), if the name field of package.json starts with a dot (i.e. .picgo), it will be judged as an illegal name, which will directly cause npm init -y to report an error similar to: "Invalid name: '.picgo'". However, Obsidian requires PicGo's main directory to be in order to work properly with PicGo-Core.~/.picgo(This is a very deep pit, it took me several days~), so I can only create the package.json file manually.
- Install PicGo-Core and plugins
Install PicGo-Core and required plugins in this directory (here we take Chevereto plugin as an example):
cd ~/.picgo npm install picgo picgo-plugin-chevereto

- Confirm the installation path
After the installation is complete, the executable file of PicGo-Core will be~/.picgo/node_modules/picgo/bin/picgo, you can confirm it with the following command:
ls -l ~/.picgo/node_modules/picgo/bin/picgo

Then in WordPress plugin image auto upload In the settings, as long as you specify this path, you can directly call PicGo-Core to upload pictures.
2.4 Setting up the "picgo-plugin-chevereto" plugin
After installing PicGo-Core locally and importing the picgo-plugin-chevereto plugin, you need to configure the plugin's uploader to upload images to Chevereto. You can interactively set the uploader information using the command line tool provided by PicGo-Core.
It's worth noting that, in theory, when you run the command picgo set uploader chevereto , PicGo-Core will interactively prompt you to enter Chevereto's API URL and key, automatically generate or update the configuration file (config.json), and write the PicGo-Core plugin information, thus completing the uploader initialization. However, in some environments, such as using a non-default directory (such as ~/picgo instead of ~/.picgo) or other system differences, this command may not generate the configuration file properly, reporting a "No uploader named chevereto" error, similar to:

In this case, you can manually create a valid config.json file first (a bit like taking off your pants and farting~), and then explicitly specify the configuration file path in the command, so that PicGo-Core can correctly load the plugin and uploader, ensuring that there will be no problems when calling the Obsidian plugin.
First create a config.json configuration file:
touch ~/.picgo/config.json
The configuration file format is demonstrated by my own use (the content after url and key can be real or not, because the purpose of the config.json configuration file here is mainly to allowpicgo set uploader cheveretoThe command can enter the interactive setting process normally):
{ "picBed": { "uploader": "chevereto", "chevereto": { "url": "http://192.168.10.99:8090/api/1/upload", "key": "1234567890", "source_param": "", "url_param": "" }, "current": "chevereto" }, "picgoPlugins": { "picgo-plugin-chevereto": true } }
Then set up the uploader using the following format:
~/.picgo/node_modules/.bin/picgo set uploader chevereto --config ~/.picgo/config.json
After execution, you will be prompted to enter the Chevereto API address, API Key, uploaded file field name and other information:

Note: During the interactive setup process, if the content following the url and key fields in the config.json file is real information, you only need to press Enter throughout the process; if it is not real information, then the setup process requires manual entry of the real content.
2.5 PicGo-Core upload function verification
After completing the installation of PicGo-Core and the configuration of the plugin, the first step is to verify whether the image hosting interface can work properly. curl The command directly calls the chevereto API to upload a picture and confirm that the server interface is ok. Take my chevereto image hosting address as an example (the first-FBehindxxxxxxxxis the key corresponding to the chevereto photo album):
curl -X POST "http://192.168.10.99:8090/api/1/upload" \ -F "xxxxxxxx" \ -F "source=@/Volumes/data/ishot/chatgpt.png"
If the upload is successful, the terminal will return JSON data similar to the following, which contains the URL of the image (the actual URL is in regular format):
{ "success": true, "image": { "url": "http://192.168.10.99:8090/images/2025/09/19/chatgp.png", ... } }
As shown below:

After confirming that the API is available, you can use PicGo-Core Now, let’s test the upload. Since we installed it locally to ~/.picgo/, the command is as follows:
~/.picgo/node_modules/.bin/picgo upload /Volumes/data/ishot/chatgpt.png --config ~/.picgo/config.json
If PicGo-Core is configured correctly, a success prompt will be displayed on the terminal after the upload is complete, and the URL of the returned image will be similar to the following:
[PicGo SUCCESS]: http://192.168.10.99:8090/images/2025/09/19/chatgptc13e706aae1fefad.png
As shown below:

Through these two steps of verification, we can confirm:
1. Chevereto API works properly
2. PicGo-Core and picgo-plugin-chevereto plugins are configured correctly and can successfully upload pictures
3. When the Obsidian "image auto upload" plug-in calls PicGo-Core to upload, the image URL can also be generated smoothly.
Here we use curl The purpose of testing the API is to confirm that the image hosting interface itself is functional, ruling out network or Chevereto configuration issues. PicGo-Core also relies on the same API for uploads. If the curl test fails, PicGo-Core will fail regardless of any configuration. This step was necessary because after upgrading the M1 Mac Mini used to host Chevereto to a Tahoe 26, insufficient internal 256GB hard drive caused Docker Desktop for Mac to malfunction. This, in turn, caused issues with the Chevereto container, leading to considerable research.
Then use PicGo-Core command lineUpload and verify that the plugin and local core program are running correctly and can generate the image URLs required by Obsidian. This order also facilitates troubleshooting: first confirm that the server is normal, then confirm that the local PicGo-Core configuration is correct, thus ensuring that subsequent Obsidian plugin calls will not fail due to interface or local environment issues.
2.6 Obsibian "image auto upload" plugin settings
At this point, there is only one step left: modify the "image auto upload" plug-in settings in obsibian. You need to modify 3 places:
1. The default uploader is changed to "PicGo-Core"
2. Picgo-Core path fill in the path of the locally installed Picgo-core:
~/.picgo/node_modules/.bin/picgo
3. And open the "Modify PATH" option
As shown below:

At this point, you are done, and you can happily use ishot to take screenshots and paste them directly into obsidian.
3
4. Afterword
This incident is actually a typical example:A seemingly insignificant problem actually involves plugin calling methods, inter-application communication, and system security policies.I used to use the PicGo app with the Obsidian plugin when writing, and while it would occasionally show errors, a reboot usually fixed them. However, after upgrading to the Tahoe 26, the "upload failed, check dev console" error reappeared. This finally convinced me to stop procrastinating, carefully review the entire process, and find a more reliable alternative.
Final replacement PicGo-CoreThis makes the process much simpler: there's no cross-application API communication, and no reliance on local loopback interfaces; all logic is executed directly by the Node.js core program. This allows the Obsidian plugin to simply call core functions, improving stability and controllability.
In terms of positioning,PicGo App is more suitable for users who are accustomed to visual configuration and drag-and-drop upload;and PicGo-Core is more suitable for command line users and automation scenariosStrictly speaking, there is no absolute difference between the two, but in terms of my own experience,PicGo-Core is significantly more stable and controllableEspecially in a high-frequency, continuous scenario like writing, the most important thing is to have less trouble and fewer errors.
For me, the rhythm of writing is more important than anything else, and tools should be quiet and reliable. Now that this Obsidian + PicGo-Core + Chevereto connection is running smoothly, at least for the foreseeable future, my train of thought will no longer be interrupted by "upload failed" errors.
In the end, it proved an old truth:Sometimes, instead of constantly tinkering with old solutions, it’s better to change your perspective and simply take a more stable path..
By the way,The steps for deploying and configuring PicGo-Core and Obsidian plugins under Windows are similar., first install Node.js, then perform local or global installation, plugin configuration, and upload test. However, the Windows environment may encounter some small pitfalls, such as path separators, administrator permissions, firewalls or antivirus software blocking Node.js network access, etc. Since I don’t usually write on Windows and I’m too lazy to verify these details, this article will not expand on the operation of the Windows platform. In contrast,Installing PicGo-Core locally on macOS is more convenient and less troublesome, which is also the reason why this article chooses the practice platform.