Scott Robinson Technical Lead

Docker

skrub

A Composer plugin that strips junk out of vendor and gives the disk space back.

A dependency archive serves more than production

A package can arrive in vendor/ with its tests, fixtures, build configuration and documentation alongside the code an application needs at runtime. Those files have a purpose in the package's development, but carrying them into a deployment consumes disk space. In a Docker image, they also contribute to the size of the image being built.

Package maintainers can trim distribution archives with .gitattributes and export-ignore. That leaves the decision with the people who know the package. It does not happen consistently, so the application receiving the dependencies still has to deal with whatever was shipped. Installing only what the application needs at the package level does not settle which files inside those packages belong in the deployment.

I built skrub to make that second question practical to inspect. It is a Composer plugin that identifies files it considers removable and reports the space their removal would recover. The important part of its interface is the gap between identifying those files and deleting them.

Removal is a second deliberate step

Running composer skrub produces the candidate list and the total recoverable disk space. It does not delete the candidates. To perform the removal, the command must be run again with --perform.

That second invocation puts a decision between the tool's assessment and a change to the filesystem. I can see what it proposes, consider the saving and read the paths before granting permission to remove them. The default command is therefore useful even when I decide to leave everything where it is. It answers what could be removed without requiring deletion as the price of finding out.

The list matters because this is a judgement about files in somebody else's packages. Calling something a test fixture or documentation describes its usual role, but the person preparing the deployment still needs to decide whether its removal is appropriate for that application. Skrub makes a proposal; --perform is the point at which the operator accepts it.

Show the consequence alongside the candidates

The recoverable space total gives the proposal context. A list of paths establishes the scope of deletion, while the size tells me what accepting that scope would achieve. Neither is enough on its own. A large saving does not establish that every file is dispensable, and a long list does not tell me whether the saving is meaningful.

This is why I would read the output before proceeding rather than treat the extra flag as installation boilerplate. The documented warning is direct: skrub performs deletion and may remove unexpected files. The preview gives that warning something concrete to refer to. It is the actual proposed removal that needs attention, rather than an abstract promise that the plugin knows what is safe everywhere.

There is no universal space-saving figure to attach to the project. The command reports the total for the installation in front of it. That is the useful number when deciding whether to remove anything, because it follows from the dependencies and candidate files actually present.

Keep the workflow close to the dependencies

Skrub installs with composer require ssx/skrub and runs through Composer. The workflow stays short: inspect the candidates with composer skrub, then use composer skrub --perform if the list is appropriate. The distinction between those commands is the main thing to understand before using it.

The project has a narrow job: reduce the files carried in a deployment where those files serve no runtime purpose. Its design leaves the final judgement visible. I wanted reclaiming disk space to begin with an inspectable proposal and end with an explicit action, with enough information between them to decide whether the deletion is worth making.