Skip to content

refactor: move all site adapters to independent plugins - #216

Merged
beubax merged 43 commits into
mainfrom
feat/linkedin-post-comments
Aug 7, 2026
Merged

refactor: move all site adapters to independent plugins#216
beubax merged 43 commits into
mainfrom
feat/linkedin-post-comments

Conversation

@ankitranjan7

@ankitranjan7 ankitranjan7 commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Description

Moves every repository-owned site adapter from clis/ into its own independently installable package under plugins/. Webcmd core no longer bundles site commands, so plugin updates can ship independently without a core release.

The change also:

  • adds the minimal public @agentrhq/webcmd/plugin-runtime helper surface required by independent plugins;
  • keeps discovery and installation explicit through webcmd plugin search and webcmd plugin install, with no auto-install or retry;
  • preserves legacy user-local adapter compatibility without an official bundled baseline;
  • keeps the browser command contract unchanged;
  • includes the new read-only linkedin post-comments command with optional --limit and exact-profile-URL deduplication;
  • removes the temporary LinkedIn design document from the PR.

Example installation:

webcmd plugin search linkedin
webcmd plugin install github:agentrhq/webcmd/linkedin

Final architecture

  • clis/ is absent.
  • cli-manifest.json is empty.
  • hosted default site commands are empty; tenant-installed plugins remain isolated.
  • the npm core tarball contains neither repository CLIs nor repository plugins.
  • each of the 123 sites is cataloged as an independently installable plugin.

Verification

  • Plugin catalog: 123 entries.
  • Plugin command inventory: 831 unique commands.
  • Frozen compatibility contract: 780/780 former bundled commands preserved exactly.
  • Core site commands: 0.
  • Hosted default site commands: 0.
  • Browser commands: 42, unchanged.
  • Full Vitest suite: 5,221 passed, 1 skipped across 418 files.
  • Hosted lifecycle and runner tests: 297 passed.
  • Typecheck, build, package-bin, hosted-contract, catalog, parity, and both audit gates passed.
  • Isolated local lifecycle passed: absent guidance, search, exact-source install, list, read-only TechCrunch execution, uninstall, and absent guidance again.
  • A final whole-branch subagent review found no Critical issues; its nine Important/Minor findings were fixed and passed scoped re-review.

Type of Change

  • New feature
  • Refactor
  • CI / build / tooling
  • Documentation

Checklist

  • Relevant tests and generated artifacts are updated.
  • Explicit plugin install and uninstall lifecycle is verified.
  • Command metadata parity is enforced in CI and release workflows.
  • No planning documents are committed.

@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

🔴 Documentation update likely missing — low confidence

The automated review found 5 likely missing documentation updates.

