Support env for API key management

Plugins sometimes need to access API, e.g. GitHub, Google, OpenAI. For security, the tokens need to be kept in an env file so that it can be gitignore’d. Some plugins, like Enveloppe, have their own env file. Is a global env file a good idea?

If the env an be outside of the vault folder so that it can be shared on multiple vaults, then it can be great.

Please include the template when posting bug reports or feature requests. Thanks!

Is this better? I didn’t use the template because I think it make the request unnecessarily lengthy. Also, why is it better on the help category and not the feature request one?


Use case or problem

Some plugins need access to APIs (e.g., GitHub, Google, OpenAI). To maintain security, API tokens are typically stored in an environment (env) file, which can then be ignored by version control using .gitignore. While some plugins, like Enveloppe, have their own dedicated env files, managing multiple env files across plugins can become cumbersome. A global env file could simplify token management and make it easier to use plugins across multiple vaults.

Proposed solution

Introduce a global env file that can be used by all plugins, stored outside of the vault folder. This would allow multiple vaults to share the same configuration, reducing redundancy and streamlining the management of API tokens. Each plugin could access the global file, eliminating the need for separate env files for every plugin.

Current workaround (optional)

Currently, plugins like Enveloppe have their own individual env files. Users need to manually manage these files, duplicating tokens across plugins and vaults, which can be inefficient and error-prone.

Related feature requests (optional)

I am gonna move this thread to developers and api.

There are many ways to save API tokens in an Obsidian plugin:

  • Plugin settings (possibly w/obfuscation); Pros: syncs to mobile, easy access. Con: can’t be easily shared across vaults
  • Local storage; Pros: not too hard to access, accessible between vaults. Con: extra coding complexity, especially if you want different keys in different vaults.
  • OS-level Environment; Pros: easy to access, never synced, global to all vaults. Cons: hard for users to configure, never synced, and global to all vaults.

I wouldn’t think of .env files as being in the top three - they are among other things, only really usable in desktop (on mobile you can’t access arbitrary files), hard for users to create and edit, and add more complexity to your plugin to access them, especially in arbitrary locations.

Finally, if you are only supporting desktop and no sync to other machines, you can potentially also use Electron safeStorage encryption to encrypt keys while they are saved in settings or localStorage. (But then you can only access them on the same desktop where you encrypted them.)

1 Like

What is the difference between and env? Isn’t that env, json, xml and the like are really just plain text local storage?

I want the keys to be accessed between vaults, and I don’t have the need to sync. I guess the plain text format is the most convenient way to edit, so perhaps the local storage is the best. What would be the best way to implement local storage? I guess I have to write a cron job to check for changes in the local storage and update plugin settings? The same thing applies with OS env?

I guess, what was meant is window.localStorage

There are even some helpers

I see. Where is that localStorage stored, that any vault can access it? Also isn’t it bad for security?

It is stored in the Obsidian executables folder. If you worry about security, don’t save anything sensitive there

Plugins can access anything on your hard drive anyway, so not sure what you mean by security here. If you use a .env file with the settings then any plugin in any vault could potentially read it, just like with localStorage.

localStorage is just more convenient to use because you can literally just assign something like localStorage["my-special-name-goes-here"] = JSON.stringify(whatever) and read it back with JSON.parse(localStorage["my-special-name-goes-here"] || JSON.stringify(defaultValues)). No async or await needed, let alone node APIs for reading files outside the vault. Just make sure the name you use is unique – i.e. it should include a plugin ID, domain name, or other unique identifier you own, so that it won’t collide with other plugins or Obsidian’s internal uses of localStorage.

(Also, note that those localStorage helpers @mnaoumov shared are for vault-specific values: you can’t use them to share configuration across vaults.)

Anyway, the idea with using localStorage for configuration is that your plugin’s settings UI can just update localStorage, and then the user doesn’t have to edit files on disk or manage that themselves. You could even do a thing where they can set up multiple API keys in local storage, and then have the vault-specific configuration (in data.json) say which API key to pull from local storage.

This gives them the best of all worlds, more-or-less. It’s not kept in the vault or synced directly, it’s obscured in the Obsidian appdata db. Users who only have one vault aren’t forced to set up .env files or environment variables. Users who sync do need to set up keys on their other devices through the settings, but that’s it.

All that being said, there are many ways to address this, I’m just noting what I would (probably) do if I had these kind of requirements. I do have a couple plugins that use localStorage for settings, either to share them between vaults (special hotkey settings) or for settings that are actually machine-specific (like what the path to a local progam is) and should not be synced to other machines, but should be shared across all vaults on the same machine.

1 Like

If localStorage is that convenient, then why can’t it be used for global config? Apparently we can have that in VS Code

If localStorage is that convenient, then why can’t it be used for global config? Apparently we can have that in VS Code

I can be used for global config. However it won’t be sync’d. If it’s not on the filesystem in the vault folder, it’s not going to be sync’d.

1 Like