Skip to content

Latest commit

 

History

24 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

img2

Plugin harness for the img2 ecosystem: everything is a plugin. The harness ships no domain capability — it owns install/link plumbing, the plugin registry, the workspace state envelope, the gate runner, and the contract.

Documentation, and which one to read

Document Its job
docs/PLUGIN_CONTRACT.md Normative. The rules. Where anything else disagrees with it, it wins
docs/WRITING_A_PLUGIN.md Your first plugin, start to finish. A linear tutorial — copy plugin-hello-cube and follow it
docs/plugin-wiki/ Everything after that. Why the architecture is shaped this way, eleven worked scenarios — add a domain, insert a step before a base step, add a gate, what to do instead of overriding one — and a field-by-field reference
CONTRIBUTING.md Changing the harness itself
SECURITY.md The threat model, and how to review a plugin before installing it
CHANGELOG.md What changed per release
docs/PLAN.md Phase status and the decisions behind it

docs/PLUGIN_ARCHITECTURE.md is a generated single-page build of the wiki — read the wiki instead, unless you want the whole thing in one file.

Ecosystem discovery: GitHub topic img2threejs-plugin.

Quickstart

npx github:img2threejs/img2 install     # $IMG2_HOME (~/.img2), harness checkout, host settings,
                                        # and an `img2` launcher linked into a writable PATH dir
                                        # (~/.local/bin, /opt/homebrew/bin, or /usr/local/bin —
                                        # if none qualifies, install prints an alias to use instead)
img2 add img2threejs/plugin-img2glb     # clone @ newest tag, pin SHA, link ~/.claude/skills/img2-img2glb
img2 list                               # registered plugins: id, version, ref, sha
img2 doctor                             # fail-loud static audit of every row (--json for tooling)
img2 sync --check                       # generated index == manifests (CI-able)
img2 remove img2glb                     # unlink every host, move clone to backups, drop the row

Every command also runs without the launcher: npx github:img2threejs/img2 <command>.

Asking which provider serves a capability

img2 capabilities answers "which installed plugin turns X into Y" for a caller — a base pipeline consulting it at a step, or you at a prompt. It is read-only, takes no lock and writes nothing.

img2 capabilities --from-kind image --to-kind glb --json
{ "version": 1, "contract": 14,
  "query": { "from": "image", "to": "glb" },
  "status": "answered",
  "providers": [{ "plugin": "img2glb", "version": "0.1.0", "resolvedSha": "353a8ea…",
                  "dir": "/Users/you/.img2/plugins/img2glb",
                  "steps": [{ "id": "generate-glb", "argv": ["python3", "…/tools/img2glb.py",
                              "--image", "{image}", "--workspace", "{workspace}"] }],
                  "gateRunner": { "argv": ["python3", "-m", "img2_core.gate_runner", ""] } }],
  "problems": [] }

Four properties a caller can rely on:

  • One JSON envelope on stdout for every outcome it owns, including failures. Branch on status (answered | ambiguous | data-fault) — never on stderr text.
  • Step commands come back as argv arrays, already tokenised, with {plugin_dir} resolved and {workspace}/{image} left as single elements to replace by value. You never build a shell string, so a path containing a space cannot split and a plugin cannot smuggle in a second command.
  • Exit codes reuse the harness table: 0 answered (zero providers is a normal answer), 1 a data fault, 3 an ambiguous edge — resolve it with --plugin <id>. This subcommand never exits 2, so 2 still means "this harness does not understand you".
  • One broken plugin cannot deny an unrelated answer. A plugin whose manifest fails to read lands in problems[] while providers[] still answers.

To detect whether a harness supports this at all, without parsing prose:

img2 --version --json    # {"harness":"0.2.0","maxPluginSchema":1,"coreApi":1,
                         #  "contract":14,"commands":[…,"capabilities"]}

An unrecognised --json, or capabilities missing from commands, means the feature is absent — treat that as "no provider" and take your built-in path, rather than as an error.

Developing a plugin locally:

img2 add --link ~/src/plugin-hello-cube   # symlink, no clone; ref/sha recorded as "local"

Layout under $IMG2_HOME (default ~/.img2; the deprecated IMG2THREEJS_HOME is honoured for one release with a warning):

harness/        canonical harness checkout (img2_core lives here)
plugins/<id>/   one clone (or --link symlink) per registry row
generated/      index.md + routes.json, regenerated by `img2 sync`
plugins.json    the registry: flat rows {id, repo, ref, resolvedSha, addedAt}
receipts.json   what was linked where
backups/        displaced directories; nothing is ever deleted in place

Plugin tools reach the Python core through the generated _img2_local.py (gitignored by contract) or $IMG2_HOME; img2_core.require_core_api(1) asserts the core API at runtime. Gates run through python3 -m img2_core.gate_runner --plugin-dir <dir> --workspace <dir>, which topo-sorts gates.json, expects one img2.gate-verdict JSON envelope per gate on stdout, and stops on a blocking fail.

Tests

node --test tests/*.test.mjs
python3 -m unittest discover -s tests/python -p 'test_*.py'

Both suites are dependency-free (node:test and unittest only). Run them from the repo root.

About

img2 plugin harness: everything is a plugin

Resources

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages