Skip to content

Plugin Config Field Reference

PicGo's Uploader / Transformer / Plugin modules can each expose a set of fields via the config(ctx) method. On the CLI side this array is passed to inquirer.js to render command-line prompts; on the GUI side it is rendered as a visual form.

A minimal example

Here is a simplified GitLab-style Uploader configuration covering a few common field types:

js
const uploaderConfig = ctx => {
  // Read the previously stored config to seed the form with current values
  const userConfig = ctx.getConfig('picBed.gitlab') || {}
  return [
    {
      name: 'host',             // field name; becomes the key in the final config
      type: 'input',            // single-line text
      alias: 'Host',            // field title shown in the GUI form
      default: userConfig.host || 'https://gitlab.com',
      required: true
    },
    {
      name: 'token',
      type: 'password',         // masked input
      alias: 'Token',
      default: userConfig.token || '',
      required: true
    },
    {
      name: 'visibility',
      type: 'list',             // single-select dropdown
      alias: 'Visibility',
      choices: ['public', 'private'],
      default: 'private',
      required: false
    }
  ]
}

Once your fields are defined, expose them to PicGo according to the dimension:

js
const handle = ctx => ctx

const uploaderConfig = ctx => [ /* Uploader fields, see above */ ]
const transformerConfig = ctx => [ /* Transformer fields */ ]
const pluginConfig = ctx => [ /* Plugin's own fields */ ]

module.exports = ctx => {
  const register = () => {
    // The Uploader's config goes with its handle into helper.uploader
    ctx.helper.uploader.register('gitlab', {
      handle,
      config: uploaderConfig
    })

    // Same pattern for the Transformer
    ctx.helper.transformer.register('gitlab', {
      handle,
      config: transformerConfig
    })
  }

  return {
    register,
    uploader: 'gitlab',         // expose the Uploader name to PicGo so it can be picked
    transformer: 'gitlab',      // same for the Transformer
    config: pluginConfig        // the Plugin's own config attaches directly on the exported object
  }
}

All three dimensions return a field array with identical shape. They only differ in where they're attached and which key in the PicGo config file the values end up under (see The config method).

Tip

ctx.getConfig('picBed.<name>') is the standard "read existing config to seed the form" pattern. Uploader configs live under picBed.<name>, Transformer configs under transformer.<name>, and a Plugin's own config under <pluginFullName> (see The config method for details).

For a real-world Uploader reference, see PicGo-Core's built-in tcyun.ts.

Common fields

All field types support these properties:

FieldTypeNotes
namestringRequired. The field name; becomes the key in the stored config object
type'input' | 'password' | 'list' | 'checkbox' | 'confirm' | 'editor'Required. Determines how the field is rendered
requiredbooleanWhether the field is required. GUI adds a red asterisk; CLI blocks empty submissions
defaultunknown | ((answers) => unknown)Default value. Can be a function — see Reactive fields
aliasstringField title in the GUI form. Ignored by the CLI. If omitted, GUI falls back to name
messagestringCLI prompt text / GUI input placeholder
tipsstringHelp text shown via a ❓ tooltip next to the GUI field title. Supports Markdown (sanitized). Ignored by the CLI

Tip

alias and tips are PicGo extensions; inquirer doesn't know about them, so the CLI ignores them.

Field types

input — single-line text

A plain string input.

js
{
  name: 'bucket',
  type: 'input',
  alias: 'Bucket',
  default: '',
  required: true
}

password — masked input

Same as input but the GUI masks the value by default (with a toggle button), and the CLI inquirer hides keystrokes.

js
{
  name: 'secretKey',
  type: 'password',
  alias: 'SecretKey',
  default: '',
  required: true
}

list — single-select dropdown

Pick one from a set of options. choices is required.

js
{
  name: 'region',
  type: 'list',
  alias: 'Region',
  choices: ['us', 'eu', 'asia'],
  default: 'us',
  required: true
}

choices can be a plain string array (label and value are the same) or an array of objects:

js
choices: [
  { name: 'North America', value: 'us' },   // GUI shows "North America", stored value is 'us'
  { name: 'Europe', value: 'eu' },
  { name: 'Asia', value: 'asia' }
]

checkbox — multi-select

Multi-select list. default is usually an array.

