Roots Discourse

Developing plugin locally


Apologies if this is a simple question, or something asked frequently, but I’ve been searching through Discourse and all across the internet and can’t seem to find a good way to do this. My wordpress site requires some custom features that, according to best practices, belong inside of a plugin (custom post types, etc.) I’m completely fine with creating a repository for the plugin, adding it to composer’s dependency list, and using composer to dictate the correct version for my production server to use.

The question I can’t find an answer to is: what is the best way to make local changes to the plugin and see them happen instantly (read: without commiting and running composer update)? On the machine I am working on the plugin, should I clone the plugin repo right into the plugin directory? Should I clone the repo somewhere else and symlink it in? I’ve even considered just including it in my Trellis+Bedrock+Sage repo, but that seems like a poor decision. I should note that the plugin will be worked on from multiple machines, so an easily repeatable process is the key.

I found this article that describes what I want at the end, but then I realized that the writer is proposing a solution that doesn’t actually exist at this time.



One suggestion I can make when I’ve worked on plugins separate from the actual project (but still connected in some way) is to use composer install --prefer-source, which will include the git repository when installing packages. So your plugin should be installed with a composer remote in the git repo. So you can make edits to your files, commit and push them, and you won’t have to deal with having the plugin repository stored somewhere else, make your updates, copy them over, commit, composer install, etc. etc.



Oh, that’s interesting. I’ll give that a shot, but it sounds like that be good enough to answer my question. Actually seems like that may have been part of the intention behind creating that flag. Thank you!



I have a similar plugin with a client site’s custom post types and some other functionality that should persist between themes. I’ve kept the plugin in its own repo and listed it in the bedrock composer.json. To see changes immediately while developing locally, I set up an extra vagrant share folder for the plugin in my Trellis vm.

As a side note for context, my understanding is that the recommended practice is to commit a developed Sage theme to the client’s Bedrock project and that you’d probably only really keep the theme separate if it were going to be used in many different projects (e.g., for sale and redistribution).

Back to plugins: A major point of moving some functionality like post types into a plugin is to isolate the more permanent features from the less permanent theme styles. So, to borrow the theme-in-bedrock rationale, if one’s plugin is specific to a client’s project and won’t be widely redistributed, perhaps it should be committed to the client’s Bedrock project as well (?). Maybe the plugin’s distinction of housing the more permanent features/functionality gives it an even stronger argument for inclusion in Bedrock (?).

I dunno, but the client-specific plugin I described above is starting to sound like a good candidate for inclusion in my Trellis+Bedrock+Sage repo, maybe autoloaded as a must-use plugin. Somebody stop me before I make a poor decision.

As @jwkicklighter already considered, if the plugin were part of my Bedrock directory, I’d see local dev changes to the plugin immediately because vagrant syncs the whole Bedrock directory. I wouldn’t have to hack in an extra vagrant share folder for the plugin.

1 Like

How to develop plugins and reload them?

Everyone’s going to have their own opinion. It really depends on the situation and the client. For a lot of client sites where it’s a custom built site, yeah you can probably include any code you won’t be re-using anywhere else. A custom post type for movies? Maybe you’ll reuse it again later on, but it’s also not that hard to set up in the first place. Heck, for a client where you know they’ll be using this custom designed masterpiece for a few years to come, and will most likely do a complete site rebuild following that, I don’t even really know if adding in custom post types to the theme is a terrible sin (although I probably just made @benword real mad with that statement)

In any case, it’s your call, you know what you need to do with your code and if you’ll reuse it or not. Obviously keeping things in one location, even if it’s between multiple projects though, will save time and effort in the long run than copy-pasting

Did I get off topic? :smiley:

1 Like


Loving this discussion, and it’s really making me consider taking the much easier route of just including what would be the plugin inside of the theme. Sage already sets up a good system for breaking functionality into separate files, so it wouldn’t even really muddy up the theme code. And in the future, “plugin” files (code that should be in a plugin) could pretty easily be moved to a new theme and included.

Maybe you’re right :wink:

1 Like


Everything within reason. If you place stuff in a plugin to re-use it later, it’s not like it’s hard to get that stuff from your theme.



Hi @fullyint,

I’m very interested in knowing more about how you

set up an extra vagrant share folder for the plugin

(in your Trellis vm.)

Could you be more precise?





The Vagrant docs on synced folders is the most fundamental resource.

When I wrote the quoted post a couple year ago, I linked the model snippet people could use in customizing their Vagrantfile to add an extra sync folder. However, as of roots/trellis#828, Trellis enables you to set up additional vagrant_synced_folders more conveniently.

You could override the empty list of vagrant_synced_folders in the Trellis core file vagrant.default.yml by creating the following vagrant.local.yml in your trellis directory:

# vagrant.local.yml

- local_path: /Users/philip/myplugin
  destination: /srv/www/
  create: false
  type: nfs
  bindfs: true
  mount_options: []
    u: 'vagrant'
    g: 'www-data'
    o: 'nonempty'

The Vagrantfile would load that config info here and create the corresponding vagrant_synced_folders here. You’ll have to look at this code and the sync options details to decide your sync config. If you are using macOS High Sierra, perhaps you’ll need these extra mount_options.

Edit. You probably wouldn’t have the plugin already in the bedrock directory, and if you did, it would already be synced. To make the example more realistic, I edited the plugin’s local_path to be outside the bedrock directory.

- - local_path: ../site/web/app/plugins/myplugin
+ - local_path: /Users/philip/myplugin
    destination: /srv/www/
1 Like


Hi @fullyint,

Thanks for your reply.

To be honest, I’m still confused on how to setup a clean workflow in order to develop my plugins and themes locally efficiently (without commit / tag / push to their respective private repos)

  1. What do you put in your composer.json ? Do you use a path repository type with the symlink option?
  2. In the require section of the composer.json, do you set a “*@dev” for the version constraints?
  3. What happens when you run composer update from the site folder? My dream would be that it updates all the packages but not the plugins or themes I’m working on.

I saw this : Should it be used ?
(it was referenced here :

Sorry if that’s too many question at the same time :confused:



All of this really depends on how hard you want to work on a platonically ideal plugin development environment.

I’ve developed plugins by git cloneing them into my plugins directory and then doing my commits from the command line in that directory. It gets the job done and doesn’t involve setting up shared folders.

1 Like


Hi @MWDelaney,

That’s what I do at the moment actually, but the issue is when I run composer update it replaces the plugin folder with the last tagged version.



If this is a plugin development environment, remove that plugin from composer.json until you’re ready to tag a new release and deploy.

1 Like