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.
Save Key Locally
- macOS/Linux
- Windows
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"
$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"
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.
Optional Downloader Install
Optional for users who want a saved local downloader script instead of relying on
/msr refresh.- macOS/Linux - download.sh
- Windows - download.ps1
#!/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"
$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)"