Skip to content

feat(cli): surface plugin install target host + add plugin target#8575

Merged
devinfoley merged 1 commit into
masterfrom
feat/plugin-install-target-host
Jun 25, 2026
Merged

feat(cli): surface plugin install target host + add plugin target#8575
devinfoley merged 1 commit into
masterfrom
feat/plugin-install-target-host

Conversation

@devinfoley

@devinfoley devinfoley commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Thinking Path

  • Paperclip is the open source app people use to manage AI agents for work
  • The CLI (paperclipai plugin ...) installs and manages plugins against a Paperclip server resolved from --api-base / PAPERCLIP_API_URL / the active profile / an inferred default
  • During local plugin development you can have more than one Paperclip running (a released host plus a branch build on another port), and nothing told you which instance a command actually talked to
  • So a plugin that depends on a route or response field only present on a feature branch could be silently installed/tested against a stale host, returning API route not found, and look broken when the real problem was the test target
  • This pull request makes the install target explicit: it probes GET /api/health and prints the resolved API URL + server status/version/mode/exposure before installing, and adds a plugin target command plus docs for running and verifying against a branch service
  • The benefit is that local plugin authors can confirm they are exercising the runtime they intend to, instead of debugging phantom plugin bugs caused by hitting the wrong server

Linked Issues or Issue Description

No public GitHub issue exists, so the underlying problem is described inline following the feature-request template.

Problem or motivation

Local plugin development assumes a single Paperclip on http://127.0.0.1:3100. When a plugin depends on server code that only exists on a feature branch (a new scoped route, a new response field, a new managed-resource capability), installing it into a long-lived host still on older code makes the route/field missing there. The plugin falls back or errors and looks broken, when the real cause is that it was tested against the wrong runtime. The CLI already let you point at any server, but it never surfaced which server you ended up on — so the mistake was invisible.

Proposed solution

Make the install target explicit. Before plugin install runs, probe GET /api/health and print the resolved API URL plus server status/version/deploymentMode/exposure, so the developer can confirm which Paperclip they are installing into. Add a standalone plugin target command to inspect the target without installing, a --no-verify-target escape hatch, and docs covering how to run a branch service on its own port and verify a branch route end-to-end.

Alternatives considered

  • Do nothing and rely on the existing --api-base / PAPERCLIP_API_URL resolution — rejected because the gap was never the inability to point at a branch server, it was the lack of feedback about which server was actually hit.
  • Fail the install when the target looks stale — rejected as too aggressive; the probe is advisory and degrades gracefully when health details are not exposed or the server is unreachable.

Dedup Search

  • I searched the open and recently closed GitHub PRs for similar or duplicate PRs — this is not a duplicate

What Changed

  • Add probeTargetDiagnostics / formatTargetDiagnostics helpers (cli/src/commands/client/plugin.ts) that read GET /api/health and report the resolved API URL plus server status / version / deploymentMode / deploymentExposure.
  • plugin install now prints these target diagnostics before installing, so you can confirm which instance you are installing into. Skippable with --no-verify-target.
  • plugin install --json keeps its original flat PluginRecord shape (top-level id / pluginKey / version / status are unchanged); when the target was probed it gains an additional top-level target field. Existing automation that reads the plugin fields keeps working.
  • Add a standalone paperclipai plugin target command to inspect the install target without installing anything.
  • Update doc/plugins/LOCAL_PLUGIN_DEVELOPMENT.md: how the CLI resolves its target, how to run a branch service on its own port and point the CLI at it explicitly, an end-to-end check that the branch route is actually served, and a troubleshooting entry for the stale-target symptom.
  • Unit tests for the diagnostics helpers (reachable + unreachable probe, and both render paths).

Verification

  • npx vitest run cli/src/__tests__/plugin-init.test.ts — 10/10 pass (covers probeTargetDiagnostics success/failure and formatTargetDiagnostics rendering).
  • CLI typecheck (tsc --noEmit in cli/) — clean.
  • Manual: with a server running, paperclipai plugin target prints Target Paperclip: <url> and the health line; plugin install prints the same block before installing and --no-verify-target skips it.

Risks

Low risk. The probe is read-only (GET /api/health) and runs before install; if the server does not expose details it degrades to ok (no details exposed), and an unreachable target prints a remediation hint rather than failing the command. The --json output keeps its original flat shape, so existing scripts are unaffected. No server or schema changes.

Model Used

Claude Opus 4.7 (claude-opus-4-7), extended thinking + tool use, via Claude Code.

