A single button click to reinstall all community plugins after cloning/pulling git repository that ignores plugins

Use case or problem

I ignore the plugins directory of my Obsidian vault by adding .obsidian/plugins/* to my .gitignore, since it may take 10MB (not a lot in relative size in a video game project, but a lot in a pure textual novel project - also some devs like keeping non-modified third-party code in external repositories rather than copying them).

Obsidian already knows which plugins are used thanks to core-plugins.json and community-plugins.json. While core plugins are pre-installed, community plugins are not, and Obsidian doesn’t exploit the data in community-plugins.json to automatically reinstall those plugins.

It makes sense to wait for user approval to start downloading community plugins due to safety risks and bandwidth usage. However, currently, even after enabling community plugins, user needs to manually search and install every plugin by reading the community-plugins.json file, which may be tedious with 10+ plugins (and require to open a .json with an external editor).

Proposed solution

First, Obsidian could showing the list of expected plugins in the Community plugins section, by reading the lines from community-plugins.json. The plugins would appear in a special section “Configured plugins not installed yet” or “Plugins to install” (you can find a better wording) shown above or below the “Installed plugins section”.

One button “Install” to the right of each entry would allow the user to install each plugin easily.

One button at the top “Install all” would even allow them to install all the plugins at once.

Possible difficulty: plugins installed via BRAT, as they would need to go through BRAT. But even if not supported, that would fix 90% of the issue and BRAT devs could then implement an extra button to install the remaining plugins.

Current workaround (optional)

a. Open .obsidian/community-plugins.json, read each line marked “true”, search corresponding plugin (knowing that “ID name” in json is not always 100% matching Readable Name), install, enable
b. (not tested) Follow Reinstall plugins without losing configuration setting the version of each plugin to 0, and force update of all plugins

Related feature requests (optional)

For the “set version to 0” technique we mentioned above

Some users troubled with what to put in gitignore and mentioning they also have a heavy plugins folder.

2 Likes

I have the same issue. I cloned the vault from my github but none of the plugins are installed. This is my .gitignore

# Exclude plugins
.obsidian/plugins/*/*

# Do not exclude the plugins config files
!.obsidian/plugins/*/data.json

# Exclude themes data (actually selected theme is in .obsidian/appearance.json, so it is versioned)
.obsidian/themes

# Exclude workspace cache
.obsidian/workspace.json

# Exclude workspace cache specific to mobile devices
.obsidian/workspace-mobile.json

# Exclude OS settings and caches
.trash/
.DS_Store

It would be nice to see (and be able to copy) the plugin id on the plugin’s page when browsing community plugins.
It would also to be able to search by plugin id.
It would also be nice to have an obsidian URI to install a plugin given its id. Example : obsidian://install-plugin?id=obsidian-excalidraw-plugin

I found a solution workaround!

Use the following script for Linux/Mac users. (I haven’t tested on Mac but it should work.) Create a file called open-plugins.sh at the root of your vault folder, paste the following script and run it from a terminal.

This script will read your community plugins file, open each plugin’s page in Obsidian successively, you only need to click “Install” and “Enable”. Then go back to the terminal, press a key and install the next one! No more searching for plugins!

#!/usr/bin/env bash

# Detect platform and set open command
if [[ "$(uname)" == "Darwin" ]]; then
  OPEN_CMD="open"
else
  OPEN_CMD="xdg-open"
fi

# Read the community plugins from the obsidian vault at `.obsidian/community-plugins.json`
sed -e 's/[][]//g' -e 's/[",]//g' -e '/^\s*$/d' -e 's/^[[:space:]]*//' -e 's/^/obsidian:\/\/show-plugin?id=/' .obsidian/community-plugins.json | while read -r line; do
  echo "$line"
  # Open the plugin link in Obsidian
  $OPEN_CMD "$line" &>/dev/null
  # Wait for the user to press a key before continuing
  read -n 1 -s -r -p "Press any key to continue..." </dev/tty
  # Clear the line
  echo
done

For Windows users, create the file open-plugins.bat and paste this instead (I haven’t tested it because I don’t have a Windows machine at the moment) :

@echo off
REM !!!!! Untested script! I don't have a Windows machine to test it on. !!!!!

REM Read the community plugins from the obsidian vault at `.obsidian/community-plugins.json`
for /f "usebackq delims=" %%A in (`powershell -NoProfile -Command ^
    "Get-Content .obsidian/community-plugins.json | `
    Select-String -NotMatch '^\s*(\[|\]|,|$)' | `
    ForEach-Object { $_.ToString().Trim().Trim('""',',') }"`) do (
    set "plugin=%%A"
    setlocal enabledelayedexpansion
    set "url=obsidian://show-plugin?id=!plugin!"
    echo !url!
    REM Open the URL in Obsidian
    start "" "!url!"
    REM Wait for a key press before continuing
    pause
    endlocal
)

I’ve been using this little script to initialize plugins after cloning my vault. You can just run it in the Obsidian dev tools, it will switch off “safe mode”, download, and enable plugins in community-plugins.json. It uses a bunch of internal APIs so it might stop working later, but its worked pretty well for me so far :sweat_smile:.

async function installPlugin(pluginId) {
    const github = "https://raw.githubusercontent.com";
    const communityPluginsUrl = `${github}/obsidianmd/obsidian-releases/HEAD/community-plugins.json`;
    const plugins = await fetch(communityPluginsUrl).then(r => r.json());
    const info = plugins.find(p => p.id == pluginId);
    if (!info) {
        console.log(`Plugin ${pluginId} not found`);
    } else {
        console.log(`Installing plugin ${pluginId}`);
        const manifestUrl = `${github}/${info.repo}/HEAD/manifest.json`;
        const manifest = await fetch(manifestUrl).then(r => r.json());
        await app.plugins.installPlugin(info.repo, manifest.version, manifest);
        await app.plugins.enablePlugin(pluginId);
    }
}

async function installPlugins() {
    // Turn off restricted mode
    if (!app.plugins.isEnabled()) {
        await app.plugins.setEnable(true)
    }

    // Install all the plugins in community-plugins.json that aren't installed
    for (const pluginId of app.plugins.enabledPlugins) {
        if (!app.plugins.manifests.hasOwnProperty(pluginId)) {
            await installPlugin(pluginId);
        }
    }
}

await installPlugins()
1 Like

I like your solution better because it’s actually platform agnostic.
How do you access the devtools ?

CTRL+Shift+I will open up the devtools and then you can just paste stuff in the console.

1 Like

Somewhat related you might want to look at either the Settings management plugin, which helps changing the configuration quickly. Not sure if you can copy it out and into other vaults easily, but it’s worth taking a look.

Or possibly the Sync config folder to common folder plugin might be of aid, as it can copy all of the config into a common folder, which then should be easier to copy/sync, and which then can be used as a base for the next vault.