Findings

  1. SKILL — Webcmd core no longer bundles site commands under clis/, and instead requires explicit plugin installation via webcmd plugin search and install.
    • Changed: README.md
    • Evidence: +The npm package ships the Webcmd core and browser commands, but no site'+adapters. Search the plugin catalog and explicitly install the adapter you'+need:
    • Suggested update: skills/webcmd-usage/SKILL.md
    • Why: The skill file is marked as modified in the file inventory, but its patch is omitted from the PR data. A review is suggested to ensure the skill's instructions regarding clis/ and plugins/ are fully updated.
  2. SKILL — Site adapters are now authored as independent plugins under plugins/ rather than private adapters under clis/.
    • Changed: docs/authoring.mdx
    • Evidence: +Keep personal or company workflows in private plugins. The legacy '~/.webcmd/clis/' path remains supported, but new portable work should use plugins.
    • Suggested update: skills/webcmd-adapter-author/SKILL.md
    • Why: The skill file is marked as modified in the file inventory, but its patch is omitted from the PR data. A review is suggested to ensure the authoring guidelines are updated to prioritize private plugins over private adapters.
  3. SKILL — Adapters and plugins must now import shared helpers (such as registerSiteAuthCommands, makeNewCommand, etc.) from @​agentrhq/webcmd/plugin-runtime instead of relative paths.
    • Changed: plugins/blinkit/auth.js
    • Evidence: +import { registerSiteAuthCommands } from '@agentrhq/webcmd/plugin-runtime';
    • Suggested update: skills/webcmd-adapter-author/SKILL.md
    • Why: The skill's key conventions section still states that adapters import only @​agentrhq/webcmd/registry and @​agentrhq/webcmd/errors, which contradicts the new requirement to import shared helpers from @​agentrhq/webcmd/plugin-runtime.
  4. DOCS — The plugin installation URL format has changed from github:agentrhq/webcmd/plugins/<site> to github:agentrhq/webcmd/<site>.
    • Changed: plugins/jhu/README.md
    • Evidence: -webcmd plugin install github:agentrhq/webcmd/plugins/jhu'+webcmd plugin install github:agentrhq/webcmd/jhu
    • Suggested update: docs/cli-reference.mdx
    • Why: The documentation in docs/cli-reference.mdx contains the old installation path format 'github:agentrhq/webcmd/plugins/ycombinator'. Since the patch for docs/cli-reference.mdx is omitted, we must verify if it has been updated to match the new format.
  5. SKILL — The plugin installation path format has changed by removing the '/plugins/' segment from the GitHub repository URL (e.g., from 'github:agentrhq/webcmd/plugins/techcrunch' to 'github:agentrhq/webcmd/techcrunch').
    • Changed: plugins/techcrunch/README.md
    • Evidence: +webcmd plugin install github:agentrhq/webcmd/techcrunch
    • Suggested update: skills/webcmd-usage/SKILL.md
    • Why: The skill file still references the old installation path format 'webcmd plugin install github:agentrhq/webcmd/plugins/ycombinator' which is outdated under the new architecture.

Limitations

  • Some review context was unavailable or reduced.
  • Some automated findings could not be verified against the pull request diff.

This review is advisory and does not block merging.

@ankitranjan7 ankitranjan7 changed the title feat: add LinkedIn post-comments command refactor: move LinkedIn commands to community plugin Aug 5, 2026
@ankitranjan7 ankitranjan7 changed the title refactor: move LinkedIn commands to community plugin refactor: move all site adapters to independent plugins Aug 5, 2026
ankitranjan7 and others added 5 commits August 5, 2026 19:20
migrate-cli-sites.mjs hardcoded webcmd: ">=0.6.0" for every plugin it
generated a fresh manifest for, but package.json ships as 0.5.3 in this
release. Every one of the 108 affected plugins (including linkedin) was
uninstallable: `webcmd plugin install` hard-fails checkCompatibility()
with "Plugin requires webcmd >=0.6.0, but current version is
incompatible" before it ever reaches npm.