@commitperclip

commitperclip Bot commented Jun 24, 2026

Copy link
Copy Markdown

✅ All checks passing — ready for Greptile review and maintainer approval.

— commitperclip

@superagent-security

Copy link
Copy Markdown

Superagent didn't find any vulnerabilities or security issues in this PR.

@greptile-apps

greptile-apps Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR surfaces the resolved install target before plugin install runs by probing GET /api/health and printing the API URL, version, mode, and exposure — eliminating the silent "installed into the wrong Paperclip" failure mode for local plugin development. It also adds a standalone paperclipai plugin target command and expands the local plugin development guide with a full "targeting a branch runtime" workflow.

  • Adds probeTargetDiagnostics / formatTargetDiagnostics helpers (pure, testable) and wires them into plugin install before the install request; skippable with --no-verify-target, and gracefully degrades to unreachable with a remediation hint when the server cannot be reached.
  • --json output remains the flat PluginRecord shape with target appended as an additive field when the probe runs, so existing automation continues to read top-level fields correctly.
  • New plugin target subcommand and four unit tests covering reachable/unreachable probe and both render branches of formatTargetDiagnostics.

Confidence Score: 5/5

Safe to merge — the change is entirely additive, read-only (one extra GET before install), and degrades gracefully on any probe failure without blocking the install.

All new logic is additive: the health probe runs before install and its failure path returns a structured result rather than throwing, so the install path itself is unchanged. The JSON output extends the existing flat shape rather than restructuring it, preserving backward compatibility. The --no-verify-target flag correctly restores the pre-PR behavior. Unit tests cover all four code paths for the new helpers, and the PR author confirmed a clean tsc --noEmit.

No files require special attention.

Important Files Changed

Filename Overview
cli/src/commands/client/plugin.ts Adds probeTargetDiagnostics/formatTargetDiagnostics helpers, pre-install health probe in plugin install, and a standalone plugin target subcommand; JSON output shape is additive (flat PluginRecord fields are preserved via spread, with optional target field appended when probe runs)
cli/src/tests/plugin-init.test.ts Adds four unit tests covering the happy path, unreachable probe, and both render paths of formatTargetDiagnostics; mock get matches the interface expected by probeTargetDiagnostics
doc/plugins/LOCAL_PLUGIN_DEVELOPMENT.md Adds a "Targeting a branch / issue-workspace runtime" section with CLI resolution order, per-port dev workflow, curl verification, and a troubleshooting bullet; prose is accurate and consistent with the implementation

Reviews (2): Last reviewed commit: "feat(cli): surface plugin install target..." | Re-trigger Greptile

Comment thread cli/src/commands/client/plugin.ts Outdated
Local plugin development could silently install or test a plugin against a
stale Paperclip host that does not serve the current branch's routes, making
the plugin look broken when the real problem is the test target.

- Add `probeTargetDiagnostics`/`formatTargetDiagnostics` helpers that read
  GET /api/health and report the resolved API URL plus server
  status/version/deploymentMode/exposure.
- `plugin install` now prints these target diagnostics before installing
  (skippable with --no-verify-target); --json keeps its original flat
  PluginRecord shape (top-level id/pluginKey/version/status unchanged) and
  attaches target diagnostics as an additive top-level `target` field.
- Add a standalone `plugin target` command to inspect the install target
  without installing.
- Document running a branch / issue-workspace Paperclip service, pointing the
  CLI at it explicitly via --api-base/PAPERCLIP_API_URL, verifying a branch
  route end-to-end, and a troubleshooting entry for the stale-target symptom.
