Public Docs

AI Tools

This is the public quick-start for AI Tools. Save your key locally, run the downloader, and paste the starter instructions into your LLM.

All Docs

Installation Guide

Save your API key once in a standard local config file, then let your own script or agent fetch the latest snapshot manifest from /api/llm/v1/snapshots/latest.

Step 1 - Save Key Locally

macOS/Linux - ~/.config/marketscanner/llm-bundle.env

CONFIG_FILE="${XDG_CONFIG_HOME:-$HOME/.config}/marketscanner/llm-bundle.env"
mkdir -p "$(dirname "$CONFIG_FILE")"
umask 077
cat > "$CONFIG_FILE" <<'EOF'
MARKETSCANNER_API_KEY=PASTE_API_KEY_HERE
EOF
echo "Saved key to $CONFIG_FILE"

Windows - $env:APPDATA\MarketScanner\llm-bundle.env

$configFile = Join-Path $env:APPDATA 'MarketScanner\llm-bundle.env'
New-Item -ItemType Directory -Force -Path (Split-Path -Parent $configFile) | Out-Null
@"
MARKETSCANNER_API_KEY=PASTE_API_KEY_HERE
"@ | Set-Content $configFile
Write-Host "Saved key to $configFile"

Step 2 - LLM Directions

Copy and paste this into your LLM

Follow these directions:

https://gist.github.com/tlk3/31e0b091f0d2d8c1790a6067edca5fd3

My API key is already stored in the correct default location.

If I say /msr refresh, download the latest MarketScanner bundle and then reload it from disk before answering.

After refresh, work from the local bundle files unless I explicitly ask for another API call.

Do not print or expose my API key.

Step 3 - Optional Downloader Install

Optional for users who want a saved local downloader script instead of relying on /msr refresh.

macOS/Linux - download.sh

#!/usr/bin/env bash
set -euo pipefail
CONFIG_FILE="${MARKETSCANNER_CONFIG_FILE:-${XDG_CONFIG_HOME:-$HOME/.config}/marketscanner/llm-bundle.env}"
if [ -f "$CONFIG_FILE" ]; then
  set -a
  . "$CONFIG_FILE"
  set +a
fi
: "${MARKETSCANNER_API_KEY:?Set MARKETSCANNER_API_KEY or create $CONFIG_FILE first}"
BASE_URL="${MARKETSCANNER_BASE_URL:-https://app.stratalerts.com}"
OUTPUT_DIR="${1:-$HOME/marketscanner-data/latest}"
mkdir -p "$OUTPUT_DIR"
MANIFEST_URL="$BASE_URL/api/llm/v1/snapshots/latest"
curl --fail --silent --show-error \
  -H "Authorization: Bearer $MARKETSCANNER_API_KEY" \
  "$MANIFEST_URL" -o "$OUTPUT_DIR/manifest.json"

extract_chunk_refs() {
  grep -o '\{[^}]*\}' "$OUTPUT_DIR/manifest.json" | while IFS= read -r obj; do
    ref="$(printf '%s\n' "$obj" | sed -n 's/.*"relative_path"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p')"
    if [ -z "$ref" ]; then
      ref="$(printf '%s\n' "$obj" | sed -n 's/.*"path"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p')"
    fi
    if [ -z "$ref" ]; then
      ref="$(printf '%s\n' "$obj" | sed -n 's/.*"name"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p')"
    fi
    if [ -n "$ref" ] && printf '%s' "$obj" | grep -q '"chunk_order"\|"chunk_name"\|"symbol_count"'; then
      printf '%s\n' "$ref"
    fi
  done
}

snapshot_version="$(sed -n 's/.*"snapshot_version"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' "$OUTPUT_DIR/manifest.json")"
chunk_refs="$(extract_chunk_refs)"
if [ -z "$chunk_refs" ]; then
  echo "No chunk references found in manifest" >&2
  exit 1
fi

