Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"$schema": "https://anthropic.com/claude-code/marketplace.schema.json",
"name": "moshcode",
"description": "moshcode's own Claude Code plugins — the pit's slash commands, in your engine",
"owner": {
"name": "moshcoder",
"url": "https://moshcode.sh"
},
"plugins": [
{
"name": "ticker",
"description": "Equity research slash commands backed by advis0r.com: scored reports, extracted signals, transcript search, company-name lookup, and ranked watchlists.",
"source": "./plugins/ticker",
"category": "productivity",
"author": {
"name": "moshcoder",
"url": "https://moshcode.sh"
},
"homepage": "https://github.com/moshcoder/moshcode#ticker",
"keywords": ["stocks", "equity", "research", "markets", "advis0r"]
}
]
}
55 changes: 55 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ or miss one that does. A test fails the build when it drifts.
| `moshcode engines` | engines | list engines and installation status |
| `moshcode tools` | tools | list workflow tools and installation status |
| `moshcode trade` | tools | look up markets and trade through Alpaca |
| `moshcode ticker` <br>`advisor` | tools | equity research from advis0r.com |
| `moshcode plugin` <br>`plugins` | extend | install moshcode's slash commands into Claude Code |
| `moshcode commands` | script | list built-in moshscript commands |
| `moshcode completion` | extend | print a shell completion script |
| `moshcode run` | script | run a moshscript |
Expand Down Expand Up @@ -211,6 +213,31 @@ Alpaca's CLI has no confirmation prompts; `--submit` intentionally removes
MoshCode's preview guard. Live trading additionally requires Alpaca's `--live`
opt-in or corresponding environment setting.

### Equity research (`moshcode ticker`)

