@arincen/charts
v1.1.0
Published
The charting library an AI agent can read. Lighter, faster, smarter: about 26 KB, zero dependencies. Two builds from one codebase, and toText/annotate so a model can read the chart and draw its answer back.
Maintainers
Readme
Arincen Charts
The charting library an AI agent can read. Lighter, faster, smarter. A financial chart that draws itself on a canvas, with zero dependencies — and your users can ask it questions, because the agent becomes their eye and hand on it.

The eye and the hand
Every charting library draws for eyes. Anything else — a language model, a screen reader, an alerting job — has to reach into series internals and write the same summary again in every project.
// see
chart.toText(); // what is on screen, in words, deterministic and free of judgement
chart.toImage(); // the same thing as a PNG, for a vision model
chart.timeScale().getVisibleRange(); // the period being looked at
// act
chart.annotate([ // the answer, back on the chart
{ from, to, text }, // a region
{ time, price, text }, // a point
{ price, text }, // a level
]);
chart.timeScale().setVisibleRange({ from, to }); // look closer
chart.setCrosshairPosition(price, time, series); // point at thisNo API key, no bundled model, no provider you are tied to. What is missing everywhere else is the boring half — getting the numbers out in a form something can reason about, and getting an answer back onto the canvas.
A user who zooms to a spike and asks what happened there has already told you the period. getVisibleRange() is the question; annotate() is the answer.
The whole loop, with tool definitions ready to paste.
Getting started
npm install @arincen/chartsimport { createChart, AreaSeries } from '@arincen/charts';
const chart = createChart(document.getElementById('chart'), { autoSize: true });
const series = chart.addSeries(AreaSeries, { lineColor: '#2962ff', lineWidth: 2 });
series.setData([
{ time: '2026-01-01', value: 24.1 },
{ time: '2026-01-02', value: 24.8 },
]);
chart.timeScale().fitContent();Or from a script tag, with no build step:
<script src="https://unpkg.com/@arincen/charts/dist/arincen-charts.standalone.js"></script>
<script>
const chart = ArincenCharts.createChart(document.getElementById('chart'));
chart.addAreaSeries({}).setData(data);
</script>Two builds from one codebase
The unusual part. Most of what a charting library carries is structural — panes, non-linear price scales, custom series — and most pages never use any of it. Tree-shaking cannot remove it, because the core genuinely references it and a bundler cannot prove your page has one pane.
So the split is made at build time:
| | size | has |
|---|---|---|
| @arincen/charts | ~26 KB | line, area, candlestick, bar, histogram, baseline · crosshair · markers · price lines · primitives · pan/zoom |
| @arincen/charts/full | ~34 KB | all of that, plus panes, logarithmic / percentage / indexed price scales, left and overlay scales, custom series, watermarks, touch tracking, kinetic scroll |
import { createChart, AreaSeries } from '@arincen/charts';
// or, when you need panes or a second price scale:
import { createChart, AreaSeries } from '@arincen/charts/full';Nothing changes but the import. The light build simply does not contain the code for what it leaves out — panes is not a method that returns empty, it is absent.
Both figures are gzipped, and both are checked rather than claimed: a test gzips the shipped bundle and fails if it has grown past its budget, or if a number written anywhere in these pages is not the one it measured. There is nothing in dependencies to audit.
Drawing your own things
Two extension points, both of which take plain objects rather than requiring a subclass:
- Primitives decorate a chart that already knows how to draw itself — bands, alert lines, annotations.
series.attachPrimitive(primitive). - Custom series replace the drawing entirely — stacked areas, heatmaps, anything with its own shape.
chart.addCustomSeries(paneView), full build only.
Types
Ships .d.ts generated from the source, so a misspelled method is a compile error rather than a runtime surprise.
Time is an index, not a duration
Bars are placed by their position in the data, never by elapsed time. That is what collapses weekends, holidays and overnight gaps instead of drawing empty space where a market was shut. It is the right default for market data and the wrong one for a sensor log.
Attribution
MIT licensed, so this is a request rather than a condition — deliberately. If Arincen Charts renders something you ship, we would appreciate either keeping the attribution mark it shows by default, or crediting "Arincen Charts" near the chart. No particular wording, and no link attribute asked for. Tell us and we will list you among the products built with it.
Lightweight Charts™ is a trademark of TradingView, Inc. This project is not affiliated with or endorsed by TradingView. Its API is deliberately similar in places, which makes moving across easier; it is not a drop-in replacement and does not aim to be.