Derive the floor from package.json's actual version instead of a
literal, and regenerate the already-committed manifests (all
plugins/*/webcmd-plugin.json + package.json, and the aggregated root
webcmd-plugin.json catalog) to match. Update the two unit tests that
had the old literal baked into their expectations.
… no sites

Several e2e and smoke tests invoked site commands (hackernews, dictionary,
google, imdb, apple-podcasts, yollomi, paperreview) and asserted on `list`
output size/contents, assuming site adapters were bundled in core. After
this migration core registers zero site commands until a plugin is
installed, so these tests failed deterministically in any clean
environment (e.g. `list` returns 0 commands, not >50).

Add installFixturePlugin() to place a repo-local plugin directly under
an isolated HOME's .webcmd/plugins/ (skipping `plugin install`'s npm
step, which only resolves a peerDependency these fixture plugins don't
otherwise need and which fails until the in-progress release is actually
published). Each affected suite now installs the specific plugin(s) it
exercises before running. The smoke test's "all expected sites
registered" check is rewritten against the plugin catalog under
plugins/, since that's the equivalent invariant post-migration.
webcmd-usage, webcmd-adapter-author, and webcmd-autofix (all shipped to
npm under skills/**) still described a repo-root clis/ directory as the
"official bundle" location for built-in adapters. That directory no
longer exists — every main-repo site, official or community, lives
under plugins/<site>/ now. Left the ~/.webcmd/clis/ references alone:
that private local-iteration directory is unaffected by this migration.
ankitranjan7 and others added 4 commits August 6, 2026 15:37
Now that core ships zero bundled site adapters, an empty `list` (0
sites) is the expected default state on a fresh install rather than a
sign something's broken. Point the user at `plugin search`/`plugin
install` instead of leaving them looking at a bare zero-count line.
It's a build artifact (npm run build-plugin-manifest scans plugins/*
via a Node loader and writes it fresh), read only by CI-time checks
within the same run: check-plugin-command-parity, check-typed-error-lint,
check-silent-column-drop, and convention-audit. Nothing reads it from a
published package or at CLI/hosted runtime, so it doesn't need to be
in the npm tarball or in git history — same treatment as
hosted-contract.json, which was already gitignored for this reason.
Gitignoring it in 4aec6c5 broke the unit-test CI job: that job runs on
a separate runner with a fresh checkout and only does `npm ci` +
vitest, so the file no longer existed for the three test files that
read it from the package root (hosted/availability, hosted/file-contract,
build-manifest) — 5 tests failed with ENOENT.

hosted-contract.json is safely gitignored only because `npm run build`
always regenerates it. Give the plugin manifest the same guarantee
instead of leaving it as a build artifact nothing in the install path
produces. Costs ~0.9s per build.
Conflicts:
- vitest.config.ts: keep main's src/browser test exclusion, drop the
  clis/** entry (clis/ no longer exists after the plugin migration).
- src/cli.ts: keep both import sets (plugin discovery + browser run).
- skills/webcmd-usage/SKILL.md: keep the plugin-architecture adapter
  bullet and main's rewritten browser-driving bullet.

Also updated src/hosted/runner.test.ts: the hosted contract sorts browser
commands, and main's new catalog order (tabs, bind, run, snapshot, close)
is no longer alphabetical, so compare against the sorted catalog.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
ankitranjan7 and others added 12 commits August 7, 2026 01:20
…ilability

The isLocalIpDomain function now strips port numbers from domain strings
(e.g. '127.0.0.1:3000') before validating the IPv4 format. This ensures
desktop-app adapters running on local IP addresses with ports are correctly
classified as 'app' rather than 'site'.

Includes regression tests to prevent port-handling regressions.
updatePlugin/updateAllPlugins now check for tracked-file modifications
in both the standalone plugin directory and the shared monorepo clone
before beginReplaceDir wipes them, with --force to opt out. Local
(symlinked) installs are unaffected since they never go through
beginReplaceDir.
git status --porcelain already omits gitignored paths (node_modules/dist
never show up), so --untracked-files=no was only hiding the case the
guard exists to catch: a new, unstaged command file. Drop the flag,
label refusal entries as new-unstaged vs modified for clarity.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Add inline comments explaining that --update-env-vars on 'execute' is a
per-execution override (not a job-spec mutation) and that workflow_dispatch
runs should target main to avoid delisting plugins.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…t guard

getDirtyFiles previously treated any git failure (missing binary, "detected
dubious ownership in repository", permission errors) as "clean", letting
beginReplaceDir silently destroy uncommitted work. It also ran `git status
--porcelain` with no pathspec, which reports the whole enclosing repository
rather than just the plugin directory, causing spurious refusals for plugins
inside a larger repo (e.g. a dotfiles-tracked home directory).

Now getDirtyFiles probes with `git rev-parse --git-dir` first: a genuine
non-repository still proceeds, but any other failure refuses the update with
a message pointing at --force. `git status` is scoped with `-- .` so only the
plugin directory is considered.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@beubax
beubax merged commit 0470ac4 into main Aug 7, 2026
21 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants