Skip to content

Contributing

tradesdontlie edited this page Jul 21, 2026 · 1 revision

Contributing

This project grows by surface area. Every TradingView capability someone wires up becomes a new verb an AI agent can use — a new thing it can see or do on a live chart. If you've ever wished the agent could reach one more corner of TradingView, that wish is a contribution waiting to happen.

This page is the friendly, expanded version of the repo's CONTRIBUTING.md — start here to understand what to build and how, then that file is the canonical rulebook.


Ways to contribute

You don't have to write code to help. In rough order of "easiest to land":

  1. File a good bug report. A tool that silently misbehaves on your setup is genuinely useful signal. See Filing a bug report.
  2. Improve reliability. TradingView ships UI changes constantly; selectors rot, timeouts get flaky. Hardening an existing tool (better selectors, error handling, retry/wait logic) is high-value and low-risk.
  3. Improve the docs. This wiki, the CLAUDE.md decision trees, the README. If something confused you, fix it while it's fresh.
  4. Mirror a tool into the CLI. Anything the MCP layer can do, the tv command should be able to do too.
  5. Wire up a new TradingView endpoint → a brand-new tool. The frontier. See Wiring up a new endpoint.
  6. Add a new use of existing tools — a workflow, a batch action, a decision-tree entry that composes tools into something greater than the sum of its parts.

Scope — read this before you build

This is a local bridge: Claude ↔ your own running TradingView Desktop, over CDP. That boundary is the whole ethical and legal footing of the project, so contributions have to respect it.

In scope

  • Reliability, error handling, and better selectors for existing tools
  • New tools that read/drive the locally running Desktop app via CDP
  • CLI commands mirroring MCP capabilities
  • Pine Script workflow improvements
  • Tests and documentation

Out of scope ❌ — a PR that does any of these will be declined:

  • Talking to TradingView's servers directly. All access goes through the local Desktop app.
  • Bypassing auth or subscription gates. The tool assumes a valid, logged-in account.
  • Scraping, caching, or redistributing market data. No databases, no CSV dumps of prices.
  • Automated trading / live order execution. This is a chart-reading and development tool. (Replay trading is simulated and fine.)
  • Reverse-engineering or bundling TradingView's proprietary code.
  • Reaching other users' private data — scripts, watchlists, accounts.

Keep personal trading configs, strategies, and bots built on top of the bridge in your own fork. Unsure? Open an issue to discuss before writing code.


Filing a bug report

A report that lets a maintainer reproduce the problem gets fixed. A one-liner gets closed. Include:

  • OS and TradingView Desktop version — plus install type (installer vs Microsoft Store / MSIX — this matters a lot on Windows).
  • The exact tool call and its full JSON result ({ success: false, error: ... } and all).
  • tv_health_check output — proves the bridge is connected and shows the chart state.
  • What you expected vs what happened.

Search first. Popular bugs here have attracted 20+ duplicate fixes. If an open issue or PR already covers it, add your setup details there instead of opening a new one.


Development setup

npm install
npm run lint        # eslint — the no-undef guard catches unfinished refactors
npm run test:unit   # offline unit tests (no TradingView needed)
npm run test:e2e    # requires TradingView running with CDP on :9222
tv status           # verify CDP connection (TradingView must be running)

Core functions take an optional _deps parameter resolved via _resolve(_deps), so the logic is unit-testable without a live chart. Study src/core/replay.js or src/core/health.js for the pattern before writing your own.


Wiring up a new endpoint (the fun part)

TradingView's internal API surface is enormous, and this bridge only exposes a slice of it. Every session, tv_discover reports paths whose methods are reachable but not yet wrapped in a tool. Turning one of those into a tool is the most impactful thing you can contribute. Here's the loop.

1. Discover what's reachable

Call the discovery tool:

tv_discover

It enumerates the known API roots and lists their methods — e.g. the chart widget exposes ~50 methods at window.TradingViewApi._activeChartWidgetWV.value(). The known roots today:

