PluginsMarketplace reference

Marketplace reference

This page lists every field Syntic Code reads from a marketplace.json file, every form a plugin source can take, and every way to name a catalog in settings and policy. For a walkthrough, see Create a marketplace.

The file

A marketplace is a JSON object in a file called marketplace.json.

Where the catalog is hostedWhere the file must be
A git repositoryAt the repository root.
A local folderAt the folder root, or pass the file’s own path.
An https URLThe response body is the file.
An npm packageAt the package root.
A command sourceThe program’s standard output is the file.

syntic plugin validate --marketplace <folder> also accepts a .syntic-plugin/marketplace.json inside the folder, but adding a catalog reads only the root location.

Top-level fields

FieldTypeRequiredMeaning
namestringYesThe catalog’s name, used after @ in plugin references. Letters, digits, ., _ and - only.
pluginsarray of entriesNo (a warning if missing)The plugins the catalog offers.

Other top-level fields, such as an owner or description, are accepted and ignored.

Reserved names

Names that imitate Syntic’s own catalog names, including look-alike spellings with swapped or accented letters, are refused by syntic plugin validate. Choose a name that clearly belongs to you or your team.

Plugin entries

Each item in plugins is an object:

FieldTypeRequiredMeaning
namestringYesThe plugin’s name. Unique within the catalog, case-sensitive. Letters, digits, ., _ and - only. Becomes the installed folder name and the prefix of the plugin’s slash commands.
sourcestringNoWhere the plugin’s files come from. Leave it out to use the catalog’s own location. See Plugin sources.
descriptionstringNoShown in /plugin and in syntic plugin list --available.
categorystringNoOne label for browsing.
tagsarray of stringsNoLabels for search and filtering.
strictbooleanNoDefaults to true, meaning the plugin folder must contain its own manifest.

The plugin’s own manifest

Whatever strict says, an install reads the fetched folder’s own manifest to learn the plugin’s version and parts. A folder needs one of: .syntic-plugin/plugin.json, plugin.json at its root, or a lone SKILL.md (a one-skill plugin, recorded as version 0.0.0). The installed version always comes from that manifest, not from the catalog. See the Manifest reference.

Plugin sources

An entry’s source is a string in one of these forms.

Relative folder

{ "name": "formatter", "source": "./plugins/formatter" }

Resolved next to marketplace.json, and only when the catalog was added from a local folder. Must not contain .. or start with /, ~ or a drive letter.

GitHub repository

{ "name": "formatter", "source": "acme/formatter-plugin" }
{ "name": "formatter", "source": "acme/formatter-plugin@v2.1.0" }
{ "name": "formatter", "source": "acme/formatter-plugin#release" }

The whole repository is the plugin. A ref after @ or # selects a branch or tag. Cloned over https, or SSH when SYNTIC_PLUGIN_GIT_PROTOCOL=ssh.

Exact commit

{ "name": "formatter", "source": "acme/formatter-plugin@4f9c2e1a7b3d5f60819a2b3c4d5e6f708192a3b4" }

A ref of exactly 40 hex characters is treated as a commit and checked out precisely.

Folder of a repository

{ "name": "formatter", "source": "acme/monorepo//plugins/formatter" }
{ "name": "linter", "source": "https://git.example.com/team/mono.git//tools/linter" }

<repository>//<folder> takes one folder of a larger repository. Only that folder is checked out and kept. The folder must be a plain relative path. Use this form for entries in git-hosted catalogs.

Any git server

{ "name": "formatter", "source": "https://git.example.com/team/formatter.git" }
{ "name": "formatter", "source": "git@git.example.com:team/formatter.git#v2" }
{ "name": "formatter", "source": "gitlab:acme/formatter" }

An https URL ending in .git (or containing /_git/), an ssh://, git:// or git+<scheme>:// URL, or user@host:path. gitlab:group/project clones from gitlab.com. A #ref selects a branch or tag.

Zip archive

{ "name": "formatter", "source": "https://downloads.example.com/formatter-1.2.0.zip#sha256=9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08" }

An https URL whose path ends in .zip. The optional #sha256= pin must be 64 hex characters; a mismatch refuses the install. Archives are capped at 100 MB, 300 MB unpacked and 20,000 entries.

npm package

{ "name": "formatter", "source": "npm:@acme/formatter" }
{ "name": "formatter", "source": "npm:@acme/formatter@1.4.2" }

Read from the public npm registry (latest when no version is given). The tarball must carry a sha512 integrity value and match it. npm never runs, so no install scripts or package dependencies run. Capped at 200 MB unpacked.

No source

{ "name": "formatter" }

The plugin is the catalog’s own location: the whole repository for a git catalog, the folder for a local one. Not possible for a URL, npm or command catalog.

Forms that do not work for a plugin

  • An https URL that is not a .zip. Use a zip or a git URL instead.
  • An empty string. Leave the field out instead.

Catalog sources

The same string forms are accepted by syntic plugin marketplace add, by /plugin (a on the Marketplaces tab), and by --marketplace on install:

FormBecomes
owner/repo, owner/repo@ref, owner/repo#refGitHub
https://github.com/owner/repoGitHub, cloned as git
*.git URL, ssh://, git://, git+https://, user@host:path, gitlab:group/projectGit
./x, ../x, /x, ~/x, C:\x, file:///xLocal folder or file
Any other http:// or https:// URLURL serving the JSON
npm:<package>, @scope/namenpm

Catalogs in settings

extraKnownMarketplaces (or its alias additionalMarketplaces) maps a catalog name to a source. The name must match the name inside the catalog.

{
  "extraKnownMarketplaces": {
    "a": "acme/acme-plugins",
    "b": { "source": "acme/acme-plugins" },
    "c": { "source": { "source": "github", "repo": "acme/acme-plugins" } },
    "d": { "source": { "source": "git", "url": "https://git.example.com/team/plugins.git" } },
    "e": { "source": { "source": "directory", "path": "/srv/plugins" } },
    "f": { "source": { "source": "npm", "package": "@acme/plugins" } },
    "g": { "source": { "source": "url", "url": "https://plugins.example.com/marketplace.json", "headersHelper": "corp-token" } },
    "h": { "source": { "source": "command", "command": "corp-catalog --json" } }
  }
}
source kindFieldsNotes
githubrepoowner/repo, optional ref.
giturlAny git URL.
directory (also file, local)pathA folder or the JSON file.
npmpackagePackage name, optional version.
urlurl, optional headersHelperMust start with http:// or https://.
commandcommandA shell command whose output is the catalog.

headersHelper and command run programs, so they are honored only from your own settings, managed policy or the environment, never from a repository’s .syntic/settings.json or a folder added with --add-dir. A headersHelper prints a JSON object of headers or Name: value lines, at most 16 KB. Commands run with no input, a 60-second limit, and Syntic Code’s sign-in secrets removed from their environment.

Entries valid only in policy lists

strictKnownMarketplaces and blockedMarketplaces in managed policy accept the source strings above plus two pattern forms:

{ "hostPattern": "^git\\.corp\\.example$" }
{ "pathPattern": "^acme-corp/" }

hostPattern is a regular expression tested against the source’s host; pathPattern against its path (owner/repo for GitHub). See Plugins for your organization.

Validation messages

syntic plugin validate --marketplace reports:

FieldSeverityMessage
(file)errorinvalid JSON, or the file is not a JSON object
nameerrormissing, empty, or imitates the official catalog name
pluginswarningno plugins declared
pluginserrorplugins must be an array
plugins.Nerrorentry must be a JSON object
plugins.N.nameerrormissing name, or a duplicate name
plugins.N.sourceerrorempty, contains .., or is an absolute path

Validation does not reach the network. A source that points at a missing repository, ref, folder or archive is reported only when someone adds the catalog or installs the plugin. Test with syntic plugin marketplace add and an install before you share the catalog.