Earn 14 free days when your bug report or suggestion is accepted — how it works

Plugin SDK

CodeLoop ships first-class runners for the most common stacks (Node, Web/Playwright, Flutter, Xcode, Android, .NET). For everything else — Python/Django, Ruby/Rails, Go, custom monorepo scripts — the plugin system lets you wire any CLI test runner into the verify loop.

How plugins work

Drop a .codeloop/plugins.json in the project root. codeloop_verify reads it on every run, executes any plugin whose detect_file exists, and folds the results into the same RunArtifact as the built-in runners — so plugin failures count toward the gate score and appear in the dashboard.

Example: Django

{
  "plugins": [
    {
      "name": "django_pytest",
      "command": "pytest",
      "args": [
        "--json-report",
        "--json-report-file=.codeloop/runs/<id>/pytest.json",
        "--tb=short"
      ],
      "detect_file": "manage.py",
      "parse_output": "pytest"
    },
    {
      "name": "django_lint",
      "command": "flake8",
      "args": [".", "--count", "--show-source", "--statistics"],
      "detect_file": "manage.py",
      "parse_output": "exit_code"
    },
    {
      "name": "django_migrations",
      "command": "python",
      "args": ["manage.py", "migrate", "--check"],
      "detect_file": "manage.py",
      "parse_output": "exit_code"
    }
  ]
}

Example: Rails

{
  "plugins": [
    {
      "name": "rails_rspec",
      "command": "bundle",
      "args": ["exec", "rspec", "--format", "json"],
      "detect_file": "Gemfile",
      "parse_output": "rspec_json"
    },
    {
      "name": "rails_rubocop",
      "command": "bundle",
      "args": ["exec", "rubocop", "--format", "json"],
      "detect_file": ".rubocop.yml",
      "parse_output": "exit_code"
    }
  ]
}

Plugin schema

FieldRequiredDescription
nameYesStable identifier reported in the run summary.
commandYesBinary or script to run.
argsNoArgument list. The token <id> is replaced with the run id.
detect_fileNoPlugin runs only when this path exists relative to the project root.
parse_outputNoexit_code, pytest, rspec_json, jest, tap, or none.
cwdNoWorking directory override (relative to project root).
timeout_msNoHard timeout for the plugin (default: 600000).

Worked examples

Both example projects live under examples/plugins/ in the CodeLoop monorepo:

Related