js
{
  name: 'options',
  type: 'checkbox',
  alias: 'Processing options',
  choices: [
    { name: 'Slim', value: 'slim', checked: true },  // checked means initially selected
    { name: 'Watermark', value: 'watermark' }
  ],
  default: ['slim']
}

checked only applies to checkbox fields and pre-selects the option on first render.

confirm — yes / no switch

A boolean, rendered as a Switch in the GUI.

js
{
  name: 'slim',
  type: 'confirm',
  alias: 'Image compression',
  confirmText: 'On',       // label when toggled to true
  cancelText: 'Off',       // label when toggled to false
  tips: 'Compress images before upload',
  default: false
}

confirmText / cancelText only apply to confirm fields.

editor — multi-line text 3.0.0+

Use this for fields where users need to enter multi-line text — for example, an API key list, a custom transform/compression script, a template snippet. The stored value is still a string and may contain \n; picgo does no further trimming or processing.

js
{
  name: 'script',
  type: 'editor',
  alias: 'Compression script',
  required: true,
  message: 'Enter the compression script (multi-line)'
}

Behavior on both sides:

  • CLI: inquirer 6's native editor type opens an external editor with the priority VISUALEDITOR → platform default (vi / nano on Unix, notepad on Windows). Whatever the user saves on exit is submitted verbatim; picgo-core doesn't trim or transform it.
  • GUI: rendered as <Textarea> that auto-grows with content; users can drag the bottom-right handle to resize manually.

Tip

On Windows, if the default notepad experience isn't great, set EDITOR=code -w (or similar) for a wait-mode editor (the -w flag is required so the CLI blocks until the GUI editor closes). This is inherent inquirer / external-editor behavior; PicGo doesn't intervene.

Reactive fields 3.0.0+

If you want a field's choices or default to react to the current value of other fields — for example, "pick a region first, then derive the bucket list" — you can write choices or default as functions and declare the dependency with dependsOn.

choices and default both support two forms:

  • Static value: same as before
  • Function: (answers) => ..., where answers is a snapshot of currently known field values (Record<string, unknown>)

dependsOn is an array of field names that this field's evaluation depends on. It's primarily used by the GUI — the GUI watches the listed fields and triggers a refresh whenever any of them changes. On the CLI side, inquirer naturally accumulates answers in prompt order, so dependsOn is just metadata in CLI; it doesn't affect evaluation.

A minimal two-level cascade (region → bucket):

js
const config = ctx => [
  {
    name: 'region',
    type: 'list',
    alias: 'Region',
    choices: ['us', 'eu', 'asia'],
    default: 'us',
    required: true
  },
  {
    name: 'bucket',
    type: 'list',
    alias: 'Bucket',
    dependsOn: ['region'],
    // After the user picks a region, this receives the latest answers.region
    choices: (answers) => {
      if (answers.region === 'eu') {
        return ['eu-west-prod', 'eu-central-prod']
      }
      if (answers.region === 'asia') {
        return ['asia-sg-prod', 'asia-tk-prod']
      }
      return ['us-east-prod', 'us-west-prod']
    },
    required: true
  }
]

Tip

Your function must handle answers === {} — when the schema is first serialized (so the GUI can render the initial form), answers is empty. Provide a reasonable fallback for upstream fields, like the example above defaulting to the us branch when answers.region isn't set.

You can use functional choices / default without dependsOn — the CLI still works (inquirer evaluates the functions itself). But the GUI won't know when to refresh, so the dropdown will only show what was computed on first load.

For GUI-side form value merging and refresh behavior, see GUI Plugin Development – Reactive fields.

Error handling

Field-level isolation is the consistent strategy — when one field's function throws, other fields keep working:

  • choices function throws → that field's choices falls back to [] (empty GUI dropdown, no CLI options)
  • default function throws → that field's default falls back to undefined
  • Both cases log the field name and error via ctx.log.warn

So you don't need defensive try/catch around your functional choices / default — PicGo has you covered. That said, you should still handle exceptions yourself when you can.

Storage paths

See the JSON example in The config method. In short:

  • Uploader: picBed.<uploaderName>.<fieldName>
  • Transformer: transformer.<transformerName>.<fieldName>
  • Plugin (its own config): <pluginFullName>.<fieldName>, at the root of the config file

The GUI filters out orphan keys (fields not in the current schema) at save time, so temporary fields produced during cascading don't leak into the persisted config.