while IFS= read -r ref; do
  [ -n "$ref" ] || continue
  chunk_name="${ref##*/}"
  case "$ref" in
    http://*|https://*) chunk_url="$ref" ;;
    /api/*) chunk_url="${BASE_URL%/}$ref" ;;
    *)
      if [ -n "$snapshot_version" ]; then
        chunk_url="${BASE_URL%/}/api/llm/v1/snapshots/$snapshot_version/$chunk_name"
      else
        chunk_url="${BASE_URL%/}/${ref#./}"
      fi
      ;;
  esac
  mkdir -p "$OUTPUT_DIR/$(dirname "$ref")"
  curl --fail --silent --show-error \
    -H "Authorization: Bearer $MARKETSCANNER_API_KEY" \
    "$chunk_url" -o "$OUTPUT_DIR/$ref"
done <<< "$chunk_refs"

missing=0
while IFS= read -r ref; do
  [ -n "$ref" ] || continue
  if [ ! -f "$OUTPUT_DIR/$ref" ]; then
    if [ "$missing" -eq 0 ]; then
      echo "Bundle incomplete. Missing chunks:" >&2
    fi
    echo "- $ref" >&2
    missing=1
  fi
done <<< "$chunk_refs"

if [ "$missing" -ne 0 ]; then
  exit 1
fi

chunk_count="$(printf '%s\n' "$chunk_refs" | grep -c '.')"
echo "Bundle ready: $OUTPUT_DIR"
echo "snapshot_version=${snapshot_version:-unknown}"
echo "chunk_count=$chunk_count"

Windows - download.ps1

$ErrorActionPreference = 'Stop'
$configFile = if ($env:MARKETSCANNER_CONFIG_FILE) { $env:MARKETSCANNER_CONFIG_FILE } elseif ($env:APPDATA) { Join-Path $env:APPDATA 'MarketScanner\llm-bundle.env' } else { Join-Path $HOME 'AppData\Roaming\MarketScanner\llm-bundle.env' }
if ((-not $env:MARKETSCANNER_API_KEY) -and (Test-Path $configFile)) {
  Get-Content $configFile | ForEach-Object {
    if ($_ -match '^\s*MARKETSCANNER_API_KEY=(.+)$') { $env:MARKETSCANNER_API_KEY = $matches[1].Trim() }
  }
}
if (-not $env:MARKETSCANNER_API_KEY) { throw "Set MARKETSCANNER_API_KEY or create $configFile first." }
$baseUrl = if ($env:MARKETSCANNER_BASE_URL) { $env:MARKETSCANNER_BASE_URL } else { 'https://app.stratalerts.com' }
$outputDir = if ($args.Length -gt 0) { $args[0] } else { Join-Path $HOME 'marketscanner-data/latest' }
New-Item -ItemType Directory -Force -Path $outputDir | Out-Null
$manifestUrl = "$baseUrl/api/llm/v1/snapshots/latest"
$headers = @{ Authorization = "Bearer $($env:MARKETSCANNER_API_KEY)" }
$manifest = Invoke-RestMethod -Headers $headers -Uri $manifestUrl
$manifest | ConvertTo-Json -Depth 10 | Set-Content (Join-Path $outputDir 'manifest.json')
$snapshotVersion = if ($manifest.snapshot_version) { "$($manifest.snapshot_version)" } else { '' }
$chunkRefs = @()
foreach ($chunk in @($manifest.chunks)) {
  $ref = ''
  if ($chunk.PSObject.Properties.Name -contains 'relative_path' -and $chunk.relative_path) { $ref = "$($chunk.relative_path)".Trim() }
  elseif ($chunk.PSObject.Properties.Name -contains 'path' -and $chunk.path) { $ref = "$($chunk.path)".Trim() }
  elseif ($chunk.PSObject.Properties.Name -contains 'name' -and $chunk.name) { $ref = "$($chunk.name)".Trim() }
  if ($ref) { $chunkRefs += $ref }
}
if (-not $chunkRefs.Count) { throw 'No chunk references found in manifest' }
foreach ($ref in $chunkRefs) {
  $chunkName = Split-Path -Leaf $ref
  if ($ref -match '^https?://') { $chunkUrl = $ref }
  elseif ($ref.StartsWith('/api/')) { $chunkUrl = "$baseUrl$ref" }
  elseif ($snapshotVersion) { $chunkUrl = "$baseUrl/api/llm/v1/snapshots/$snapshotVersion/$chunkName" }
  else { $chunkUrl = "$baseUrl/$($ref.TrimStart('/'))" }
  $targetPath = Join-Path $outputDir ($ref -replace '/', [IO.Path]::DirectorySeparatorChar)
  $targetDir = Split-Path -Parent $targetPath
  if ($targetDir) { New-Item -ItemType Directory -Force -Path $targetDir | Out-Null }
  Invoke-WebRequest -Headers $headers -Uri $chunkUrl -OutFile $targetPath
}
$missing = @()
foreach ($ref in $chunkRefs) {
  $targetPath = Join-Path $outputDir ($ref -replace '/', [IO.Path]::DirectorySeparatorChar)
  if (-not (Test-Path $targetPath)) { $missing += $ref }
}
if ($missing.Count -gt 0) {
  Write-Error "Bundle incomplete. Missing chunks:`n- $($missing -join "`n- ")"
  exit 1
}
Write-Host "Bundle ready: $outputDir"
Write-Host "snapshot_version=$([string]::IsNullOrWhiteSpace($snapshotVersion) ? unknown : $snapshotVersion)"
Write-Host "chunk_count=$($chunkRefs.Count)"