Where `trade` is Alpaca's order book, `ticker` is the research desk:
[advis0r.com](https://advis0r.com/api)'s public read-only API, rendered in the
pit. No key, no login, no write routes, no binary to install:

```sh
moshcode ticker NVDA # score, technicals, fundamentals, thesis, signals
moshcode ticker lookup rivian # company name → RIVN
moshcode ticker signals AAPL # what was said, quoted and sourced
moshcode ticker search "data center" # across every indexed transcript
moshcode ticker reports --limit 10 # the stored index, best score first
moshcode ticker discover fusion # a ranked watchlist (slow — analyzes each candidate)
moshcode ticker open NVDA # the shareable report page
```

Add `--json` to any of them for the raw response. The same facade is `/ticker …`
in the pit, and `MOSHCODE_ADVISOR_URL` points it at another instance.

Reports are **stored snapshots**, not live quotes: every response carries
`reportGeneratedAt` and every renderer prints it, alongside whether the price is
delayed and which feed produced it. Scores labelled `offline` come from
deterministic rules rather than a model. It is a research aid, not advice, and
nothing under `ticker` can place an order.

### Social posting from the pit

The pit can hand a prepared post to Bluesky or Nostr without storing either
Expand Down Expand Up @@ -305,6 +332,34 @@ from and five to rotate. Porkbun's API access is off by default and enabled
per-domain — and its documentation tools work with no keys at all, which is a
sensible way to try the server before trusting it with DNS writes.

## Claude Code plugins

MoshCode publishes its own plugin marketplace, so the pit's slash commands work
inside your engine too:

```sh
moshcode plugin list # what the marketplace ships, and who can take it
moshcode plugin install # add the marketplace + install `ticker`
moshcode plugin remove ticker # take it back off
```

`ticker@moshcode` adds `/ticker`, `/signals`, `/research`, `/lookup`,
`/reports`, and `/discover` — the same advis0r research surface described above,
driven from inside a coding session. Restart the engine afterwards; a newly
installed plugin is not live in a session that is already running.

The equivalent by hand:

```sh
claude plugin marketplace add moshcoder/moshcode
claude plugin install ticker@moshcode
```

Claude Code is currently the only engine with a plugin primitive. The others are
reported as skipped with a reason, the same way they are for skills, rather than
being left out of the summary. `MOSHCODE_PLUGIN_SOURCE=.` installs from a local
checkout instead of GitHub, which is how you try an unreleased plugin.

## Upgrade everything

```sh
Expand Down
16 changes: 15 additions & 1 deletion bin/moshcode.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ import { tradeArgs, tradeUsage } from "../src/trade.mjs";
import { runUpgrade } from "../src/upgrade.mjs";
import { selfUpdateCommand } from "../src/selfupdate.mjs";
import { describeUninstall, uninstallPlan } from "../src/uninstall.mjs";
import { mcpCommand, skillCommand } from "../src/integrations.mjs";
import { mcpCommand, pluginCommand, skillCommand } from "../src/integrations.mjs";
import { tickerCommand } from "../src/advisor.mjs";
import { canOpenBrowser, openBrowser } from "../src/open-url.mjs";
import { locate, tilde } from "../src/pwd.mjs";
import { createPrd, listPrds, authoringPrompt } from "../src/prd.mjs";
import { loginAuto, whoami, logout } from "../src/auth.mjs";
Expand Down Expand Up @@ -344,6 +346,18 @@ async function main() {
propagateExit(r.code, r.signal);
return;
}
if (cmd === "ticker" || cmd === "advisor") {
const code = await tickerCommand(rest, {
openUrl: (url) => canOpenBrowser() && openBrowser(url),
});
if (code) process.exitCode = code;
return;
}
if (cmd === "plugin" || cmd === "plugins") {
const code = await pluginCommand(rest);
if (code) process.exitCode = code;
return;
}
if (cmd === "console") {
const code = await consoleCommand(rest);
if (code) process.exitCode = code;
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
"src",
"examples",
"prd",
".claude-plugin",
"plugins",
"install.sh",
"README.md"
],
Expand Down
13 changes: 13 additions & 0 deletions plugins/ticker/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"$schema": "https://anthropic.com/claude-code/plugin.schema.json",
"name": "ticker",
"description": "Equity research slash commands backed by advis0r.com: scored reports, extracted signals, transcript search, company-name lookup, and ranked watchlists.",
"version": "0.1.0",
"author": {
"name": "moshcoder",
"url": "https://moshcode.sh"
},
"homepage": "https://github.com/moshcoder/moshcode#ticker",
"license": "MIT",
"keywords": ["stocks", "equity", "research", "markets", "advis0r"]
}
49 changes: 49 additions & 0 deletions plugins/ticker/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# ticker — equity research in your engine 🤘

Slash commands backed by [advis0r.com](https://advis0r.com/api): scored research
reports, extracted signals with sources, transcript search, company-name lookup,
and ranked watchlists.

| command | what it does |
| --- | --- |
| `/ticker NVDA` | score, technicals, fundamentals, thesis, signals, sources |
| `/signals AAPL` | what was actually said, quoted and sourced |
| `/research data center` | full-text search across every indexed transcript |
| `/lookup rivian` | company name → `RIVN` |
| `/reports` | every stored report, best score first |
| `/discover fusion` | a ranked watchlist for a topic (slow) |

## Install

```bash
moshcode plugin install
```

Or straight from Claude Code:

```bash
claude plugin marketplace add moshcoder/moshcode
claude plugin install ticker@moshcode
```

Restart the engine afterwards — a newly installed plugin is not live in a
session that is already running.

## How it works

Each command shells out to `moshcode ticker …`, which calls advis0r's public,
read-only API. No key, no login, no write routes. With `moshcode` absent, every
command falls back to `curl` against the same endpoints.

Point the commands at another instance with `MOSHCODE_ADVISOR_URL`.

## What this is not

A research aid, not advice. Reports are **stored snapshots** — every response
carries `reportGeneratedAt`, and every command is instructed to print it, because
a stale price presented as a live one is the one failure mode that actually costs
someone money. Scores marked `offline` come from deterministic rules, not a model.

Trading lives behind a different verb: `moshcode trade` wraps Alpaca, previews
orders by default, and requires an explicit `--submit`. Nothing in this plugin
can place an order.
37 changes: 37 additions & 0 deletions plugins/ticker/commands/discover.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
description: Build a ranked watchlist for a topic (slow — it analyzes each candidate).
argument-hint: "[topic]"
allowed-tools: Bash(moshcode ticker:*), Bash(curl -sS https://advis0r.com/api/:*)
---

## Task

Rank candidates for `$ARGUMENTS` (no topic → the default watchlist).

```bash
moshcode ticker discover $ARGUMENTS --limit 10 --json
```

Fallback: `curl -sS --max-time 180 "https://advis0r.com/api/discover?topic=<url-encoded>&provider=offline&horizon=2&limit=10"`

**This route runs an analysis per candidate and can take minutes.** Tell the
user it is working before you start, and do not retry on a timeout — re-running
it costs the same minutes again.

## Reading the response

`candidates` is ranked, each with `rank`, `ticker`, `companyName`, `lastPrice`,
`overallScore`, `confidence`, `classification`, `thesis`, `primaryCatalyst`,
`mainRisk`, `independentConfirmation`, plus liquidity fields
(`bidAskSpreadPercent`, `avgVolume`, `float`, `marketCap`).

## Rules

- Lead with `rank`, `ticker`, `overallScore`, and `classification`.
- **Print `mainRisk` next to every thesis.** A ranked list that shows only the
bull case is a pitch, not research.
- `provider: offline` means these scores are deterministic rules, not a model.
Say which provider produced the ranking.
- Flag illiquidity: a wide `bidAskSpreadPercent` or thin `avgVolume` matters
more than the score for anything small-cap.
- End with the response's own `disclaimer`.
27 changes: 27 additions & 0 deletions plugins/ticker/commands/lookup.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
description: Find a ticker symbol by company name (rivian → RIVN).
argument-hint: <company name>
allowed-tools: Bash(moshcode ticker:*), Bash(curl -sS https://advis0r.com/api/:*)
---

## Task

Resolve `$ARGUMENTS` to a ticker symbol.

```bash
moshcode ticker lookup $ARGUMENTS --limit 10 --json
```

Fallback: `curl -sS "https://advis0r.com/api/lookup?q=<url-encoded>&limit=10"`

## Reading the response

`matches` is a list of `{ symbol, name, exchange, hasReport }`.
`hasReport: true` means advis0r already has a stored research snapshot.

## Rules

- Show every match with its exchange — "Delta" is an airline and a faucet company.
- Mark which ones have a report, and offer `/ticker <SYMBOL>` for those.
- One unambiguous match: say the symbol and go straight to offering the report.
- No match: say the *directory* has no match, and do not invent a symbol.
30 changes: 30 additions & 0 deletions plugins/ticker/commands/reports.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
description: Every stored advis0r research report, best score first.
argument-hint: "[--limit n] [--sort recent|score|ticker]"
allowed-tools: Bash(moshcode ticker:*), Bash(curl -sS https://advis0r.com/api/:*)
---

## Task

List the stored reports.

```bash
moshcode ticker reports $ARGUMENTS --json
```

Fallback: `curl -sS "https://advis0r.com/api/reports?sort=score&limit=25"`

## Reading the response

`reports` is a list of `{ ticker, companyName, lastPrice, overallScore,
confidence, classification, aiProvider, aiModel, sourceCount, signalCount,
generatedAt }`, and `total` is how many exist.

## Rules

- Render as a table: ticker, score, classification, price, generated-at.
- **`generatedAt` per row, always.** These are snapshots taken at different
times; a table that hides that reads as one consistent as-of date.
- A row with no `aiProvider` was scored deterministically, not by a model.
- Offer `/ticker <SYMBOL>` for anything worth a closer look.
- This is a coverage list, not a recommendation list. Rank order is score order.
29 changes: 29 additions & 0 deletions plugins/ticker/commands/research.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
description: Full-text search across every indexed earnings transcript and article.
argument-hint: <words to search for>
allowed-tools: Bash(moshcode ticker:*), Bash(curl -sS https://advis0r.com/api/:*)
---

## Task

Search the transcript index for `$ARGUMENTS`.

```bash
moshcode ticker search $ARGUMENTS --limit 20 --json
```

Fallback: `curl -sS "https://advis0r.com/api/search?q=<url-encoded>&limit=20"`

## Reading the response

`results` is a list of segments: `text`, `speaker`, `ticker`, `event_date`.
The API tries full-text search first and falls back to a substring scan, so a
hit is a hit — but relevance is not ranked. Read before summarizing.

## Rules

- Cluster the hits by ticker and say which companies came up, with dates.
- Quote sparingly and attribute each quote to its speaker and ticker.
- If nothing matches, say the *index* has no match — this searches advis0r's
indexed corpus, not the whole web. Suggest `/lookup` if the query looks like
a company name.
30 changes: 30 additions & 0 deletions plugins/ticker/commands/signals.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
description: What was actually said about a ticker — extracted signals with quotes and sources.
argument-hint: <SYMBOL>
allowed-tools: Bash(moshcode ticker:*), Bash(curl -sS https://advis0r.com/api/:*)
---

## Task

List the extracted signals for `$ARGUMENTS`.

```bash
moshcode ticker signals $ARGUMENTS --json
```

Fallback: `curl -sS "https://advis0r.com/api/signals?ticker=$ARGUMENTS"`

## Reading the response

Each signal carries `signal_type`, `direction` (positive/negative/neutral),
`strength`, `specificity`, `quote`, `event_date`, `speaker`, `speaker_title`,
`source_url`, and `source_tier`.

## Rules

- Group by direction and lead with the most recent. Note the positive/negative split.
- **Every claim keeps its `source_url`.** These are extracted quotes from
transcripts and articles — a signal repeated without its source is a rumor.
- `strength` and `specificity` are the extractor's confidence, not the market's.
A strong signal from a low `source_tier` is still a low-tier source; say so.
- End with the response's own `disclaimer`.
Loading
Loading