- Unit tests for the diagnostics helpers.
@devinfoley devinfoley force-pushed the feat/plugin-install-target-host branch from 6184aab to 27352f2 Compare June 24, 2026 15:46
@devinfoley devinfoley merged commit 1951c80 into master Jun 25, 2026
36 of 38 checks passed
@devinfoley devinfoley deleted the feat/plugin-install-target-host branch June 25, 2026 08:07
superbiche added a commit to mvanhorn/paperclip-plugin-discord that referenced this pull request Jun 27, 2026
Point users at `paperclipai plugin target` (paperclipai/paperclip#8575) to
confirm the resolved host + server version before filing activation/secret
errors that are usually host-version mismatches, not plugin bugs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SmVr9Go9oNU53wPw8oYoXa
btiknas pushed a commit to btiknas/paperclip that referenced this pull request Jun 30, 2026
…aperclipai#8575)

## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The CLI (`paperclipai plugin ...`) installs and manages plugins
against a Paperclip server resolved from `--api-base` /
`PAPERCLIP_API_URL` / the active profile / an inferred default
> - During local plugin development you can have more than one Paperclip
running (a released host plus a branch build on another port), and
nothing told you *which* instance a command actually talked to
> - So a plugin that depends on a route or response field only present
on a feature branch could be silently installed/tested against a stale
host, returning `API route not found`, and look broken when the real
problem was the test target
> - This pull request makes the install target explicit: it probes `GET
/api/health` and prints the resolved API URL + server
status/version/mode/exposure before installing, and adds a `plugin
target` command plus docs for running and verifying against a branch
service
> - The benefit is that local plugin authors can confirm they are
exercising the runtime they intend to, instead of debugging phantom
plugin bugs caused by hitting the wrong server

## Linked Issues or Issue Description

No public GitHub issue exists, so the underlying problem is described
inline following the feature-request template.

**Problem or motivation**

Local plugin development assumes a single Paperclip on
`http://127.0.0.1:3100`. When a plugin depends on server code that only
exists on a feature branch (a new scoped route, a new response field, a
new managed-resource capability), installing it into a long-lived host
still on older code makes the route/field missing there. The plugin
falls back or errors and *looks* broken, when the real cause is that it
was tested against the wrong runtime. The CLI already let you point at
any server, but it never surfaced which server you ended up on — so the
mistake was invisible.

**Proposed solution**

Make the install target explicit. Before `plugin install` runs, probe
`GET /api/health` and print the resolved API URL plus server
status/version/deploymentMode/exposure, so the developer can confirm
which Paperclip they are installing into. Add a standalone `plugin
target` command to inspect the target without installing, a
`--no-verify-target` escape hatch, and docs covering how to run a branch
service on its own port and verify a branch route end-to-end.

**Alternatives considered**

- Do nothing and rely on the existing `--api-base` / `PAPERCLIP_API_URL`
resolution — rejected because the gap was never the inability to point
at a branch server, it was the lack of feedback about which server was
actually hit.
- Fail the install when the target looks stale — rejected as too
aggressive; the probe is advisory and degrades gracefully when health
details are not exposed or the server is unreachable.

## Dedup Search

- [x] I searched the open and recently closed GitHub PRs for similar or
duplicate PRs — this is not a duplicate

## What Changed

- Add `probeTargetDiagnostics` / `formatTargetDiagnostics` helpers
(`cli/src/commands/client/plugin.ts`) that read `GET /api/health` and
report the resolved API URL plus server `status` / `version` /
`deploymentMode` / `deploymentExposure`.
- `plugin install` now prints these target diagnostics before
installing, so you can confirm which instance you are installing into.
Skippable with `--no-verify-target`.
- `plugin install --json` keeps its original flat `PluginRecord` shape
(top-level `id` / `pluginKey` / `version` / `status` are unchanged);
when the target was probed it gains an additional top-level `target`
field. Existing automation that reads the plugin fields keeps working.
- Add a standalone `paperclipai plugin target` command to inspect the
install target without installing anything.
- Update `doc/plugins/LOCAL_PLUGIN_DEVELOPMENT.md`: how the CLI resolves
its target, how to run a branch service on its own port and point the
CLI at it explicitly, an end-to-end check that the branch route is
actually served, and a troubleshooting entry for the stale-target
symptom.
- Unit tests for the diagnostics helpers (reachable + unreachable probe,
and both render paths).

## Verification

- `npx vitest run cli/src/__tests__/plugin-init.test.ts` — 10/10 pass
(covers `probeTargetDiagnostics` success/failure and
`formatTargetDiagnostics` rendering).
- CLI typecheck (`tsc --noEmit` in `cli/`) — clean.
- Manual: with a server running, `paperclipai plugin target` prints
`Target Paperclip: <url>` and the health line; `plugin install` prints
the same block before installing and `--no-verify-target` skips it.

## Risks

Low risk. The probe is read-only (`GET /api/health`) and runs before
install; if the server does not expose details it degrades to `ok (no
details exposed)`, and an unreachable target prints a remediation hint
rather than failing the command. The `--json` output keeps its original
flat shape, so existing scripts are unaffected. No server or schema
changes.

## Model Used

Claude Opus 4.7 (`claude-opus-4-7`), extended thinking + tool use, via
Claude Code.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

1 participant