Root Path
Active chart widget window.TradingViewApi._activeChartWidgetWV.value()
Chart widget collection window.TradingViewApi._chartWidgetCollection
WebSocket layer window.ChartApiInstance
Bottom toolbar window.TradingView.bottomWidgetBar
Bar replay window.TradingViewApi._replayApi
Alerts window.TradingViewApi._alertService

Scan the method list for something no existing tool covers — a getter you wish an agent could read, or an action you wish it could trigger.

2. Prototype live with ui_evaluate

Before writing any files, poke the method directly in the page context and see what it returns:

ui_evaluate  code: "return window.TradingViewApi._activeChartWidgetWV.value().someMethod();"

Iterate here until you understand the shape of the data and any quirks (promises that need unwrapping, values wrapped in .value(), arguments, edge cases). This is your REPL — it costs nothing and teaches you the API.

3. Wrap it in a core function

Put the logic in src/core/<area>.js. Keep the evaluated JS defensive — wrap internal access in try/catch and return a clean, compact object:

// src/core/myfeature.js
import { evaluate } from '../connection.js';

export async function getMyThing({ _deps } = {}) {
  const data = await evaluate(`
    (function() {
      try {
        var chart = window.TradingViewApi._activeChartWidgetWV.value();
        var thing = chart.someMethod();
        return { ok: true, value: thing };
      } catch (e) {
        return { ok: false, error: e.message };
      }
    })()
  `);
  if (!data.ok) throw new Error(data.error || 'someMethod() unavailable');
  return { success: true, value: data.value };
}

4. Register it as a tool

Add the tool in src/tools/<area>.js — thin handler, validation via zod, always return through jsonResult:

// src/tools/myfeature.js
import { z } from 'zod';
import { jsonResult } from './_format.js';
import * as core from '../core/myfeature.js';

export function registerMyFeatureTools(server) {
  server.tool(
    'myfeature_get_thing',
    'One clear sentence describing what this reads/does and when to use it',
    { detail: z.coerce.boolean().optional().describe('Return the verbose form (default false)') },
    async ({ detail }) => {
      try { return jsonResult(await core.getMyThing({ detail })); }
      catch (err) { return jsonResult({ success: false, error: err.message }, true); }
    }
  );
}

Then wire the registrar into src/server.js:

import { registerMyFeatureTools } from './tools/myfeature.js';
// ...
registerMyFeatureTools(server);

5. Finish the job

  • Test it — add a unit test using the _deps seam; verify live against a real chart and note what you ran.
  • Mind the context budget — default to compact output; gate anything large behind an opt-in flag (summary, study_filter, verbose). See Context Management.
  • Update the count and docs — the tool count appears in src/server.js (instructions header), the two CLAUDE.md files, README.md, and RESEARCH.md. Add your tool to the Tool Reference and, if it enables a new pattern, to Agent Workflows.
  • Name it well — the agent picks tools by name and description. area_verb_noun, present tense, specific. A vague name is a tool the agent never calls.

⚠️ These are undocumented internal APIs and can change without notice — a TradingView update can break any tool at any time. Fail gracefully ({ success: false, error }), never throw raw, and prefer feature-detection over assumptions.


Designing a good tool (checklist)

  • Single, clear purpose — one verb, one job. Compose in workflows, not in mega-tools.
  • Compact by default — the agent pays for every byte. Offer detail as opt-in.
  • Self-describing — the name + description alone should tell an agent when to reach for it.
  • { success: true/false, ... } — always, even on failure. Include an actionable error/hint.
  • Defensive against UI drift — try/catch around DOM and internal-API access.
  • Testable — logic in src/core, thin handler in src/tools, _deps seam for units.

Pull requests

  • One focused change per PR. Bundled PRs (feature + config + docs rewrite) tend to get closed in favor of the smallest equivalent.
  • Search open PRs before writing code — comment on an existing one rather than duplicating it.
  • Add tests for new functionality where possible.
  • npm run lint and npm run test:unit must pass.
  • Verify against a live TradingView Desktop and describe exactly what you ran and observed in the PR body. Real verification notes merge much faster.

Thanks for helping give agents more reach on a live chart. Open an issue to float an idea, or dive into Architecture Internals to see how the bridge is put together.

Clone this wiki locally