Skip to main content

Plugins Overview

adt-cli is plugin-first. Almost every feature beyond the core HTTP client and a handful of essential commands (auth, info, fetch, search, import) ships as an optional plugin you opt in to via your adt.config.ts. This keeps the default install lean and lets teams assemble exactly the toolbox they need.

There are two classes of plugin, and they solve different problems.

Command plugins

Command plugins extend the CLI with new subcommands. They implement the CliCommandPlugin interface and register their own commander commands plus options. Once loaded, a plugin's subcommands are indistinguishable from built-in ones — they share the same auth, logger, and client instance.

Examples shipped in this repo:

PluginCommands addedPurpose
@abapify/adt-atcadt atcRun ABAP Test Cockpit checks, emit SARIF/GitLab/Sonar
@abapify/adt-aunitadt aunitRun ABAP Unit tests, emit JUnit/JaCoCo/Sonar
@abapify/adt-exportadt export, adt deployDeploy local serialized files back to SAP
@abapify/adt-plugin-gcts-cliadt gcts …gCTS (git-enabled CTS) repo/branch/commit operations
@abapify/adt-diffadt diffCompare local abapGit files against SAP remote
@abapify/adt-codegenadt codegenRegenerate contracts from discovery/fixtures

Format plugins

Format plugins handle serialization — converting ADK objects to and from on-disk file layouts. They implement the FormatPlugin interface and register themselves under a short name (abapgit, gcts). Any command that reads or writes source files (import, export, checkin, checkout) accepts a --format <name> flag to pick which serializer runs.

PluginFormat namesLayout
@abapify/adt-plugin-abapgitabapgit.abap + .xml (classic abapGit)
@abapify/adt-plugin-gctsgcts / affJSON metadata + .abap / .asddls / .asdcls

Format plugins are stateless and client-agnostic: they receive ADK objects or a FileTree and do nothing else. All SAP interaction stays in the command plugin or core CLI.

How plugins are loaded

Plugins are loaded at CLI startup by @abapify/adt-config, which reads adt.config.ts from the current working directory (walking upward until it finds one). Each string in the commands array is a dynamic ESM import path.

adt.config.ts
import type { AdtConfig } from '@abapify/adt-config';

export default {
commands: [
'@abapify/adt-atc/commands/atc',
'@abapify/adt-aunit/commands/aunit',
'@abapify/adt-export/commands/export',
'@abapify/adt-plugin-gcts-cli/commands/gcts',
],
} as AdtConfig;
  • The import path must resolve to an ESM module with a default export implementing CliCommandPlugin (or a named export that adt-cli re-exports — see the plugin's own docs).
  • Format plugins self-register on import. You rarely list them directly in commands; they get pulled in transitively by any command plugin that uses them, or explicitly via import '@abapify/adt-plugin-abapgit' in a custom setup.
  • If a plugin import fails, adt-cli prints a warning and continues — missing plugins don't break the rest of the CLI.

See @abapify/adt-config for the full config schema (logging, output, extension-specific options) and architecture overview for how plugins slot into the overall stack.

Writing your own

Both plugin classes have step-by-step guides: