moshcode 0.28.0 → 0.29.0

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.
@@ -8,15 +8,15 @@
8
8
  },
9
9
  "plugins": [
10
10
  {
11
- "name": "ticker",
11
+ "name": "stocks",
12
12
  "description": "Equity research slash commands backed by advis0r.com: scored reports, extracted signals, transcript search, company-name lookup, and ranked watchlists.",
13
- "source": "./plugins/ticker",
13
+ "source": "./plugins/stocks",
14
14
  "category": "productivity",
15
15
  "author": {
16
16
  "name": "moshcoder",
17
17
  "url": "https://moshcode.sh"
18
18
  },
19
- "homepage": "https://github.com/moshcoder/moshcode#ticker",
19
+ "homepage": "https://github.com/moshcoder/moshcode#stocks",
20
20
  "keywords": ["stocks", "equity", "research", "markets", "advis0r"]
21
21
  },
22
22
  {
package/README.md CHANGED
@@ -371,12 +371,12 @@ inside your engine too:
371
371
 
372
372
  ```sh
373
373
  moshcode plugin list # what the marketplace ships, and who can take it
374
- moshcode plugin install # add the marketplace + install `ticker`
374
+ moshcode plugin install # add the marketplace + install `stocks`
375
375
  moshcode plugin install crypto # add the marketplace + install `crypto`
376
- moshcode plugin remove ticker # take it back off
376
+ moshcode plugin remove stocks # take it back off
377
377
  ```
378
378
 
379
- `ticker@moshcode` adds `/stocks`, `/signals`, `/research`, `/lookup`,
379
+ `stocks@moshcode` adds `/stocks`, `/signals`, `/research`, `/lookup`,
380
380
  `/reports`, and `/discover` — the same advis0r research surface described above,
381
381
  driven from inside a coding session.
382
382
 
@@ -392,10 +392,24 @@ The equivalent by hand:
392
392
 
393
393
  ```sh
394
394
  claude plugin marketplace add moshcoder/moshcode
395
- claude plugin install ticker@moshcode
395
+ claude plugin install stocks@moshcode
396
396
  claude plugin install crypto@moshcode
397
397
  ```
398
398
 
399
+ ### Upgrading from `ticker@moshcode`
400
+
401
+ `stocks` was called `ticker` before v0.29.0. Installing the new id does **not**
402
+ replace the old one — engines install plugins side by side, so `/stocks` would
403
+ come from two plugins at once. Remove the old id first:
404
+
405
+ ```sh
406
+ moshcode plugin remove ticker
407
+ moshcode plugin install stocks
408
+ ```
409
+
410
+ `remove ticker` keeps working for exactly that reason, even though
411
+ `install ticker` no longer does.
412
+
399
413
  Claude Code is currently the only engine with a plugin primitive. The others are
400
414
  reported as skipped with a reason, the same way they are for skills, rather than
401
415
  being left out of the summary. `MOSHCODE_PLUGIN_SOURCE=.` installs from a local
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "moshcode",
3
- "version": "0.28.0",
3
+ "version": "0.29.0",
4
4
  "type": "module",
5
5
  "description": "moshcode — a metal wrapper for coding engines and native UGig/CoinPay workflow CLIs, with OpenPRD and moshscript",
6
6
  "repository": {
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "$schema": "https://anthropic.com/claude-code/plugin.schema.json",
3
- "name": "ticker",
3
+ "name": "stocks",
4
4
  "description": "Equity research slash commands backed by advis0r.com: scored reports, extracted signals, transcript search, company-name lookup, and ranked watchlists.",
5
5
  "version": "0.1.0",
6
6
  "author": {
7
7
  "name": "moshcoder",
8
8
  "url": "https://moshcode.sh"
9
9
  },
10
- "homepage": "https://github.com/moshcoder/moshcode#ticker",
10
+ "homepage": "https://github.com/moshcoder/moshcode#stocks",
11
11
  "license": "MIT",
12
12
  "keywords": ["stocks", "equity", "research", "markets", "advis0r"]
13
13
  }
@@ -1,4 +1,4 @@
1
- # ticker — equity research in your engine 🤘
1
+ # stocks — equity research in your engine 🤘
2
2
 
3
3
  Slash commands backed by [advis0r.com](https://advis0r.com/api): scored research
4
4
  reports, extracted signals with sources, transcript search, company-name lookup,
@@ -13,11 +13,23 @@ and ranked watchlists.
13
13
  | `/reports` | every stored report, best score first |
14
14
  | `/discover fusion` | a ranked watchlist for a topic (slow) |
15
15
 
16
- The headline command is `/stocks`, not `/ticker` — it was renamed so the verb
17
- says what it covers, now that `/crypto` sits beside it. **The plugin itself is
18
- still `ticker@moshcode`**, deliberately: renaming the plugin would force
19
- everyone who already installed it to uninstall and reinstall, and an id is not
20
- worth that. Existing installs pick `/stocks` up on the next plugin update.
16
+ ## Upgrading from `ticker@moshcode`
17
+
18
+ This plugin used to be called `ticker`. Both it and its headline command were
19
+ renamed so the name says which market it covers, now that `/crypto` sits beside
20
+ it.
21
+
22
+ Installing the new one does **not** replace the old one — engines install
23
+ plugins side by side, so `/stocks` would come from two plugins at once. Remove
24
+ the old id first:
25
+
26
+ ```bash
27
+ moshcode plugin remove ticker
28
+ moshcode plugin install stocks
29
+ ```
30
+
31
+ `moshcode plugin remove ticker` keeps working for exactly this reason, even
32
+ though `moshcode plugin install ticker` no longer does.
21
33
 
22
34
  ## Install
23
35
 
@@ -29,7 +41,7 @@ Or straight from Claude Code:
29
41
 
30
42
  ```bash
31
43
  claude plugin marketplace add moshcoder/moshcode
32
- claude plugin install ticker@moshcode
44
+ claude plugin install stocks@moshcode
33
45
  ```
34
46
 
35
47
  Restart the engine afterwards — a newly installed plugin is not live in a
@@ -10,7 +10,7 @@ import {
10
10
  } from "./skills.mjs";
11
11
  import {
12
12
  MARKETPLACE_NAME, PLUGINS, PLUGIN_ENGINES, marketplaceSource, planPluginCommand,
13
- pluginId, resolvePlugin, runPluginCommand,
13
+ pluginId, resolvePlugin, resolveRetiredPlugin, runPluginCommand,
14
14
  } from "./plugins.mjs";
15
15
  import { catalogList, resolveCatalog } from "./mcp-catalog.mjs";
16
16
  import { MCP_VERBS, PLUGIN_VERBS, SKILL_VERBS } from "./cli-schema.mjs";
@@ -315,10 +315,22 @@ export async function pluginCommand(tokens, { run, installedSet } = {}) {
315
315
  const stray = rest.find((t) => String(t).startsWith("-"));
316
316
  if (stray) { console.log(err(`unknown plugin flag "${stray}"`)); return 1; }
317
317
 
318
- const plugin = resolvePlugin(rest[0]);
318
+ let plugin = resolvePlugin(rest[0]);
319
319
  if (!plugin) {
320
- console.log(err(`unknown plugin "${rest[0]}" this marketplace ships ${PLUGINS.map((p) => p.name).join(", ")}`));
321
- return 1;
320
+ // A retired name still has to be removable: the old plugin is installed in
321
+ // someone's engine right now, and installing its replacement puts a second
322
+ // copy of the same slash commands beside it rather than replacing it.
323
+ const retired = resolveRetiredPlugin(rest[0]);
324
+ if (retired && verb === "remove") {
325
+ plugin = { name: retired.name, description: `retired — renamed to ${retired.renamedTo}`, commands: [] };
326
+ } else if (retired) {
327
+ console.log(err(`"${retired.name}" is now "${retired.renamedTo}" — install ${bone(pluginId(retired.renamedTo))}`));
328
+ console.log(info(`already have the old one? ${bone(`moshcode plugin remove ${retired.name}`)} first`));
329
+ return 1;
330
+ } else {
331
+ console.log(err(`unknown plugin "${rest[0]}" — this marketplace ships ${PLUGINS.map((p) => p.name).join(", ")}`));
332
+ return 1;
333
+ }
322
334
  }
323
335
 
324
336
  const source = marketplaceSource();
package/src/plugins.mjs CHANGED
@@ -29,7 +29,7 @@ export function marketplaceSource(env = process.env) {
29
29
  /** The plugins this marketplace ships. Mirrors .claude-plugin/marketplace.json. */
30
30
  export const PLUGINS = [
31
31
  {
32
- name: "ticker",
32
+ name: "stocks",
33
33
  description: "equity research slash commands backed by advis0r.com",
34
34
  commands: ["/stocks", "/signals", "/research", "/lookup", "/reports", "/discover"],
35
35
  },
@@ -42,12 +42,38 @@ export const PLUGINS = [
42
42
 
43
43
  export const DEFAULT_PLUGIN = PLUGINS[0].name;
44
44
 
45
+ /**
46
+ * Plugins this marketplace no longer ships, and what replaced them.
47
+ *
48
+ * A renamed plugin is not the same problem as a renamed command. The old
49
+ * command simply stops existing; an old *plugin* is still sitting installed in
50
+ * someone's engine, still serving its slash commands, and the new one installs
51
+ * alongside it rather than over it — so `/stocks` would resolve to two plugins
52
+ * at once. Removal therefore has to keep reaching a name that install refuses.
53
+ */
54
+ export const RETIRED_PLUGINS = [
55
+ { name: "ticker", renamedTo: "stocks" },
56
+ ];
57
+
45
58
  export function resolvePlugin(name) {
46
59
  if (!name) return PLUGINS.find((p) => p.name === DEFAULT_PLUGIN) ?? null;
47
60
  const key = String(name).toLowerCase().replace(/@.*$/, "");
48
61
  return PLUGINS.find((p) => p.name === key) ?? null;
49
62
  }
50
63
 
64
+ /**
65
+ * A retired plugin by its old name, or null.
66
+ *
67
+ * Deliberately separate from resolvePlugin: `remove ticker` must work so the
68
+ * stale install can be cleaned up, and `install ticker` must not, or the rename
69
+ * never actually happens.
70
+ */
71
+ export function resolveRetiredPlugin(name) {
72
+ if (!name) return null;
73
+ const key = String(name).toLowerCase().replace(/@.*$/, "");
74
+ return RETIRED_PLUGINS.find((p) => p.name === key) ?? null;
75
+ }
76
+
51
77
  /** Fully-qualified plugin id, the form `claude plugin install` disambiguates with. */
52
78
  export function pluginId(name) {
53
79
  return `${name}@${MARKETPLACE_NAME}`;
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes