
Lck Analytics
- 3.4k installs
- 6.5k repo stars
- Updated July 27, 2026
- nomadamas/k-skill
lck-analytics is a skill that queries Riot LCK schedules and Oracle-style historical rows so fans and analysts can review results, live stats, and meta trends.
About
lck-analytics is a Korean-locale skill for League of Legends Champions Korea esports lookups and analysis. It fetches schedule and results via Riot getSchedule, standings via getStandings, and live window or details feeds for in-progress games. Team aliases normalize Korean and English names such as T1, SKT T1, DN SOOPers, and Hanwha before filtering by date or squad. Historical analysis ingests Oracle's Elixir style CSV rows for team power ratings, champion matchup and synergy summaries, and patch meta reports. Lightweight local scripts sync-oracle, build-match-report, and analyze-live-game write cache under .openclaw-lck-cache. Prerequisites require Node.js eighteen plus and a global npm install -g lck-analytics before any workaround. Workflows cover date-specific results, current split rankings, live kill gold objective summaries, turning-point timeline analysis, and date-level match reports. Attribution notes adaptation from jerjangmin's original lck-analytics pack into the k-skill monorepo workspace.
- LCK-focused queries for match results, standings, live stats, and turning-point timeline analysis.
- Team alias normalization for Korean and English names including T1, Gen.G, Hanwha, and DN variants.
- Uses Riot getSchedule, getStandings, getEventDetails, and livestats window or details endpoints.
- Oracle's Elixir style CSV powers historical matchup, synergy, patch meta, and power ratings.
- Requires global npm install -g lck-analytics and includes local sync and match-report scripts.
Lck Analytics by the numbers
- 3,365 all-time installs (skills.sh)
- +127 installs in the week ending Jul 28, 2026 (Skillselion tracking)
- Ranked #27 of 2,066 Data Science & ML skills by installs in the Skillselion catalog
- Security screen: MEDIUM risk (skills.sh audit)
- Data as of Jul 28, 2026 (Skillselion catalog sync)
lck-analytics capabilities & compatibility
- Capabilities
- riot schedule standings and live feed queries · team alias normalization for korean and english · live turning point timeline analysis · oracle csv historical matchup and synergy analys · local cache scripts for sync and match reports
- Use cases
- data analysis · research
What lck-analytics says it does
Riot 공식 LoL Esports 데이터와 Oracle's Elixir 스타일 historical 데이터로 LCK 경기 결과
npm install -g lck-analytics
live timeline 기반 turning point 분석
npx skills add https://github.com/nomadamas/k-skill --skill lck-analyticsAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 3.4k |
|---|---|
| repo stars | ★ 6.5k |
| Security audit | 2 / 3 scanners passed |
| Last updated | July 27, 2026 |
| Repository | nomadamas/k-skill ↗ |
How do I get LCK match results, live stats, standings, and ban-pick meta analysis for a date or team?
Query LCK match results, standings, live stats, ban-pick analysis, and patch meta from Riot and Oracle-style historical data.
Who is it for?
Korean or English-speaking LCK fans and analysts who need official Riot feeds plus Oracle-style historical breakdowns.
Skip if: Skip for non-LCK leagues, casual game coaching without esports data APIs, or environments without Node.js and lck-analytics installed.
When should I use this skill?
User asks for today's LCK results, team standings, live game stats, turning points, ban-pick matchup analysis, or patch meta picks.
What you get
Structured match results, standings tables, live summaries, turning-point notes, or historical meta and power-rating reports.
- historical cache JSON
- match analysis reports
- live-game analysis output
By the numbers
- Bundles 3 Node scripts for CSV sync, match reports, and live-game analysis
- Includes oracle-lck-sample.csv for local smoke testing
Files
LCK Results + Advanced Analysis
What this skill does
이 스킬은 LCK 조회/분석 전용이다.
- 특정 날짜 LCK 경기 결과 조회
- 특정 팀 alias 정규화 후 필터링
- 현재 스플릿 순위 조회
- 진행 중 경기 live stats 조회
- live timeline 기반 turning point 분석
- Oracle's Elixir 스타일 historical row / CSV 기반
- 팀 파워 레이팅
- 챔피언 matchup / synergy 분석
- patch meta 요약
- 날짜별 match analysis 생성
Origin / attribution
이 스킬은 jerjangmin 님이 만든 원본 `lck-analytics` skill pack을 k-skill 저장소 안으로 옮기고, 이 저장소의 npm workspace / Changesets 배포 방식에 맞게 정리한 버전이다.
When to use
- "오늘 LCK 경기 결과 알려줘"
- "2026-04-01 한화 경기 결과랑 순위 보여줘"
- "지금 T1 경기 킬/골드/오브젝트 요약해줘"
- "이 경기 turning point가 뭐였어?"
- "이 밴픽에서 어느 쪽 조합이 더 좋았는지 설명해줘"
- "현재 패치에서 어떤 챔피언이 메타 픽인지 보여줘"
- "LCK 팀 파워 레이팅 보여줘"
Prerequisites
- Node.js 18+
npm install -g lck-analytics
패키지가 없으면 다른 방법으로 우회하지 말고 먼저 전역 설치를 시도한다.
npm install -g lck-analyticsInputs
기본 입력
- 날짜:
YYYY-MM-DD - 선택 사항: 팀명, 과거 팀명, 한글/영문 약칭 alias
고급 분석 입력
- Oracle's Elixir 스타일 CSV 문자열 또는 row 배열
- game id / match id
- live window/details payload 또는 실시간 fetch 권한
- patch version
Team alias normalization
다음 이름들은 같은 canonical team 으로 인식한다.
DN SOOPersDN FREECS광동 프릭스Afreeca Freecs
추가로 T1, SKT T1, 담원, Dplus KIA, 브리온, 한화, 젠지, 피어엑스 등도 alias 정규화를 지원한다.
Official surfaces
이 스킬은 Riot 공식 / 공식 웹앱 표면을 우선 사용한다.
- 일정/결과:
getSchedule - 토너먼트 목록:
getTournamentsForLeague - 순위:
getStandings - 이벤트 상세:
getEventDetails - 라이브 window:
https://feed.lolesports.com/livestats/v1/window/{gameId} - 라이브 details:
https://feed.lolesports.com/livestats/v1/details/{gameId}
historical 고급 분석은 Oracle's Elixir 스타일 데이터 입력을 사용한다.
Workflow
Included lightweight local pipeline
이 k-skill 팩에는 경량 로컬 파일 기반 파이프라인 스크립트가 포함된다.
scripts/sync-oracle.js: Oracle-style CSV → historical cache JSONscripts/build-match-report.js: 날짜별 match analysis 생성scripts/analyze-live-game.js: game analysis 생성- 기본 cache 위치:
.openclaw-lck-cache/
1. Basic scoreboard / standings query
GLOBAL_NPM_ROOT="$(npm root -g)" node --input-type=module - <<'JS'
import path from "node:path";
import { pathToFileURL } from "node:url";
const entry = pathToFileURL(
path.join(process.env.GLOBAL_NPM_ROOT, "lck-analytics", "src", "index.js"),
).href;
const { getLckSummary } = await import(entry);
const summary = await getLckSummary("2026-04-01", {
team: "한화",
includeStandings: true,
});
console.log(JSON.stringify(summary, null, 2));
JS2. Historical analytics from Oracle-style CSV
직접 API를 호출해도 되지만, local skill pipeline에서는 아래 스크립트 사용을 우선 권장한다.
node ./lck-analytics/scripts/sync-oracle.js \
--csv ./lck-analytics/samples/oracle-lck-sample.csv3. Match analysis via local pipeline script
node ./lck-analytics/scripts/build-match-report.js \
--date 2026-04-01필요하면 팀 필터도 같이 준다.
node ./lck-analytics/scripts/build-match-report.js \
--date 2026-04-01 \
--team 한화4. Game analysis with turning points via local pipeline script
node ./lck-analytics/scripts/analyze-live-game.js \
--game game-idfixture 기반으로 분석할 때는 --window, --details 를 같이 줄 수 있다.
Output guidelines
사용자에게는 원본 JSON을 길게 그대로 던지지 말고 먼저 아래 순서로 정리한다.
경기 결과 요청
- 경기 시각
- 팀1 vs 팀2
- 상태
- 세트 스코어
- 요청 팀 경기만 있으면 해당 경기 우선
- standings 요청이 있으면 현재 순위 같이 표시
진행 중 경기 요청
- 현재 게임 번호
- 킬 차이
- 골드 차이
- 드래곤/바론/타워 차이
- turning point 1~3개
historical / meta 요청
- sample 수를 먼저 표시
- 팀 파워 레이팅은 상위 팀부터 정렬
- champion matchup / synergy는 표본 수가 적으면 낮은 확신도로 표시
- patch meta는 top picks / risers 위주로 짧게 요약
Done when
- 날짜 기준 경기 요약이 있다
- 요청 팀 필터가 적용된다
- standings 요청이면 현재 순위가 같이 정리된다
- live 요청이면 현재 게임 요약과 turning point가 있다
- historical 입력이 있으면 patch meta 또는 power rating까지 설명할 수 있다
Failure modes
- Riot 웹앱 API 구조/헤더가 바뀌면 패키지 수정이 필요할 수 있다
LOLESPORTS_API_KEYpublic fallback이 회전되면 환경변수 override가 필요할 수 있다- historical CSV 컬럼명이 너무 다르면 Oracle-style 정규화 전에 전처리가 필요할 수 있다
Notes
- 이 스킬은 조회/분석 전용이다
- 사용자의 "오늘/어제" 요청은 항상 절대 날짜(
YYYY-MM-DD)로 변환해서 실행한다 - 이 저장소에서
main으로 머지되면 Changesets가 Version Packages PR을 만들고, 그 PR이 merge된 뒤 npm publish가 실행된다
LCK Analytics skill pack
k-skill 버전의 lck-analytics 스킬 팩입니다.
- Original source: <https://github.com/jerjangmin/share/tree/main/SKILL/lck-analytics>
- Original author:
jerjangmin - This repo adaptation: npm workspace / Changesets 릴리스 흐름에 맞춘 k-skill 배포용 패키징
포함 항목:
SKILL.md: 에이전트에 바로 줄 수 있는 스킬 문서scripts/sync-oracle.js: Oracle-style CSV → historical cache JSONscripts/build-match-report.js: 날짜별 match analysis 생성scripts/analyze-live-game.js: live game analysis 생성samples/oracle-lck-sample.csv: local smoke test용 샘플 CSV
league,matchid,date,patch,side,teamname,opponentteam,playername,position,champion,opponentchampion,result,gd15,csd15,xpd15,drg,bn,blindpick,counterpick
LCK,match-1,2026-04-01,16.6.753.8272,blue,Hanwha Life Esports,T1,HLE Zeus,top,Aatrox,Gnar,win,1200,18,340,100,100,0,1
LCK,match-1,2026-04-01,16.6.753.8272,blue,Hanwha Life Esports,T1,HLE Peanut,jungle,Vi,Sejuani,win,800,5,280,100,100,1,0
LCK,match-1,2026-04-01,16.6.753.8272,red,T1,Hanwha Life Esports,T1 Doran,top,Gnar,Aatrox,loss,-1200,-18,-340,0,0,1,0
LCK,match-1,2026-04-01,16.6.753.8272,red,T1,Hanwha Life Esports,T1 Oner,jungle,Sejuani,Vi,loss,-800,-5,-280,0,0,0,1
const fs = require("node:fs");
const path = require("node:path");
const { pathToFileURL } = require("node:url");
async function loadLckResults() {
const candidates = [];
const packageNames = ["lck-analytics", "lck-results"];
if (process.env.GLOBAL_NPM_ROOT) {
for (const packageName of packageNames) {
candidates.push(path.join(process.env.GLOBAL_NPM_ROOT, packageName, "src", "index.js"));
}
}
try {
const globalRoot = await detectGlobalNpmRoot();
for (const packageName of packageNames) {
candidates.push(path.join(globalRoot, packageName, "src", "index.js"));
}
} catch {
// ignore detection failure and continue to local fallback
}
candidates.push(path.resolve(__dirname, "..", "..", "packages", "lck-analytics", "src", "index.js"));
const entryPath = candidates.find((candidate) => fs.existsSync(candidate));
if (!entryPath) {
throw new Error("Could not find lck-analytics package. Install it globally with `npm install -g lck-analytics` or run from the k-skill repo.");
}
return import(pathToFileURL(entryPath).href);
}
function ensureDir(dirPath) {
fs.mkdirSync(dirPath, { recursive: true });
}
function readJson(filePath, fallback = null) {
if (!fs.existsSync(filePath)) {
return fallback;
}
return JSON.parse(fs.readFileSync(filePath, "utf8"));
}
function writeJson(filePath, value) {
ensureDir(path.dirname(filePath));
fs.writeFileSync(filePath, `${JSON.stringify(value, null, 2)}\n`, "utf8");
}
function readText(filePath, fallback = "") {
if (!fs.existsSync(filePath)) {
return fallback;
}
return fs.readFileSync(filePath, "utf8");
}
function parseArgs(argv) {
const args = {};
for (let index = 0; index < argv.length; index += 1) {
const token = argv[index];
if (!token.startsWith("--")) {
continue;
}
const key = token.slice(2);
const next = argv[index + 1];
if (!next || next.startsWith("--")) {
args[key] = true;
continue;
}
args[key] = next;
index += 1;
}
return args;
}
function formatOutput(value) {
return `${JSON.stringify(value, null, 2)}\n`;
}
function resolveCachePaths(baseDir) {
return {
root: baseDir,
historical: path.join(baseDir, "historical-analysis.json"),
live: path.join(baseDir, "live"),
reports: path.join(baseDir, "reports"),
};
}
async function detectGlobalNpmRoot() {
const { execFileSync } = require("node:child_process");
return execFileSync("npm", ["root", "-g"], { encoding: "utf8" }).trim();
}
module.exports = {
ensureDir,
formatOutput,
loadLckResults,
parseArgs,
readJson,
readText,
resolveCachePaths,
writeJson,
};
#!/usr/bin/env node
const fs = require("node:fs");
const path = require("node:path");
const {
formatOutput,
loadLckResults,
parseArgs,
readJson,
resolveCachePaths,
writeJson,
} = require("./_lib");
async function main() {
const args = parseArgs(process.argv.slice(2));
const gameId = args.game;
if (!gameId) {
throw new Error("--game <gameId> is required");
}
const cacheDir = path.resolve(args.cache || path.join(process.cwd(), ".openclaw-lck-cache"));
const paths = resolveCachePaths(cacheDir);
const historicalWrapper = readJson(paths.historical, { data: {} });
const pkg = await loadLckResults();
const liveWindowPayload = args.window ? JSON.parse(fs.readFileSync(path.resolve(args.window), "utf8")) : undefined;
const liveDetailsPayload = args.details ? JSON.parse(fs.readFileSync(path.resolve(args.details), "utf8")) : undefined;
const analysis = await pkg.getGameAnalysis(gameId, {
matchId: args.match,
number: args.number ? Number(args.number) : null,
state: args.state || undefined,
historicalDataset: historicalWrapper.data,
liveWindowPayload,
liveDetailsPayload,
});
const reportFile = path.join(paths.reports, `game-${gameId}.json`);
writeJson(reportFile, analysis);
process.stdout.write(formatOutput({
ok: true,
reportFile,
patch: analysis.patch,
turningPoints: analysis.turningPoints,
draftEdge: analysis.draft?.overallEdge || null,
}));
}
main().catch((error) => {
console.error(error.stack || String(error));
process.exitCode = 1;
});
#!/usr/bin/env node
const path = require("node:path");
const {
formatOutput,
loadLckResults,
parseArgs,
readJson,
resolveCachePaths,
writeJson,
} = require("./_lib");
async function main() {
const args = parseArgs(process.argv.slice(2));
const date = args.date;
if (!date) {
throw new Error("--date <YYYY-MM-DD> is required");
}
const cacheDir = path.resolve(args.cache || path.join(process.cwd(), ".openclaw-lck-cache"));
const paths = resolveCachePaths(cacheDir);
const historicalWrapper = readJson(paths.historical, { data: {} });
const pkg = await loadLckResults();
const analysis = await pkg.getMatchAnalysis(date, {
team: args.team || undefined,
historicalDataset: historicalWrapper.data,
});
const reportFile = path.join(paths.reports, `match-${date}${args.team ? `-${args.team}` : ""}.json`);
writeJson(reportFile, analysis);
process.stdout.write(formatOutput({
ok: true,
reportFile,
queryDate: analysis.queryDate,
matchCount: analysis.matches.length,
teams: analysis.matches.map((match) => `${match.team1?.name} vs ${match.team2?.name}`),
}));
}
main().catch((error) => {
console.error(error.stack || String(error));
process.exitCode = 1;
});
#!/usr/bin/env node
const path = require("node:path");
const {
formatOutput,
loadLckResults,
parseArgs,
readText,
resolveCachePaths,
writeJson,
} = require("./_lib");
async function main() {
const args = parseArgs(process.argv.slice(2));
const cacheDir = path.resolve(args.cache || path.join(process.cwd(), ".openclaw-lck-cache"));
const csvPath = args.csv ? path.resolve(args.csv) : path.join(__dirname, "..", "samples", "oracle-lck-sample.csv");
const league = args.league || "LCK";
const csvText = readText(csvPath);
if (!csvText.trim()) {
throw new Error(`CSV not found or empty: ${csvPath}`);
}
const pkg = await loadLckResults();
const historical = pkg.buildHistoricalAnalytics(csvText, { league });
const paths = resolveCachePaths(cacheDir);
writeJson(paths.historical, {
source: {
type: "oracle-style-csv",
csvPath,
league,
updatedAt: new Date().toISOString(),
},
data: historical,
});
process.stdout.write(formatOutput({
ok: true,
cacheFile: paths.historical,
teamRatings: historical.teamPowerRatings.length,
matchupStats: historical.matchupStats.length,
synergyStats: historical.synergyStats.length,
patchMeta: historical.patchMeta.length,
}));
}
main().catch((error) => {
console.error(error.stack || String(error));
process.exitCode = 1;
});
Related skills
How it compares
Choose lck-analytics for scripted LCK Oracle CSV pipelines; use general data-science skills for non-esports tabular analysis.
FAQ
What must be installed before using lck-analytics?
Node.js 18+ and a global npm install -g lck-analytics; the skill does not bypass a missing package.
Which data sources does it use?
Riot official LoL Esports APIs for schedule, standings, events, and livestats feeds plus Oracle's Elixir style historical CSV rows.
Can it analyze games in progress?
Yes. Live window and details endpoints support kill, gold, objective summaries and turning-point timeline analysis.
Is Lck Analytics safe to install?
skills.sh reports 2 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.