Due to some maintenance issues, this service has been switched in read-only mode, you can find more information about the why

and how to migrate your plugin documentation in this blogpost

Skip to end of metadata
Go to start of metadata

Plugin Information

View Custom Tools on the plugin site for more information.

A generic tool installer. You define how tools get installed, and the plugin will automatically install them when needed. 


A job will often require a tool not already installed on your Jenkins agents. In large environments, this often results in waiting on an administrator. The goal of this plugin is to let users manage their own tools, without requiring this administrator involvement. Using this plugin, you can define a script (or just a URL) for installing a tool using standard Jenkins Tool Installers. Plugins like Extra Tool Installers can be also used in this plugin. You then define which jobs require the tool, and the plugin installs them as needed before the build runs.

See the plugin documentation here.

Version History

Newer releases

See GitHub Releases

Version 0.6 (Oct 30, 2018)

  • JENKINS-54154 - Fix passing of Tool Properties for custom tools when configured via Jenkins Configuration as Code plugin (installers, etc.)

Version 0.5 (Apr 08, 2017)

  • Update the core baseline to 1.609.3 (last one with Java 6 support)
  • Update plugin to the new plugin parent POM
  • Cleanup FindBugs issues in the plugin

This is just a maintenance release, new features will be delivered later.

Version 0.4.4 (Oct 15, 2014)

  • (info) Properly escape special symbols in Additional vars coming from substituted variables (JENKINS-24113)

Version 0.4.3 (Oct 09, 2014)

  • (error) Be robust against null multi-configuration options after plugin upgrades (JENKINS-24853)
  • (error) Respect slave platform while constructing environment variables (JENKINS-14515)

Version 0.4.2 (06/29/2014)

  • (info) Support of tool version parameters in CLI build commands (JENKINS-22923)
  • (info) Reduce the size of the configuration page by adding the Advanced section (JENKINS-20909)
  • (error) Return non-null default values for CLI to workaround JENKINS-15094 in Jenkins core (JENKINS-22925)
  • (error) Throw errors if the configured tool cannot be found (JENKINS-18814)
  • (error) Properly handle missing tools in the Install wrapper to avoid NPEs (JENKINS-22075)

Version 0.4.1 (11/25/2013)

Version 0.4 (09/08/2013)

Version 0.3 (08/02/2013)

  • Change of ownership. New owner: Oleg Nenashev, Synopsys Inc., www.synopsys.com
  • New features:
    • JENKINS-18774 - New option: Setup of label-specific environment variables (useful for LD_LIBRARY_PATH, etc.)
    • JENKINS-18707 - New option: Skip installation of tool at MatrixBuild's master job
    • JENKINS-17844 - Improvement: Environment Variables expansion in ExportedPaths and ToolHome
    • Partial replacement of the Tool Environment Plugin. Custom Tools can export HOME variables in different cases (ex, Tool_HOME and TOOL_HOME)
  • Bug fixes:
    • JENKINS-18815 - Home variables substitution doesn't work properly in case of leading variable
    • JENKINS-18481 - BuildWrapper throws NPE if user doesn't select any tool 
    • JENKINS-14515 - Malformed path variable in case of different operating systems at master and slave
    • JENKINS-13285 - customtools-plugin does not delegate the Launcher.isUnix() call in DecoratedLauncher


  1. Unknown User (cbos.ec@gmail.com)

    Is it possible to define different ways to install the same version for different operating systems?
    The example above shows a script to install on linux. How to configure it if you want to support the custom tool to install both on linux and windows slaves?

    Will it always install the tool, or is it conditional? Or should the command step do it conditional?

    1. Unknown User (oleg_nenashev)

  2. Unknown User (klakier)

    Is there a way to setup custom environment variables for custom tool (other than PATH) independently of the project/build configuration? E.g. they are defined for every build step that uses given custom tool.

    1. Unknown User (oleg_nenashev)

      I've added such functionality into version 0.3

  3. Unknown User (wernight)

    Would be nice to have some more help explaining well what each field means when filled and when left empty.

    For example I've set up:

    Without the "Exported paths" section, I've PsTools twice in my PATH.

    1. Unknown User (oleg_nenashev)

      It was a bug. Fixed it in the version 0.3

  4. Unknown User (gbois)

    Be careful: your current JIRA component is 'customtools-plugin' and not 'custom-tools-plugin'. It is the reason why the Open issues link refer to an empty list.

    1. Unknown User (oleg_nenashev)

  5. Unknown User (okigan)

    Right now exported path are *appended* to system path.

    Any way to *prepend* it (so custom tool picked up instead of system's one)?

    1. Unknown User (oleg_nenashev)

      At the current state answer is "no". But I have such feature in the TODOs list.

      Anyway, you can remove system variables from your node using launch scripts, EnvInject, etc., etc.

  6. Unknown User (ludovicroucoux)


    I have a problem after installing a tool. How can I get the "tool_HOME" programmatically with Java ?

    I have tested a lot of things (build.getEnvironment(listener), System.getenv(), ...) without success.

    Can anyone help me ?

    1. Unknown User (oleg_nenashev)

      Sorry, missed the comment.

      tool_HOME is quite complicated due to the implementation specifics. IIRC the variable is being injected to scripts and other executable runs only. It does not appear in build.getEnvironment() now. In scripts you could use CustomToolInstallWrapper::setUp() directly, but a more generic approach would be useful. It would worth if you create a JIRA issue for the enhancement and describe your use-cases there.

  7. Unknown User (moodysma)

    Does this plugin even work?  I tried downloading from a url pstools like one of the comments, and nothing got downloaded or extracted.  Please let me know, i've already spent an inordinate amount of time trying to get it to work.

    1. Unknown User (oleg_nenashev)

      Yes, this plugin works well. BTW I have never used it together with pstool + the installation process greatly depends on the Custom Tool configuration you set. If you have an issue with a particular tool, please create a JIRA issue and provide the tool configuration there.

  8. Unknown User (dhoer)

    Can you use this plugin with declarative jenkinsfile?

    1. Unknown User (dhoer)

      1. Unknown User (dhoer)

        pipeline {

          agent any

          environment {
            PLAY_ACTIVATOR = tool name: 'play_activator_1.3.10', type: 'com.cloudbees.jenkins.plugins.customtools.CustomTool'

          stages {
            stage('Build') {
              steps {
                sh '${PLAY_ACTIVATOR}/activator clean dist'

  9. Unknown User (jkhoriaty)

    How does the plugin determine if a program is installed or not? What if my "Custom Tool" is just a python script that I developed and cloned into a particular folder of the system and added it to the PATH?

  10. Unknown User (cosbug)

    Does anyone have an example how to add a custom tool via groovy script, lets say a ZIP-ed binary from a URL ?

  11. Unknown User (tnguyen1)

    Unknown User (cosbug) This groovy script works for me as a init.groovy.d script for Jenkins (here's an example of NodeJS installation using a zip installer):

    import jenkins.model.*
    import hudson.tools.*
    import com.cloudbees.jenkins.plugins.customtools.*
    import com.synopsys.arc.jenkinsci.plugins.customtools.versions.ToolVersionConfig

    CustomTool.DescriptorImpl descriptor = Jenkins.instance.getDescriptorByType(com.cloudbees.jenkins.plugins.customtools.CustomTool.DescriptorImpl.class)
    String name = 'NodeJS_424'
    String home = ''
    String exportedPaths = '**/bin'
    List<ToolInstaller> installers = new ArrayList<ToolInstaller>()
    installers.add(new ZipExtractionInstaller('', 'https://nodejs.org/dist/v4.2.4/node-v4.2.4-linux-x64.tar.gz', ''))
    List<ToolProperty> properties = new ArrayList<ToolProperty>()
    properties.add(new InstallSourceProperty(installers))
    List<CustomTool> installations = descriptor.getInstallations().toList()
    // remove existing custom tool with same name
    List<CustomTool> toRemove = new ArrayList<CustomTool>()
    for (CustomTool tool : installations) {
    if (tool.getName().equals(name)) {
    // add custom tool
    installations.add(new CustomTool(name, home, properties, exportedPaths, null, ToolVersionConfig.DEFAULT, null))
    def customTools = installations as CustomTool[]

    Hope that helps.

  12. Unknown User (cosbug)

    Thanks for sharing Unknown User (tnguyen1). Exactly what I was looking for!