cpyany 0.2.5 → 0.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +17 -17
  2. package/index.mjs +71 -80
  3. package/package.json +8 -14
package/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # cpyany
2
2
 
3
- One-command installer for the PingHumans MCP server.
3
+ One-command installer for cpyany, an MCP for coding agents that copy websites,
4
+ pages, and individual elements from reference sites.
4
5
 
5
6
  ```bash
6
7
  npx cpyany setup
@@ -8,25 +9,25 @@ npx cpyany setup
8
9
 
9
10
  Auto-detects every supported AI client installed on your machine (Claude Code,
10
11
  Claude Desktop, Cursor), opens a browser to authorize, and writes the resulting
11
- bearer token into each client's MCP config from a single OAuth flow. Restart
12
- the affected clients to load `ping_humans` and `get_ping`.
12
+ bearer token into each client's MCP config from a single OAuth flow.
13
+
14
+ After setup, ask your coding agent to copy from a reference:
15
+
16
+ ```text
17
+ Use cpyany to copy the hero section from https://example.com into this app.
18
+ ```
13
19
 
14
20
  ## Install paths
15
21
 
16
22
  | Client | MCP config we patch | Rule + skill we install | Auto-detected via |
17
23
  |---|---|---|---|
18
- | Claude Code | runs `claude mcp add --scope user --transport http …` (writes `~/.claude.json`) | `~/.claude/rules/pinghumans.md` + `~/.claude/skills/pinghumans-qa/SKILL.md` | `claude` on `PATH` |
24
+ | Claude Code | runs `claude mcp add --scope user --transport http …` (writes `~/.claude.json`) | `~/.claude/rules/cpyany.md` + `~/.claude/skills/cpyany/SKILL.md` | `claude` on `PATH` |
19
25
  | Claude Desktop | `~/Library/Application Support/Claude/claude_desktop_config.json` (mac) / `%APPDATA%\Claude\claude_desktop_config.json` (win) — bridged via `mcp-remote` | _(none — Claude Desktop has no rules/skills mechanism)_ | the per-platform Claude config dir exists |
20
- | Cursor | `~/.cursor/mcp.json` | `~/.cursor/rules/pinghumans.mdc` (`alwaysApply: true`) + `~/.cursor/skills/pinghumans-qa/SKILL.md` | `~/.cursor` exists |
26
+ | Cursor | `~/.cursor/mcp.json` | `~/.cursor/rules/cpyany.mdc` (`alwaysApply: true`) + `~/.cursor/skills/cpyany/SKILL.md` | `~/.cursor` exists |
21
27
 
22
- Guidance is two-tier (the same layout Context7 uses): a short always-loaded
23
- rule telling the agent _when_ to reach for PingHumans, and a `pinghumans-qa`
24
- skill with the full QA workflow that the agent loads only when it actually
25
- files or collects a human test. Installs that predate 0.1.0 (which appended a
26
- marker block to `~/.claude/CLAUDE.md`) are migrated automatically on any CLI
27
- invocation. `cpyany remove` cleans everything up. The published package
28
- also keeps `copyanything` and `pinghumans` as legacy binary aliases during
29
- the rename.
28
+ Guidance is two-tier: a short always-loaded rule telling the agent when to use
29
+ cpyany, and a deeper `cpyany` skill with the copy-from-reference workflow.
30
+ `cpyany remove` cleans everything up.
30
31
 
31
32
  ## Restrict to one client
32
33
 
@@ -39,8 +40,7 @@ npx cpyany setup --client claude-code
39
40
 
40
41
  ## Skip the browser
41
42
 
42
- If you'd rather paste the snippet manually, sign in at
43
- [pinghumans.com/dashboard](https://pinghumans.com/dashboard) and copy the
43
+ If you'd rather paste the snippet manually, open the app dashboard and copy the
44
44
  config block from the **MCP integration** section.
45
45
 
46
46
  ## Remove
@@ -52,5 +52,5 @@ npx cpyany remove --client claude-desktop # just one
52
52
 
53
53
  ## License
54
54
 
55
- UNLICENSED — the CLI is published for ease of installation, but the source
56
- of the PingHumans server is not open-licensed.
55
+ UNLICENSED — the CLI is published for ease of installation, but the service
56
+ source is not open-licensed.
package/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- // pinghumans — install the PingHumans MCP server in your AI client.
2
+ // cpyany — install the cpyany MCP server in your AI client.
3
3
  // One command: shows a one-time code, you approve it in the browser
4
4
  // (RFC 8628 device flow), your client configs get patched, you're done.
5
5
 
@@ -11,7 +11,7 @@ import { execFile } from "node:child_process";
11
11
  import { promisify } from "node:util";
12
12
  import open from "open";
13
13
 
14
- const VERSION = "0.2.5";
14
+ const VERSION = "0.2.6";
15
15
  const execFileP = promisify(execFile);
16
16
  const APP_URL = process.env.PINGHUMANS_APP_URL ?? "https://pinghumans.com";
17
17
  // Hoisted with the other top-of-module consts — the entry try-block runs
@@ -87,82 +87,67 @@ const RULES_MARKER_START =
87
87
  const RULES_MARKER_END = "<!-- pinghumans-mcp:end -->";
88
88
 
89
89
  // Two-tier guidance (Context7-style):
90
- // RULE_BODY — short, always-loaded: WHEN to reach for PingHumans.
90
+ // RULE_BODY — short, always-loaded: WHEN to reach for cpyany.
91
91
  // SKILL_BODY — full workflow, loaded on demand when the agent does QA.
92
- const RULE_BODY = `Use the PingHumans MCP to put a real human in the verification loop whenever you build or change something you can't verify yourself — rendered UI, animation smoothness, real-device behavior, real third-party side-effects (OAuth round-trips, receipt emails, payments), or judgment calls about taste, clarity, and confusion. Even when the code looks right: you can't see the page, a human can. Don't caveat with "I'm guessing" — file a test or a poll instead.
92
+ const RULE_BODY = `Use cpyany when the user asks you to copy, clone, recreate, or match a website, page, section, component, or visual element from a reference URL, screenshot, or existing site.
93
93
 
94
- Do not use for: anything verifiable with code, tests, or a local browser; objective questions answerable from docs or search.
94
+ Do not use for: unrelated implementation work, backend-only tasks, or generic UI work with no reference to copy from.
95
95
 
96
96
  ## Steps
97
97
 
98
- 1. Built/changed a UI? Deploy or tunnel it to a PUBLICLY reachable URL (localhost won't work — a remote human opens it), make sure \`<script src="https://pinghumans.com/qa-toolbar.js"></script>\` is in the preview build's HTML, then call \`request_human_test\` with structured \`steps\` — machine-verifiable \`check\` rules plus inline \`options\` (e.g. \`["Smooth","Janky"]\`) for qualitative steps
99
- 2. Quick taste/preference read with no build to test? Call \`ping_humans\` (blocks ~50s)
100
- 3. File tests early and keep working while the human tests — collect results with \`get_test_results\` at checkpoints, \`wait_for_results\` when blocked, or \`npx cpyany wait <ping_id>\` as a background task (foreground in one-shot runs)
101
- 4. When results arrive, treat the human's verdict/comments as acceptance criteria. Use browser/Chrome checks to implement and confirm those criteria, not to overrule the worker.
102
- 5. For the full QA workflow (verifiable steps, evidence, waiting modes, acting on results), use the pinghumans-qa skill
98
+ 1. Identify the reference URL, screenshot, or specific element/section the user wants copied.
99
+ 2. Preserve the target app's framework and style conventions; copy the look and behavior, not the reference site's codebase wholesale.
100
+ 3. Match layout, spacing, typography, color, imagery, responsive behavior, and interaction states as closely as practical.
101
+ 4. Verify against the reference with browser inspection or screenshots before reporting completion.
102
+ 5. For the full copy-from-reference workflow, use the cpyany skill.
103
103
  `;
104
104
 
105
105
  const SKILL_BODY = `---
106
- name: pinghumans-qa
107
- description: This skill should be used when the user has built or changed a UI and wants it verified by a real human, asks for human QA / human testing / human feedback on a build, or wants to check the results of a previously filed human test. Also activates for subjective gut-checks (taste, copy, design preference) via PingHumans.
106
+ name: cpyany
107
+ description: Use this skill when the user asks to copy, clone, recreate, or match a website, landing page, section, component, or visual element from a reference site, URL, screenshot, or design inspiration.
108
108
  ---
109
109
 
110
- When you've built or changed something you can't verify yourself, use PingHumans to have a real human test it and return structured results a verdict, pinned component comments with CSS selectors, a per-step proof-of-work report, and screenshots you can open.
110
+ cpyany helps coding agents recreate a reference site's visual design in the current codebase. The goal is to copy the user's requested look, layout, and interaction in one pass while still fitting the target app's framework and component conventions.
111
111
 
112
112
  ## When to Use This Skill
113
113
 
114
- - You shipped a UI change and can't see the rendered result ("does this look right on a real phone?", "is this animation smooth or janky?")
115
- - The check needs real-world reach a sandbox doesn't have ("sign in with Google did it actually log you in?", "did the test purchase email a receipt?")
116
- - Sense-making ("complete the checkout anything confusing or broken?")
117
- - A previously filed test needs its results collected
118
- - A quick subjective read with no build to test ("which logo looks more professional?") — use \`ping_humans\` for these
114
+ - "Copy this homepage/hero/pricing card/nav from <url>"
115
+ - "Make this section look like the reference"
116
+ - "Clone this element into my app"
117
+ - "Use this screenshot/site as visual inspiration and build it here"
118
+ - "Match the spacing, typography, and styling of this page"
119
119
 
120
- ## How to File a Test
120
+ ## Workflow
121
121
 
122
- ### Step 1: Make the build reachable and instrumented
122
+ ### Step 1: Understand the copy target
123
123
 
124
- The \`url\` must be PUBLICLY reachable — a remote human opens it, so localhost won't work: tunnel it first (ngrok, cloudflared) or deploy a preview. The toolbar script is REQUIRED for pinned comments and step auto-verification one line, once per project, in the preview build's HTML (root layout / index template), preview/dev only:
124
+ Clarify whether the user wants a whole page, a section, a single component, or only a style direction. If they give a URL, inspect the exact target. If they give a screenshot, use it as the visual source of truth.
125
125
 
126
- \`\`\`html
127
- <script src="https://pinghumans.com/qa-toolbar.js"></script>
128
- \`\`\`
126
+ ### Step 2: Recreate in the target codebase
129
127
 
130
- No per-task id needed the tester's claim link carries the task token. \`request_human_test\`'s result reports whether the script was detected (\`toolbar_detected\`) if it warns, fix the build and redeploy before testers arrive.
128
+ Use existing project components, styling systems, tokens, and routing patterns. Prefer copying the visual outcome rather than importing unrelated abstractions from the reference. Preserve accessibility and responsive behavior.
131
129
 
132
- ### Step 2: File with verifiable steps
130
+ ### Step 3: Match the visible details
133
131
 
134
- Call \`request_human_test\` with a \`url\`, structured \`steps\`, and optional \`verdict_options\` / \`require_evidence\`. You wrote the code, so you know what "done" looks like — attach a \`check\` rule to every step you can:
132
+ Pay close attention to:
135
133
 
136
- - \`{type:"url", pattern:"/pricing"}\` — tester actually navigated there
137
- - \`{type:"click", selector:".checkout button"}\` — tester actually clicked it
138
- - \`{type:"fill", selector:"input[type=email]"}\` tester actually typed
139
- - \`{type:"comment"}\` tester pinned at least one comment
134
+ - spacing and alignment
135
+ - typography scale and weight
136
+ - color, gradients, borders, shadows, and blur
137
+ - imagery, icon treatment, and decorative elements
138
+ - hover/focus states and animation feel
139
+ - desktop and mobile layout
140
140
 
141
- The toolbar observes the page and auto-verifies them; results report each step as ✓ auto (machine-verified), ✓ manual, or ✗ not done — your proof the tester did the work. Leave \`check\` null only for pure-judgment steps.
141
+ ### Step 4: Verify
142
142
 
143
- When a step asks a question rather than performs an action, add \`options\` (2–4 short labels, e.g. \`{text:"Scroll the homepage smooth or janky?", options:["Smooth","Janky"]}\`): the tester answers with one tap right on the step and the pick comes back in \`steps_result[].answer\` far richer than a bare checkmark. A step with a \`selector\` in its check also gets highlighted on the page for the tester, so prefer real selectors.
144
-
145
- ### Step 3: Wait the right way
146
-
147
- The call does NOT block (QA takes minutes) — it returns \`status='pending'\` immediately. In order of preference:
148
-
149
- 1. **File early, keep working.** The human tests in parallel — their time is free to you.
150
- 2. **Interactive session with background shell tasks:** launch \`npx cpyany wait <ping_id>\` in the background — it exits the moment results land, waking you with the results.
151
- 3. **One-shot run (subagent / final answer due this run):** do NOT end your run while results are pending — nothing can wake you afterwards, and a backgrounded waiter dies with you. Run \`npx cpyany wait <ping_id>\` in the FOREGROUND, or call \`wait_for_results(ping_id)\` in a loop until complete.
152
- 4. **Checkpoint checks:** \`get_test_results(ping_id)\` at natural pauses.
153
- 5. **Genuinely blocked:** \`wait_for_results(ping_id)\` blocks server-side (~45s per call, free) and returns early on news. Never hand-roll sleep loops.
154
-
155
- ### Step 4: Act on the results
156
-
157
- Each result has a verdict, notes, pinned comments, per-step truth, and a screenshot URL — open and look at it. Comments carry CSS selectors that point at the exact component to change. Treat the human's verdict/comments as acceptance criteria, not suggestions. Browser, Chrome, screenshots, source checks, and getComputedStyle are implementation aids: use them to satisfy and confirm the worker's requested changes, never to decide the worker was wrong.
158
-
159
- **Clone-compare tasks** (filed with both \`url\` = the original and \`draft_url\` = your clone): before you touch the clone, call \`check_og_source(ping_id)\`. It reads the ORIGINAL's authored HTML source for exactly the elements a human flagged and diffs each against your clone. The worker's alignment feedback is the acceptance criteria: modify HTML/CSS so every requested move/match/delete is met with reasonable visual accuracy. Allow small manual error in hand-placed move/align markers, but preserve the worker's intended direction and target. Use the returned authored classes to implement the feedback; only fall back to measuring/live inspection for pairs marked \`needs_live_inspection\`, and only to satisfy the human request, not to replace it with your own visual judgment.
143
+ Run the app, inspect the result in a browser, and compare it to the reference. Iterate until the copied result is recognizably faithful.
160
144
 
161
145
  ## Guidelines
162
146
 
163
- - **Pricing**: ~$0.05 per response received; filing is free, results are charged
164
- - **Quick polls**: \`ping_humans\` for taste questions blocks ~50s; poll \`get_ping(ping_id)\` for late arrivals
165
- - **Pending isn't dead**: "a tester has claimed the task and is testing right now" means results are imminent — keep waiting
147
+ - Do not claim pixel perfection unless you verified it.
148
+ - Do not copy private assets or secrets from the reference.
149
+ - Do not add heavy dependencies just to mimic a small visual effect.
150
+ - When the reference and target app conflict, preserve the target app's architecture and recreate the look locally.
166
151
  `;
