@kuandotdev/indicator 0.1.1 → 0.1.3

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 (80) hide show
  1. package/README.md +2 -7
  2. package/package.json +4 -1
  3. package/project/.cursor/rules/agent-docs.mdc +16 -0
  4. package/project/.cursor/rules/api-credential-storage.mdc +16 -0
  5. package/project/.cursor/rules/pinescript-v6.mdc +16 -0
  6. package/project/.cursor/rules/stock-model-forecast.mdc +16 -0
  7. package/project/.cursor/rules/system-prompt-injection.mdc +16 -0
  8. package/project/.cursor/rules/system-prompt-updater.mdc +16 -0
  9. package/project/.cursor/rules/tradingview-stock-data.mdc +16 -0
  10. package/project/.env.example +44 -0
  11. package/project/.npm-packaged-project +1 -0
  12. package/project/.pi/APPEND_SYSTEM.md +338 -0
  13. package/project/.pi/settings.json +8 -0
  14. package/project/AGENTS.md +538 -0
  15. package/project/CLAUDE.md +538 -0
  16. package/project/GEMINI.md +538 -0
  17. package/project/Makefile +488 -0
  18. package/project/README.md +419 -0
  19. package/project/conda-env-active.sh +98 -0
  20. package/project/conda-env-deactive.sh +42 -0
  21. package/project/docs/agent-install.md +446 -0
  22. package/project/docs/agent-skill-directory.md +222 -0
  23. package/project/docs/integration.html +271 -0
  24. package/project/packages/indicator/README.md +39 -0
  25. package/project/packages/indicator/package.json +40 -0
  26. package/project/packages/indicator/scripts/build-project-snapshot.js +57 -0
  27. package/project/packages/indicator/src/cli.js +368 -0
  28. package/project/packages/tradingview-stock-data-skill/README.md +112 -0
  29. package/project/packages/tradingview-stock-data-skill/extensions/stock-prompt-injector.ts +121 -0
  30. package/project/packages/tradingview-stock-data-skill/package.json +35 -0
  31. package/project/packages/tradingview-stock-data-skill/scripts/postinstall.sh +73 -0
  32. package/project/packages/tradingview-stock-data-skill/skills/tradingview-stock-data/SKILL.md +241 -0
  33. package/project/pyproject.toml +68 -0
  34. package/project/screenshots/.gitkeep +0 -0
  35. package/project/scripts/indicators/example_rsi_bands.pine +27 -0
  36. package/project/scripts/indicators/tsla_levels.pine +57 -0
  37. package/project/skills/agent-docs/SKILL.md +56 -0
  38. package/project/skills/api-credential-storage/SKILL.md +83 -0
  39. package/project/skills/api-credential-storage/scripts/upsert_env.py +151 -0
  40. package/project/skills/pinescript-v6/SKILL.md +129 -0
  41. package/project/skills/pinescript-v6/reference/built-ins.md +219 -0
  42. package/project/skills/pinescript-v6/reference/templates/alert-webhook.pine +76 -0
  43. package/project/skills/pinescript-v6/reference/templates/indicator.pine +48 -0
  44. package/project/skills/pinescript-v6/reference/templates/strategy.pine +50 -0
  45. package/project/skills/pinescript-v6/reference/v5-to-v6-migration.md +102 -0
  46. package/project/skills/pinescript-v6/reference/v6-language.md +202 -0
  47. package/project/skills/stock-model-forecast/SKILL.md +192 -0
  48. package/project/skills/system-prompt-injection/CUSTOM_SYSTEM_PROMPT.md +333 -0
  49. package/project/skills/system-prompt-injection/DEFAULT_SYSTEM_PROMPT.md +327 -0
  50. package/project/skills/system-prompt-injection/SKILL.md +90 -0
  51. package/project/skills/system-prompt-injection/SYSTEM_PROMPT.md +23 -0
  52. package/project/skills/system-prompt-updater/SKILL.md +82 -0
  53. package/project/skills/system-prompt-updater/scripts/system_prompt_update.sh +106 -0
  54. package/project/skills/tradingview-stock-data/SKILL.md +272 -0
  55. package/project/src/tv_indicator/__init__.py +0 -0
  56. package/project/src/tv_indicator/browser/__init__.py +0 -0
  57. package/project/src/tv_indicator/browser/automation.py +541 -0
  58. package/project/src/tv_indicator/browser/selectors.py +70 -0
  59. package/project/src/tv_indicator/cli/__init__.py +0 -0
  60. package/project/src/tv_indicator/cli/browser_cmds.py +92 -0
  61. package/project/src/tv_indicator/cli/data_cmds.py +178 -0
  62. package/project/src/tv_indicator/cli/main.py +56 -0
  63. package/project/src/tv_indicator/cli/model_cmds.py +255 -0
  64. package/project/src/tv_indicator/cli/pine_cmds.py +140 -0
  65. package/project/src/tv_indicator/config.py +98 -0
  66. package/project/src/tv_indicator/data/__init__.py +0 -0
  67. package/project/src/tv_indicator/data/client.py +187 -0
  68. package/project/src/tv_indicator/data/screener.py +268 -0
  69. package/project/src/tv_indicator/mcp/__init__.py +0 -0
  70. package/project/src/tv_indicator/mcp/agent_server.py +398 -0
  71. package/project/src/tv_indicator/mcp/browser_server.py +133 -0
  72. package/project/src/tv_indicator/mcp/data_server.py +239 -0
  73. package/project/src/tv_indicator/model/__init__.py +19 -0
  74. package/project/src/tv_indicator/model/forecast.py +693 -0
  75. package/project/tools/import_agent_tools.sh +503 -0
  76. package/project/tools/install_skills.sh +673 -0
  77. package/project/tools/interactive_install.sh +917 -0
  78. package/project/tools/progress.sh +114 -0
  79. package/project/tools/uninstall_agent_tools.sh +373 -0
  80. package/src/cli.js +22 -25
@@ -0,0 +1,488 @@
1
+ # =============================================================================
2
+ # tv-indicator Makefile
3
+ # Indicator: PineScript authoring + data + browser.
4
+ # =============================================================================
5
+
6
+ .PHONY: help \
7
+ install install-deps install-playwright install-tvdatafeed uninstall reinstall \
8
+ agent-import agent-uninstall uninstall-all env-active env-deactive status version doctor \
9
+ ohlcv search rating screener model-status model-setup model-forecast \
10
+ login session-check push screenshot \
11
+ pine-new pine-list pine-validate pine-show \
12
+ mcp-data mcp-browser mcp-agent mcp-config-claude mcp-config-pi \
13
+ lint fmt test \
14
+ tree clean clean-screenshots clean-sessions clean-all
15
+
16
+ .DEFAULT_GOAL := help
17
+
18
+ # =============================================================================
19
+ # Configuration
20
+ # =============================================================================
21
+ CONDA_ENV ?= tv-indicator
22
+ PYTHON_VERSION ?= 3.11
23
+ PLATFORM ?= auto
24
+ FORCE_INSTALL ?= 0
25
+ SCRIPTS_DIR := scripts
26
+ SCREENSHOTS_DIR := screenshots
27
+
28
+ # Run a command inside the conda env without requiring the user to activate.
29
+ # `--live-stream` + `--no-capture-output` keeps stdout/stderr flowing in real time.
30
+ RUN := conda run -n $(CONDA_ENV) --live-stream --no-capture-output
31
+ TV_CLI := python -m tv_indicator.cli.main
32
+
33
+ # Platform detection (parity with skin_type_regonize_model)
34
+ IS_MAC := $(shell [ "$$(uname -s)" = "Darwin" ] && echo 1 || echo 0)
35
+
36
+ # =============================================================================
37
+ # Help
38
+ # =============================================================================
39
+ help:
40
+ @echo "Indicator — PineScript authoring + data + browser automation"
41
+ @echo ""
42
+ @echo "GETTING STARTED"
43
+ @echo " make install The one command. Idempotent. Run this every time."
44
+ @echo " Handles fresh install, upgrades, and re-runs of the wizard."
45
+ @echo " make uninstall-all Full uninstall — removes everything cleanly"
46
+ @echo " make status Show TradingView config + auth status"
47
+ @echo " make doctor Diagnose env / deps / cookies / skills"
48
+ @echo ""
49
+ @echo "ENVIRONMENT (power-user)"
50
+ @echo " make install FORCE_INSTALL=1 Re-run core install even if binaries are already in place"
51
+ @echo " make install-deps (re)install Python deps only"
52
+ @echo " make install-playwright Download Chromium for Playwright"
53
+ @echo " make install-tvdatafeed Re-pin tvdatafeed from GitHub"
54
+ @echo " make reinstall uninstall + install"
55
+ @echo " make uninstall Remove conda env '$(CONDA_ENV)' only"
56
+ @echo " make agent-import [PLATFORM=auto] Re-import a specific agent's MCP/skills"
57
+ @echo " make agent-uninstall [PLATFORM=auto|all|...] Remove TradingView MCP from selected agent(s)"
58
+ @echo " make env-active Print: 'source conda-env-active.sh $(CONDA_ENV)'"
59
+ @echo " make env-deactive Print: 'source conda-env-deactive.sh $(CONDA_ENV)'"
60
+ @echo ""
61
+ @echo "AGENT SKILLS (multi-agent skill wiring)"
62
+ @echo " make install-skills Wire skill into all agents (.claude, .pi, .cursor, AGENTS.md, GEMINI.md)"
63
+ @echo " make install-skills-global Also symlink into ~/.claude/skills/ (user-global)"
64
+ @echo " make update-skills Refresh autogen files (run after editing canonical skill)"
65
+ @echo " make check-skills Report which discovery points are wired up"
66
+ @echo " make uninstall-skills Remove managed symlinks + autogen files"
67
+ @echo ""
68
+ @echo "DATA (read TradingView)"
69
+ @echo " make ohlcv SYMBOL=NASDAQ:AAPL [INTERVAL=1D] [BARS=500]"
70
+ @echo " make search Q=tesla [LIMIT=20]"
71
+ @echo " make rating SYMBOL=NASDAQ:AAPL"
72
+ @echo " make screener [MARKET=america] [FILTER='RSI < 30'] [LIMIT=50]"
73
+ @echo ""
74
+ @echo "MODEL FORECAST (server-side API; stock/ETF/index only)"
75
+ @echo " make model-status Show forecast API configuration/status"
76
+ @echo " make model-setup Validate forecast API configuration"
77
+ @echo " make model-forecast SYMBOL=NASDAQ:TSLA Fetch 20d forecast from API"
78
+ @echo " make model-forecast SYMBOL=TSLA REFRESH=1 Ask API to refresh/recompute first"
79
+ @echo ""
80
+ @echo "BROWSER (write to TradingView)"
81
+ @echo " make login Interactive login (visible browser)"
82
+ @echo " make session-check Verify cookie / profile still valid"
83
+ @echo " make push SCRIPT=scripts/indicators/foo.pine [APPLY=NASDAQ:AAPL] [SHOT=1]"
84
+ @echo " make screenshot [SYMBOL=NASDAQ:AAPL] [OUT=path.png]"
85
+ @echo ""
86
+ @echo "PINE SCRIPT (local authoring)"
87
+ @echo " make pine-new KIND=indicator|strategy|webhook NAME=my_rsi"
88
+ @echo " make pine-list List all .pine files"
89
+ @echo " make pine-validate SCRIPT=scripts/indicators/foo.pine"
90
+ @echo " make pine-show SCRIPT=scripts/indicators/foo.pine"
91
+ @echo ""
92
+ @echo "MCP SERVERS (agents)"
93
+ @echo " make mcp-data Run the TradingView data MCP server in the foreground"
94
+ @echo " make mcp-browser Run the TradingView browser MCP server in the foreground"
95
+ @echo " make mcp-agent Run the TradingView agent MCP server in the foreground"
96
+ @echo " make mcp-config-claude Print JSON snippet for Claude Desktop"
97
+ @echo " make mcp-config-pi Print TOML snippet for pi"
98
+ @echo ""
99
+ @echo "QUALITY"
100
+ @echo " make lint ruff check src/"
101
+ @echo " make fmt ruff format src/"
102
+ @echo " make test pytest"
103
+ @echo ""
104
+ @echo "HOUSEKEEPING"
105
+ @echo " make tree Show project tree"
106
+ @echo " make clean Remove __pycache__ / *.pyc"
107
+ @echo " make clean-screenshots Remove generated PNGs"
108
+ @echo " make clean-sessions Remove saved browser profiles (forces re-login)"
109
+ @echo " make clean-all All of the above"
110
+
111
+ # =============================================================================
112
+ # Environment setup
113
+ # =============================================================================
114
+ install:
115
+ @echo "[1/4] Checking core install for conda env '$(CONDA_ENV)' (python=$(PYTHON_VERSION))..."
116
+ @bash -c '\
117
+ set -eo pipefail; \
118
+ if [[ "$(FORCE_INSTALL)" != "1" ]] \
119
+ && command -v conda >/dev/null 2>&1 \
120
+ && conda env list | sed "s/[[:space:]].*//" | grep -qx "$(CONDA_ENV)" \
121
+ && conda run -n "$(CONDA_ENV)" python -c "import tv_indicator,mcp,playwright,tradingview_screener; import tv_indicator.mcp.data_server,tv_indicator.mcp.browser_server,tv_indicator.mcp.agent_server" >/dev/null 2>&1 \
122
+ && conda run -n "$(CONDA_ENV)" python -m tv_indicator.cli.main --help >/dev/null 2>&1; then \
123
+ echo " core already installed ✓ (use FORCE_INSTALL=1 to reinstall)"; \
124
+ else \
125
+ export TV_PYTHON_VERSION=$(PYTHON_VERSION); \
126
+ source ./conda-env-active.sh $(CONDA_ENV); \
127
+ fi \
128
+ '
129
+ @echo ""
130
+ @echo "[2/4] Verifying TradingView CLI + model API client..."
131
+ -@./tools/progress.sh --success "TradingView CLI available ✓" --failure "TradingView CLI NOT available ✗" "Checking TradingView CLI" -- $(RUN) $(TV_CLI) --help
132
+ -@./tools/progress.sh --success "Model API client available ✓" --failure "Model API client NOT available ✗" "Checking model API client" -- $(RUN) $(TV_CLI) model --help
133
+ @mkdir -p temp && echo " Analysis artifact dir ready ✓ (temp/)"
134
+ @echo ""
135
+ @echo "[3/4] Interactive TradingView + agent/MCP setup..."
136
+ @echo " Progress indicators show background work; prompts may wait for your input."
137
+ @CONDA_ENV="$(CONDA_ENV)" PLATFORM="$(PLATFORM)" ./tools/interactive_install.sh
138
+ @echo ""
139
+ @echo "[4/4] Done. Useful checks:"
140
+ @echo " make status"
141
+ @echo " make session-check"
142
+ @echo " make model-status"
143
+ @echo " make model-setup # verify model API env"
144
+ @echo " make model-forecast SYMBOL=NASDAQ:TSLA MODEL_JSON=1"
145
+ @echo " make doctor"
146
+ @echo " make check-skills"
147
+ @echo ""
148
+ @echo "Final TradingView login status:"
149
+ -@$(RUN) $(TV_CLI) browser session-check 2>/dev/null || echo " TradingView login status check failed — retry with 'make session-check'"
150
+ @echo ""
151
+ @echo "Final model forecast API status:"
152
+ -@$(RUN) $(TV_CLI) model status || echo " Model status check failed — retry with 'make model-status'"
153
+
154
+ install-deps:
155
+ $(RUN) python -m pip install --upgrade pip
156
+ $(RUN) python -m pip install -e ".[data,dev]"
157
+
158
+ install-playwright:
159
+ $(RUN) python -m playwright install chromium
160
+
161
+ install-tvdatafeed:
162
+ $(RUN) python -m pip install --upgrade --force-reinstall \
163
+ git+https://github.com/rongardF/tvdatafeed.git
164
+
165
+ uninstall:
166
+ @bash -c 'source ./conda-env-deactive.sh $(CONDA_ENV)'
167
+
168
+ reinstall:
169
+ $(MAKE) uninstall
170
+ $(MAKE) install
171
+
172
+ env-active:
173
+ @echo "Run this in your shell (don't run it through make):"
174
+ @echo ""
175
+ @echo " source conda-env-active.sh $(CONDA_ENV)"
176
+ @echo ""
177
+
178
+ env-deactive:
179
+ @echo "Run this in your shell (don't run it through make):"
180
+ @echo ""
181
+ @echo " source conda-env-deactive.sh $(CONDA_ENV)"
182
+ @echo ""
183
+
184
+ status:
185
+ $(RUN) $(TV_CLI) status
186
+
187
+ version:
188
+ $(RUN) $(TV_CLI) version
189
+
190
+ agent-import:
191
+ @./tools/import_agent_tools.sh --platform "$(PLATFORM)"
192
+
193
+ agent-uninstall:
194
+ @./tools/uninstall_agent_tools.sh --platform "$(PLATFORM)"
195
+
196
+ doctor:
197
+ @echo "─── Agent skills ───────────────────────────────────────"
198
+ @./tools/install_skills.sh --check 2>&1 | tail -n +4 || echo " (run 'make install-skills' to wire up agent discovery)"
199
+ @echo ""
200
+ @echo "─── Conda ──────────────────────────────────────────────"
201
+ @command -v conda >/dev/null && echo " conda ✓ ($$(conda --version))" || echo " conda ✗ — install miniforge"
202
+ @conda env list | awk '{print $$1}' | grep -qx "$(CONDA_ENV)" \
203
+ && echo " env '$(CONDA_ENV)' ✓" \
204
+ || echo " env '$(CONDA_ENV)' ✗ — run 'make install'"
205
+ @echo ""
206
+ @echo "─── Package ────────────────────────────────────────────"
207
+ -@$(RUN) python -c "import tv_indicator; print(' tv_indicator ✓', tv_indicator.__file__ if hasattr(tv_indicator,'__file__') else '')" 2>/dev/null || echo " tv_indicator ✗ — run 'make install-deps'"
208
+ -@$(RUN) python -c "import importlib.util,sys; sys.exit(0 if importlib.util.find_spec('tvDatafeed') or importlib.util.find_spec('tvdatafeed') else 1)" 2>/dev/null && echo " tvdatafeed ✓" || echo " tvdatafeed ✗ — run 'make install-tvdatafeed'"
209
+ -@$(RUN) python -c "import playwright" 2>/dev/null && echo " playwright ✓" || echo " playwright ✗ — run 'make install-deps'"
210
+ -@$(RUN) python -c "import tradingview_screener" 2>/dev/null && echo " screener ✓" || echo " screener ✗"
211
+ -@$(RUN) python -c "import mcp" 2>/dev/null && echo " mcp ✓" || echo " mcp ✗"
212
+ @echo ""
213
+ @echo "─── Model forecast API ─────────────────────────────────"
214
+ -@$(RUN) $(TV_CLI) model status 2>/dev/null || echo " model API ✗ — set TV_MODEL_API_URL"
215
+ @echo ""
216
+ @echo "─── Config ─────────────────────────────────────────────"
217
+ @[ -f .env ] && echo " .env file ✓" || echo " .env file ✗ — run 'cp .env.example .env'"
218
+ -@$(RUN) $(TV_CLI) status 2>/dev/null || true
219
+
220
+ # =============================================================================
221
+ # Agent skill installation
222
+ # =============================================================================
223
+ install-skills:
224
+ @./tools/install_skills.sh
225
+
226
+ update-skills: install-skills
227
+
228
+ install-skills-global:
229
+ @TV_INSTALL_GLOBAL_CLAUDE=1 ./tools/install_skills.sh
230
+
231
+ check-skills:
232
+ @./tools/install_skills.sh --check
233
+
234
+ uninstall-skills:
235
+ @./tools/install_skills.sh --uninstall
236
+
237
+ # =============================================================================
238
+ # Data (read)
239
+ # =============================================================================
240
+ SYMBOL ?= NASDAQ:AAPL
241
+ INTERVAL ?= 1D
242
+ BARS ?= 500
243
+ Q ?=
244
+ LIMIT ?= 20
245
+ MARKET ?= america
246
+ FILTER ?=
247
+ MODEL_REPO ?=
248
+ MODEL_CSV ?=
249
+ MODEL_CONDA_ENV ?=
250
+ MODEL_PERIOD ?= 10y
251
+ MODEL_API_URL ?=
252
+ MODEL_STATUS_URL ?=
253
+ REFRESH ?= 0
254
+ MODEL_JSON ?= 0
255
+
256
+ ohlcv:
257
+ @[ -n "$(SYMBOL)" ] || (echo "ERROR: SYMBOL is required, e.g. make ohlcv SYMBOL=NASDAQ:AAPL"; exit 1)
258
+ $(RUN) $(TV_CLI) data ohlcv "$(SYMBOL)" --interval $(INTERVAL) --bars $(BARS)
259
+
260
+ search:
261
+ @[ -n "$(Q)" ] || (echo "ERROR: Q is required, e.g. make search Q=tesla"; exit 1)
262
+ $(RUN) $(TV_CLI) data search "$(Q)" --limit $(LIMIT)
263
+
264
+ rating:
265
+ @[ -n "$(SYMBOL)" ] || (echo "ERROR: SYMBOL is required"; exit 1)
266
+ $(RUN) $(TV_CLI) data rating "$(SYMBOL)" --interval $(INTERVAL)
267
+
268
+ screener:
269
+ $(RUN) $(TV_CLI) data screener --market $(MARKET) --limit $(LIMIT) \
270
+ $(if $(FILTER),--filter "$(FILTER)",)
271
+
272
+ model-status:
273
+ $(RUN) $(TV_CLI) model status \
274
+ $(if $(MODEL_REPO),--repo "$(MODEL_REPO)",) \
275
+ $(if $(MODEL_CSV),--csv "$(MODEL_CSV)",) \
276
+ $(if $(MODEL_CONDA_ENV),--conda-env "$(MODEL_CONDA_ENV)",) \
277
+ $(if $(MODEL_API_URL),--api-url "$(MODEL_API_URL)",) \
278
+ $(if $(MODEL_STATUS_URL),--status-url "$(MODEL_STATUS_URL)",) \
279
+ $(if $(filter 1 true yes,$(MODEL_JSON)),--json,)
280
+
281
+ model-setup:
282
+ $(RUN) $(TV_CLI) model setup \
283
+ $(if $(MODEL_REPO),--repo "$(MODEL_REPO)",) \
284
+ $(if $(MODEL_CONDA_ENV),--conda-env "$(MODEL_CONDA_ENV)",) \
285
+ $(if $(MODEL_API_URL),--api-url "$(MODEL_API_URL)",) \
286
+ $(if $(MODEL_STATUS_URL),--status-url "$(MODEL_STATUS_URL)",) \
287
+ $(if $(filter 1 true yes,$(MODEL_JSON)),--json,)
288
+
289
+ model-forecast:
290
+ @[ -n "$(SYMBOL)" ] || (echo "ERROR: SYMBOL is required, e.g. make model-forecast SYMBOL=NASDAQ:TSLA"; exit 1)
291
+ $(RUN) $(TV_CLI) model forecast "$(SYMBOL)" \
292
+ $(if $(filter 1 true yes,$(REFRESH)),--refresh,) \
293
+ $(if $(MODEL_REPO),--repo "$(MODEL_REPO)",) \
294
+ $(if $(MODEL_CSV),--csv "$(MODEL_CSV)",) \
295
+ $(if $(MODEL_CONDA_ENV),--conda-env "$(MODEL_CONDA_ENV)",) \
296
+ $(if $(MODEL_API_URL),--api-url "$(MODEL_API_URL)",) \
297
+ --period "$(MODEL_PERIOD)" \
298
+ $(if $(filter 1 true yes,$(MODEL_JSON)),--json,)
299
+
300
+ # =============================================================================
301
+ # Browser (write)
302
+ # =============================================================================
303
+ SCRIPT ?=
304
+ SHOT ?= 0
305
+ OUT ?=
306
+ LAYOUT ?=
307
+ APPLY ?=
308
+
309
+ login:
310
+ $(RUN) $(TV_CLI) browser login
311
+
312
+ session-check:
313
+ $(RUN) $(TV_CLI) browser session-check
314
+
315
+ push:
316
+ @[ -n "$(SCRIPT)" ] || (echo "ERROR: SCRIPT is required, e.g. make push SCRIPT=scripts/indicators/foo.pine APPLY=NASDAQ:AAPL"; exit 1)
317
+ $(RUN) $(TV_CLI) browser push "$(SCRIPT)" \
318
+ $(if $(APPLY),--apply "$(APPLY)",) \
319
+ $(if $(filter 1 true yes,$(SHOT)),--screenshot,)
320
+
321
+ screenshot:
322
+ $(RUN) $(TV_CLI) browser screenshot \
323
+ $(if $(SYMBOL),--symbol "$(SYMBOL)",) \
324
+ $(if $(LAYOUT),--layout "$(LAYOUT)",) \
325
+ $(if $(OUT),--out "$(OUT)",)
326
+
327
+ # =============================================================================
328
+ # Pine (local)
329
+ # =============================================================================
330
+ KIND ?= indicator
331
+ NAME ?=
332
+
333
+ pine-new:
334
+ @[ -n "$(NAME)" ] || (echo "ERROR: NAME is required, e.g. make pine-new KIND=indicator NAME=my_rsi"; exit 1)
335
+ $(RUN) $(TV_CLI) pine new $(KIND) $(NAME)
336
+
337
+ pine-list:
338
+ $(RUN) $(TV_CLI) pine list
339
+
340
+ pine-validate:
341
+ @[ -n "$(SCRIPT)" ] || (echo "ERROR: SCRIPT is required"; exit 1)
342
+ $(RUN) $(TV_CLI) pine validate "$(SCRIPT)"
343
+
344
+ pine-show:
345
+ @[ -n "$(SCRIPT)" ] || (echo "ERROR: SCRIPT is required"; exit 1)
346
+ $(RUN) $(TV_CLI) pine show "$(SCRIPT)"
347
+
348
+ # =============================================================================
349
+ # MCP servers
350
+ # =============================================================================
351
+ mcp-data:
352
+ @echo "Starting TradingView data MCP server on stdio. Ctrl-C to stop."
353
+ $(RUN) python -m tv_indicator.mcp.data_server
354
+
355
+ mcp-browser:
356
+ @echo "Starting TradingView browser MCP server on stdio. Ctrl-C to stop."
357
+ $(RUN) python -m tv_indicator.mcp.browser_server
358
+
359
+ mcp-agent:
360
+ @echo "Starting TradingView agent MCP server on stdio. Ctrl-C to stop."
361
+ $(RUN) python -m tv_indicator.mcp.agent_server
362
+
363
+ mcp-config-claude:
364
+ @echo "Paste this into ~/Library/Application Support/Claude/claude_desktop_config.json:"
365
+ @echo ""
366
+ @echo '{'
367
+ @echo ' "mcpServers": {'
368
+ @echo ' "training-view-data": {'
369
+ @echo " \"command\": \"$$(conda run -n $(CONDA_ENV) which training-view-mcp-data 2>/dev/null || echo 'training-view-mcp-data')\","
370
+ @echo ' "env": { "TV_SESSIONID": "<paste-here>", "TV_MODEL_API_URL": "<model-api-url>" }'
371
+ @echo ' },'
372
+ @echo ' "training-view-browser": {'
373
+ @echo " \"command\": \"$$(conda run -n $(CONDA_ENV) which training-view-mcp-browser 2>/dev/null || echo 'training-view-mcp-browser')\","
374
+ @echo ' "env": { "TV_SESSIONID": "<paste-here>", "TV_BROWSER_HEADLESS": "true" }'
375
+ @echo ' },'
376
+ @echo ' "training-view-agent": {'
377
+ @echo " \"command\": \"$$(conda run -n $(CONDA_ENV) which training-view-mcp-agent 2>/dev/null || echo 'training-view-mcp-agent')\""
378
+ @echo ' }'
379
+ @echo ' }'
380
+ @echo '}'
381
+
382
+ mcp-config-pi:
383
+ @echo "Paste this into .pi/config.toml (or your global pi config):"
384
+ @echo ""
385
+ @echo '[mcp_servers.training-view-data]'
386
+ @echo "command = \"$$(conda run -n $(CONDA_ENV) which training-view-mcp-data 2>/dev/null || echo 'training-view-mcp-data')\""
387
+ @echo 'env = { TV_SESSIONID = "<paste-here>", TV_MODEL_API_URL = "<model-api-url>" }'
388
+ @echo ''
389
+ @echo '[mcp_servers.training-view-browser]'
390
+ @echo "command = \"$$(conda run -n $(CONDA_ENV) which training-view-mcp-browser 2>/dev/null || echo 'training-view-mcp-browser')\""
391
+ @echo 'env = { TV_SESSIONID = "<paste-here>", TV_BROWSER_HEADLESS = "true" }'
392
+ @echo ''
393
+ @echo '[mcp_servers.training-view-agent]'
394
+ @echo "command = \"$$(conda run -n $(CONDA_ENV) which training-view-mcp-agent 2>/dev/null || echo 'training-view-mcp-agent')\""
395
+
396
+ # =============================================================================
397
+ # Quality
398
+ # =============================================================================
399
+ lint:
400
+ $(RUN) ruff check src/
401
+
402
+ fmt:
403
+ $(RUN) ruff format src/
404
+
405
+ test:
406
+ $(RUN) pytest -q
407
+
408
+ # =============================================================================
409
+ # Housekeeping
410
+ # =============================================================================
411
+ tree:
412
+ @command -v tree >/dev/null && tree -I '__pycache__|*.egg-info|.venv|venv|sessions|.git' -L 4 . \
413
+ || find . -type f -not -path '*/\.*' -not -path '*/__pycache__/*' -not -path '*/sessions/*' | sort | head -60
414
+
415
+ clean:
416
+ @find . -type d -name __pycache__ -prune -exec rm -rf {} + 2>/dev/null || true
417
+ @find . -type f -name '*.pyc' -delete 2>/dev/null || true
418
+ @find . -type d -name '*.egg-info' -prune -exec rm -rf {} + 2>/dev/null || true
419
+ @echo "Cleaned pyc / egg-info."
420
+
421
+ clean-screenshots:
422
+ @find $(SCREENSHOTS_DIR) -type f ! -name '.gitkeep' -delete 2>/dev/null || true
423
+ @echo "Cleaned $(SCREENSHOTS_DIR)/"
424
+
425
+ clean-sessions:
426
+ @rm -rf tools/tv_browser/sessions/* 2>/dev/null || true
427
+ @echo "Cleaned browser profiles (you'll need to log in again)."
428
+
429
+ clean-all: clean clean-screenshots clean-sessions
430
+ @echo "All clean."
431
+
432
+ # =============================================================================
433
+ # Full uninstall — removes Indicator from every agent + the conda env +
434
+ # generated/runtime artifacts. Repo source files stay; re-run 'make install'
435
+ # anytime to reinstall.
436
+ #
437
+ # Optional flag: KEEP_ENV=1 — preserve .env (otherwise it's deleted, since it
438
+ # may contain TradingView cookies / API keys you no longer want lying around).
439
+ # =============================================================================
440
+ KEEP_ENV ?= 0
441
+
442
+ uninstall-all:
443
+ @echo "[1/6] Removing per-agent MCP registrations (Pi, Claude Desktop, Claude Code, Codex, Gemini, Cursor)..."
444
+ @./tools/uninstall_agent_tools.sh --platform all || true
445
+ @echo ""
446
+ @echo "[2/6] Removing managed skill symlinks and generated context files (CLAUDE.md, AGENTS.md, GEMINI.md, .pi/APPEND_SYSTEM.md, .cursor/rules/*.mdc, docs/agent-skill-directory.md)..."
447
+ @./tools/install_skills.sh --uninstall || true
448
+ @echo ""
449
+ @echo "[3/6] Removing project-local agent artifacts (.mcp.json, .cursor/mcp.json, .pi/{config.toml,settings.json,.tv-indicator-auto-imported})..."
450
+ @rm -f .mcp.json .cursor/mcp.json 2>/dev/null || true
451
+ @rm -f .pi/.tv-indicator-auto-imported 2>/dev/null || true
452
+ @if [ -d .pi ]; then \
453
+ [ -f .pi/config.toml ] && [ ! -s .pi/config.toml ] && rm -f .pi/config.toml || true; \
454
+ [ -f .pi/settings.json ] && [ "$$(wc -c < .pi/settings.json | tr -d ' ')" -lt 5 ] && rm -f .pi/settings.json || true; \
455
+ rmdir .pi/skills 2>/dev/null || true; \
456
+ rmdir .pi/agent/skills 2>/dev/null || true; \
457
+ rmdir .pi/agent 2>/dev/null || true; \
458
+ rmdir .pi 2>/dev/null || true; \
459
+ fi
460
+ @if [ -d .cursor ]; then \
461
+ rmdir .cursor/rules 2>/dev/null || true; \
462
+ rmdir .cursor 2>/dev/null || true; \
463
+ fi
464
+ @if [ -d .claude/skills ]; then \
465
+ rmdir .claude/skills 2>/dev/null || true; \
466
+ rmdir .claude 2>/dev/null || true; \
467
+ fi
468
+ @echo ""
469
+ @echo "[4/6] Removing browser session profile + screenshots..."
470
+ @$(MAKE) -s clean-sessions || true
471
+ @$(MAKE) -s clean-screenshots || true
472
+ @echo ""
473
+ @echo "[5/6] Removing stray *.bak files left from earlier sed passes..."
474
+ @find . -type f -name '*.bak' -not -path '*/.git/*' -delete 2>/dev/null || true
475
+ @echo ""
476
+ @echo "[6/6] Removing conda env '$(CONDA_ENV)'..."
477
+ @conda env list | awk '{print $$1}' | grep -qx "$(CONDA_ENV)" \
478
+ && conda env remove -y -n $(CONDA_ENV) \
479
+ || echo " conda env '$(CONDA_ENV)' not present, skipping"
480
+ @echo ""
481
+ @if [ "$(KEEP_ENV)" = "1" ]; then \
482
+ echo " Kept .env (KEEP_ENV=1)"; \
483
+ elif [ -f .env ]; then \
484
+ rm -f .env && echo " Removed .env (pass KEEP_ENV=1 to preserve cookies/keys)"; \
485
+ fi
486
+ @echo ""
487
+ @echo "Done. Repo source files remain — run 'make install' to reinstall."
488
+ @echo "If you want a fully clean slate, you can now also: rm -rf $(CURDIR)"