167
152
 
168
153
  // ─── Entry ────────────────────────────────────────────────────────────────
@@ -280,7 +265,7 @@ async function setup(client) {
280
265
  track("setup_complete", { client_label: t });
281
266
  }
282
267
 
283
- console.log(`\n${pc.green("✔")} PingHumans setup complete\n`);
268
+ console.log(`\n${pc.green("✔")} cpyany setup complete\n`);
284
269
  for (const { client: c, entries } of summary) {
285
270
  console.log(` ${pc.bold(prettyClient(c))}`);
286
271
  for (const e of entries) {
@@ -301,7 +286,7 @@ async function setup(client) {
301
286
  if (restartList) {
302
287
  console.log(`\nRestart ${restartList} to load the MCP server.`);
303
288
  }
304
- console.log(`Try it: ask your agent to "use ping_humans to ask if pizza is cooler than tacos."`);
289
+ console.log(`Try it: ask your agent to "use cpyany to copy the hero section from a reference site."`);
305
290
  }
306
291
 
307
292
  async function remove(client) {
@@ -319,7 +304,7 @@ async function remove(client) {
319
304
  }
320
305
  for (const t of targets) {
321
306
  await unpatchConfig(t);
322
- console.log(`✓ Removed pinghumans from ${prettyClient(t)} config.`);
307
+ console.log(`✓ Removed cpyany from ${prettyClient(t)} config.`);
323
308
  await unpatchRules(t);
324
309
  track("remove", { client_label: t });
325
310
  }
@@ -494,7 +479,7 @@ async function performDeviceLogin() {
494
479
  const linkLine = `${pc.dim("Open this link to approve:")}\n${pc.cyan(authorization.verification_uri_complete)}\n\n${pc.dim("Or visit")} ${pc.cyan(authorization.verification_uri)} ${pc.dim("and enter the code above.")}`;
495
480
  console.log(
496
481
  boxen(`${codeLine}\n\n${linkLine}`, {
497
- title: "Sign in to PingHumans",
482
+ title: "Sign in to cpyany",
498
483
  titleAlignment: "left",
499
484
  padding: 1,
500
485
  margin: { top: 1, bottom: 1, left: 2, right: 2 },
@@ -607,7 +592,8 @@ async function patchConfig(client, token) {
607
592
  // Claude Desktop doesn't natively support Streamable HTTP MCP servers
608
593
  // (only stdio). Bridge via the community mcp-remote package, which spawns
609
594
  // a stdio server that proxies to our hosted HTTP MCP.
610
- config.mcpServers.pinghumans = {
595
+ delete config.mcpServers.pinghumans;
596
+ config.mcpServers.cpyany = {
611
597
  command: "npx",
612
598
  args: [
613
599
  "-y",
@@ -619,7 +605,8 @@ async function patchConfig(client, token) {
619
605
  };
620
606
  } else {
621
607
  // Cursor + others: native streamable-HTTP works.
622
- config.mcpServers.pinghumans = {
608
+ delete config.mcpServers.pinghumans;
609
+ config.mcpServers.cpyany = {
623
610
  url: `${APP_URL}/api/mcp`,
624
611
  headers: { Authorization: `Bearer ${token}` },
625
612
  };
@@ -630,18 +617,16 @@ async function patchConfig(client, token) {
630
617
 
631
618
  async function unpatchConfig(client) {
632
619
  if (client === "claude-code") {
633
- try {
634
- await execFileP("claude", ["mcp", "remove", "pinghumans", "--scope", "user"]);
635
- } catch (err) {
636
- console.error(`Couldn't run \`claude mcp remove\`: ${err.message}`);
637
- }
620
+ await execFileP("claude", ["mcp", "remove", "cpyany", "--scope", "user"]).catch(() => {});
621
+ await execFileP("claude", ["mcp", "remove", "pinghumans", "--scope", "user"]).catch(() => {});
638
622
  return;
639
623
  }
640
624
  const path = configPath(client);
641
625
  try {
642
626
  const text = await readFile(path, "utf8");
643
627
  const config = JSON.parse(text);
644
- if (config?.mcpServers?.pinghumans) {
628
+ if (config?.mcpServers?.cpyany || config?.mcpServers?.pinghumans) {
629
+ delete config.mcpServers.cpyany;
645
630
  delete config.mcpServers.pinghumans;
646
631
  await writeFile(path, JSON.stringify(config, null, 2) + "\n");
647
632
  }
@@ -653,7 +638,7 @@ async function unpatchConfig(client) {
653
638
  // ─── Agent rules ──────────────────────────────────────────────────────────
654
639
  //
655
640
  // In addition to MCP tool descriptions, we install a short prose "rule"
656
- // telling the agent WHEN to reach for ping_humans. Tool descriptions only
641
+ // telling the agent WHEN to reach for cpyany. Tool descriptions only
657
642
  // fire during tool selection; rules sit in the agent's persistent
658
643
  // instructions and bias it toward the tool earlier in reasoning.
659
644
  //
@@ -661,7 +646,7 @@ async function unpatchConfig(client) {
661
646
  // - Claude Code → ~/.claude/CLAUDE.md (the canonical user-memory file
662
647
  // Claude Code auto-loads at session start). Marker tags so re-install
663
648
  // and remove are clean even if the user hand-edits the file.
664
- // - Cursor → ~/.cursor/rules/pinghumans.mdc (Cursor's auto-loaded
649
+ // - Cursor → ~/.cursor/rules/cpyany.mdc (Cursor's auto-loaded
665
650
  // rules dir, with `alwaysApply: true` frontmatter).
666
651
  // - Claude Desktop → no equivalent; skipped.
667
652
  //
@@ -686,17 +671,17 @@ function stripMarkerBlock(text) {
686
671
  // mechanism, so it gets MCP config only.
687
672
  function rulePath(client) {
688
673
  if (client === "claude-code")
689
- return join(homedir(), ".claude", "rules", "pinghumans.md");
674
+ return join(homedir(), ".claude", "rules", "cpyany.md");
690
675
  if (client === "cursor")
691
- return join(homedir(), ".cursor", "rules", "pinghumans.mdc");
676
+ return join(homedir(), ".cursor", "rules", "cpyany.mdc");
692
677
  return null;
693
678
  }
694
679
 
695
680
  function skillPath(client) {
696
681
  if (client === "claude-code")
697
- return join(homedir(), ".claude", "skills", "pinghumans-qa", "SKILL.md");
682
+ return join(homedir(), ".claude", "skills", "cpyany", "SKILL.md");
698
683
  if (client === "cursor")
699
- return join(homedir(), ".cursor", "skills", "pinghumans-qa", "SKILL.md");
684
+ return join(homedir(), ".cursor", "skills", "cpyany", "SKILL.md");
700
685
  return null;
701
686
  }
702
687
 
@@ -779,7 +764,7 @@ async function refreshStaleRules({ verbose = false } = {}) {
779
764
  }
780
765
 
781
766
  if (updated.length > 0) {
782
- console.log(`↻ Refreshed PingHumans agent rules (v${VERSION}):`);
767
+ console.log(`↻ Refreshed cpyany agent rules (v${VERSION}):`);
783
768
  for (const p of updated) console.log(` ${p}`);
784
769
  track("rules_refresh");
785
770
  } else if (verbose) {
@@ -812,6 +797,13 @@ async function patchClaudeCodeViaCli(token) {
812
797
  // It writes to ~/.claude.json (or similar) for us.
813
798
  try {
814
799
  // Remove any existing config first, otherwise `mcp add` errors on dupes.
800
+ await execFileP("claude", [
801
+ "mcp",
802
+ "remove",
803
+ "cpyany",
804
+ "--scope",
805
+ "user",
806
+ ]).catch(() => {});
815
807
  await execFileP("claude", [
816
808
  "mcp",
817
809
  "remove",
@@ -829,7 +821,7 @@ async function patchClaudeCodeViaCli(token) {
829
821
  "user",
830
822
  "--transport",
831
823
  "http",
832
- "pinghumans",
824
+ "cpyany",
833
825
  `${APP_URL}/api/mcp`,
834
826
  "--header",
835
827
  `Authorization: Bearer ${token}`,
@@ -872,7 +864,7 @@ function prettyClient(client) {
872
864
  }
873
865
 
874
866
  function printHelp() {
875
- console.log(`cpyany — install the PingHumans MCP server in your AI client.
867
+ console.log(`cpyany — install the cpyany MCP server in your AI client.
876
868
 
877
869
  Usage:
878
870
  cpyany setup [--client claude-code|claude-desktop|cursor]
@@ -881,7 +873,7 @@ Usage:
881
873
  # block until a human test has results (exit 0 = news,
882
874
  # 2 = timed out). Run it in the background after filing
883
875
  # a test so your agent gets woken when results land.
884
- cpyany whoami # show which PingHumans account this machine's token belongs to
876
+ cpyany whoami # show which account this machine's token belongs to
885
877
  cpyany rules # refresh the installed agent rules to this version
886
878
  cpyany version
887
879
 
@@ -893,7 +885,6 @@ Setup opens your browser to ${APP_URL}/cli-auth, generates a fresh bearer
893
885
  token after you sign in, and writes it into each client's MCP config.
894
886
 
895
887
  Aliases: --claude (= --claude-desktop), --code (= --claude-code).
896
- Legacy binary alias: pinghumans.
897
888
  `);
898
889
  }
899
890
 
@@ -911,7 +902,7 @@ Legacy binary alias: pinghumans.
911
902
  // Hoisted as a function — the entry dispatch runs before bottom-of-module
912
903
  // consts initialize (the 0.0.4 TDZ lesson, again).
913
904
  function credsPath() {
914
- return join(homedir(), ".config", "pinghumans", "credentials.json");
905
+ return join(homedir(), ".config", "cpyany", "credentials.json");
915
906
  }
916
907
 
917
908
  async function readCreds() {
@@ -983,7 +974,7 @@ async function validateStoredToken() {
983
974
  const warn = (s) => (pc ? pc.yellow(s) : s);
984
975
  console.error(
985
976
  "\n" +
986
- warn("⚠ Your PingHumans token is no longer valid") +
977
+ warn("⚠ Your cpyany token is no longer valid") +
987
978
  " (revoked, or the account was deleted).\n" +
988
979
  " Re-link this machine: " +
989
980
  (pc ? pc.cyan("npx cpyany setup") : "npx cpyany setup") +
@@ -1007,7 +998,7 @@ async function resolveLocalToken() {
1007
998
  for (const p of candidates) {
1008
999
  try {
1009
1000
  const cfg = JSON.parse(await readFile(p, "utf8"));
1010
- const entry = cfg?.mcpServers?.pinghumans;
1001
+ const entry = cfg?.mcpServers?.cpyany ?? cfg?.mcpServers?.pinghumans;
1011
1002
  const header = entry?.headers?.Authorization ?? entry?.headers?.authorization;
1012
1003
  const m = /Bearer\s+(\S+)/.exec(header ?? "");
1013
1004
  if (m) return m[1];
@@ -1027,7 +1018,7 @@ async function waitForResultsCli(rest) {
1027
1018
  const token = await resolveLocalToken();
1028
1019
  if (!token) {
1029
1020
  throw new Error(
1030
- "No PingHumans token found. Run `npx cpyany setup` first."
1021
+ "No cpyany token found. Run `npx cpyany setup` first."
1031
1022
  );
1032
1023
  }
1033
1024
 
@@ -1061,7 +1052,7 @@ async function waitForResultsCli(rest) {
1061
1052
 
1062
1053
  if (status === "not_found") {
1063
1054
  throw new Error(
1064
- "Ping not found for this account. Results are asker-scoped — `wait` only works on tests filed with the same PingHumans account."
1055
+ "Ping not found for this account. Results are asker-scoped — `wait` only works on tests filed with the same cpyany account."
1065
1056
  );
1066
1057
  }
1067
1058
  if (status !== "pending" || received > baseline) {
package/package.json CHANGED
@@ -1,13 +1,11 @@
1
1
  {
2
2
  "name": "cpyany",
3
- "version": "0.2.5",
4
- "description": "Install the PingHumans MCP server in Claude Desktop, Claude Code, or Cursor with one command.",
3
+ "version": "0.2.6",
4
+ "description": "Install cpyany so coding agents can copy websites, pages, and elements from references.",
5
5
  "type": "module",
6
6
  "main": "index.mjs",
7
7
  "bin": {
8
- "cpyany": "index.mjs",
9
- "copyanything": "index.mjs",
10
- "pinghumans": "index.mjs"
8
+ "cpyany": "index.mjs"
11
9
  },
12
10
  "files": [
13
11
  "index.mjs",
@@ -26,12 +24,6 @@
26
24
  "ora": "^9.4.0",
27
25
  "picocolors": "^1.1.1"
28
26
  },
29
- "homepage": "https://pinghumans.com",
30
- "repository": {
31
- "type": "git",
32
- "url": "git+https://github.com/alex-durango/pinghumans.git",
33
- "directory": "cli"
34
- },
35
27
  "license": "UNLICENSED",
36
28
  "private": false,
37
29
  "publishConfig": {
@@ -43,9 +35,11 @@
43
35
  "claude",
44
36
  "cursor",
45
37
  "ai",
46
- "humans",
47
38
  "cpyany",
48
- "copyanything",
49
- "pinghumans"
39
+ "copy",
40
+ "website",
41
+ "design",
42
+ "reference",
43
+ "clone"
50
44
  ]
51
45
  }