mcpField
S
sling

sling

github.com/starslingdevその他4540 回インストール今日更新
リポジトリ

sling について

slingは、GitHub Actionsのライブデータを照会・分析するStarSlingのエージェント向けコマンドラインツールです。読み取り専用で構造化JSONを返し、スキルは依頼の振り分けやトラブルシューティング手順も示します。

主な機能

  1. 01実行・ジョブ・試行データの照会
  2. 02アカウントのRunner分数の確認
  3. 03構造化JSONでの出力
  4. 04安定した終了コード
  5. 05CIデータの読み取りと分析

活用シーン

  1. 01GitHub Actionsの実行やジョブの診断
  2. 02CIログと結果の確認
  3. 03アカウントのRunner分数の把握
  4. 04slingが使えない場合にghで読み取り

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/starslingdev/skills --skill sling

インストール後、Claude Code で/slingを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

CHANGELOG.md
LICENSE
evals/
evals.json
prompt-routing.json
references/
command-reference.md
command-surface.json
gh-fallback.md
tests/
test_sling_routing.py

README(原文)English

プロジェクトの README より

この README の日本語訳はまだありません。以下は英語の原文です。日本語の紹介はページ上部をご覧ください。

sling CLI

sling is StarSling's agent-first CLI for GitHub Actions. It answers questions about live CI data — one run, one job, one attempt, or an account's runner-minutes — from StarSling's control plane, with structured JSON on stdout and a stable exit-code table. In this release it is read-only: it reads and analyzes, and there is no sling command that changes anything in GitHub.

This skill's job is picking the right tool per request. Live question about a run, a job, or spend → sling. Anything that changes CI state → gh. A repo-wide audit of workflow files → hand off to the audit skill that owns it and stop. Do not invent a sling subcommand for something sling does not do; the command surface is the complete list.

Every fact in this skill's command reference was read off sling itself (v0.1.8) rather than from documentation — see references/command-reference.md for the verified per-command JSON shapes.

Preflight: is sling installed and authenticated?

Do this once per session, before the first sling command.

  1. Is it on PATH? command -v sling. If it is missing, sling is installed by a one-line installer published on the installation page at https://docs.starsling.dev/sling-cli/installation — point the user at that page and let them run it, rather than pasting an installer command from memory. It supports Apple Silicon macOS and x64 glibc Linux only; there is no Windows build, so on Windows say so plainly and use the gh-only path in step 6.

  2. Is the environment healthy? sling doctor --agent. It emits {"checks": [{"key", "ok", "detail", ...}]} on stdout and exits 10 when a real check fails (0 when healthy). The checks name the problem. Seven of the eight are actionable — token, control_plane, clock_skew, git_remote, patch_tooling, version, org — so act on the one that is ok: false instead of guessing (the eighth, agent_skill, is advisory only; see below) — and when SEVERAL are ok: false, act on control_plane first: an unreachable control plane fails token and org as dependents, and the token check still attaches fix_command: "sling login" — a wrong lead during an outage, since the device flow cannot reach the control plane either. Network first, never login. "skipped": true can also mean "not checked" for exactly this reason — read detail, not just the flag. A version check with warn: true is an upgrade notice, not a failure — any fix_command it carries is the installer one-liner, a shell pipeline, so surface it to the user rather than running it yourself. version reads ok: false, skipped: true when it could not compare at all (installer URL unreachable, served version unreadable) — that is "not checked", not "out of date". The agent_skill row is likewise advisory and can never make doctor unhealthy: a check counts as failing only when it is ok: false AND not skipped, and this row's only ok: false shape is also skipped: true. It reports whether this skill is installed for a coding agent on the machine, and it can read "not installed" while you are reading the skill, because it only looks in a fixed set of directories. So report the row with its detail and never run its fix_command yourself — installing is the user's call (see references/command-reference.md).

  3. Not authenticated (doctor's token check fails, or a command exits 4 whose stderr does not name an org): ask the user to run sling login in their own terminal, then wait for them to say it is done. Do not run it yourself, and never pass --agent to it.

    Read the stderr before acting on exit 4. You don't have access to org "<name>" is a missing app installation, not a stale credential, and it belongs to step 5 rather than here. It ends Run \sling login`` anyway, because a generic decorator appends that to every auth-class error — so the code and the advice both point the wrong way. Signing in again succeeds and changes nothing, which reads to the user as a broken login rather than as the missing installation it is.

    Signing in needs a person at a browser: sling login prints a device code, opens a GitHub approval page, and blocks until someone approves it. Launched as a subprocess that is unworkable in both directions — the output arrives only once the command has already finished or timed out, so the code is never visible while it can still be used, and --agent would refuse the prompt outright with exit 2. There is no automated path here, and pretending otherwise just hangs the session.

    The credential is saved per user at ~/.config/sling/credentials, so once they have signed in, an agent running as them is authenticated with no further setup. Re-run sling doctor --agent to confirm, then carry on.

  4. Wrong org — you belong to several and have not picked one. doctor's org check naming multiple slugs, an exit 2 about org ambiguity, or an id that resolves to nothing but plausibly exists in another of your orgs: sling org switch <slug>, or pass --org <slug> on the single command.

    --org and --repo <owner/name> are accepted by most subcommands but not by sling logs, which parses strictly and rejects both with exit 2 (Unknown flag "--org"). That is the command this routing table reaches for most, so fix a wrong org for a logs read by switching the default rather than by adding a flag to the call. --repo otherwise defaults to the git remote of the current directory, and takes owner/name — a bare repo name is rejected with exit 2.

    doctor's org check also fails when you belong to no orgs, which looks similar and is not this. There is no slug to switch to — that is step 5.

  5. StarSling gate — the app is not installed anywhere you can see. sling reports CI that the StarSling GitHub App collected, so a valid login sees nothing until the app is installed on a GitHub organization. Two shapes, one cause, one answer:

    • An org exists and you cannot see it — exit 4, You don't have access to org "<name>". Rule out a typo first. A slug that could never exist returns byte-identically, so this message alone does not establish that an org is real: sling org switch <slug> answers with Unknown org "<slug>" — your orgs: …, which both settles it and prints the list. Telling someone to install a GitHub App on an organization they mistyped is worse than saying nothing. The URL carve-out below does NOT cover the flag path: a third party's org passed via --repo/--org lands here at exit 4 (verified: --repo vercel/skills), same split — your own orgs are listed by org switch; a third party's routes to the gh read fallback of step 6. The message ends Run \sling login``, which cannot work: the credential was never the problem. That suffix is appended to every auth-class error by a generic decorator, so read it as boilerplate rather than as advice about this case.
    • You have no orgs at all — exit 2, You don't belong to any orgs yet., and doctor's org check saying the same. This is the ordinary state of someone who installed sling and signed in before ever installing the app; signing in succeeds and gives no hint that a step is missing. Do not read exit 2 here as a bad flag, and do not send them to sling org switch — there is nothing to switch to.

    A sandboxed agent shell can also fail an auth probe for reasons of its own, so retry once with host access before trusting a single failure.

    In either shape, STOP and tell the user plainly — every answer this skill gives comes from StarSling's record of their runs, so until the app is installed there is no run data to read and only the gh read path remains. Give them the path: install the app at https://github.com/apps/starslingdev on the organization whose CI they are asking about, or ask an owner to add them. Continue on the gh-only path ONLY if they say so, and name what is unavailable when you do.

    A pasted URL from someone else's org never reaches this gate. The resolver searches only orgs you belong to, so a foreign Actions URL fails with exit 3 (not-found), not exit 4 — verified live on a mastra-ai run URL. The app-install remedy applies only to orgs the user belongs to; for a third party, the right move is the gh read fallback of step 6.

    Organizations only. The app installs on a personal repository but StarSling does not pick up its jobs, so there is never data to report for one — say that rather than reporting an empty result.

  6. If sling cannot be installed or authenticated at all, fall back to the gh read path for whatever is achievable (gh run view, gh run view --log-failed) and tell the user plainly that the richer diagnosis — sling why's classification, sling time's phase breakdown — is unavailable without sling. Do not silently degrade.

    Run the gh gate below before promising that path: with neither CLI available there is nothing left to fall back to, and saying so up front beats discovering it one failed command at a time.

Always pass --agent

--agent is the machine-mode flag: JSON on stdout, no prompts, no colour. Pass it on every data command and parse stdout as JSON. Do not also pass --json — help pages render the pair together (--json, --agent), with per-command wording.

Do not describe it as an alias for a longer flag list. The published docs call it "exactly equivalent to --json --compact --no-input --no-color --yes", and on v0.1.8 --compact is not a flag this binary has at all: passing it changes nothing because unknown flags are ignored, not because it does anything. Output is pretty-printed, indented JSON either way, so feed stdout to a real JSON parser and never to a line-oriented one that assumes one object per line.

Never pass --agent to sling login. Signing in requires a human to open a browser and approve a device code, and --agent carries --no-input, which refuses the prompt rather than showing it — turning the one command that needs a person into exit 2. sling org switch has the same shape: under --agent its picker is refused, so give it an explicit slug (sling org switch acme --agent).

  • Branch on the exit code, never on whether stdout looks empty. Human chrome (spinners, summary rows, prompts) goes to stderr, and only when stderr is a TTY. 6 and 10 are outcomes rather than errors: they emit the full JSON payload on stdout with stderr empty — an unhealthy sling doctor --agent exits 10 and still returns every check, which is exactly what the preflight above asks you to read.

    A non-zero exit does not mean stdout is empty, and a well-formed JSON body does not mean success. sling logs on a job that stores no logs exits 3 and still prints {"lines": [], "has_more": false, …}; sling resolve on an ambiguous id exits 2 and still prints {"candidates": […]}. So read stdout as JSON and read the exit code, and when the two disagree the exit code decides. Reporting that empty lines array as "nothing in the log" is exactly the silent false negative this skill exists to prevent — the reason is on stderr, which stays worth reading even when stdout parsed cleanly.

  • Under --agent, every data command returns JSON, sling logs included (sling exit-codes is help text: exit 0, empty stdout, prose on stderr). A log-less job's payload carries its own machine discriminator — "local": {"empty": {"kind": "absent"}} — alongside "lines": [].

  • JSON keys are snake_case on every command except whoami, which returns camelCase (userId, githubLogin, expiresAt). Key a parser per command, not on a local-vs-remote rule.

The traps in this contract are collected under Gotchas — worth reading before the first parse.

The routing table

Decide with two questions, in order.

1. Does the request change anything, or only read? If the user wants to change CI state — re-run a job, cancel a run, trigger a workflow, flip a workflow on or off, pull down an artifact — sling cannot do it in this release. Use gh directly; do not attempt a sling subcommand for these under any name.

2. If it only reads: is it about one run, one job, or aggregate cost/usage — or about the repo's CI configuration as a whole? One run, one job, or spend attribution → sling. The repo's workflow YAML, its best-practice adherence, its security posture, or a multi-run optimization sweep → hand off (see Handoff) instead of reading YAML yourself.

User is asking about...Route toCommand
Why a specific job failedslingsling why <run|job|attempt id|URL>
Where a run's wall-clock went (queue wait vs. provision vs. steps vs. teardown)slingsling time <run|job|attempt id|URL>
The same, as percentiles across a reposlingsling time --repo <owner/name> --window <n>d
Recent runs and their statusslingsling runs list [--branch --status --conclusion --trigger --workflow-path --label --window --limit]
Detail on one run (its jobs, attempts, runner)slingsling runs show <run id|URL> [--wait] [--fail-fast]
Which jobs in a run failed, or jobs across a reposlingsling jobs list --run <id> / --repo <owner/name>
Which step in a job failed, and each step's durationslingsling jobs show <job id|URL>
Only the log lines that matter for a failureslingsling logs <run|job|attempt id|URL> [--grep <re>] [--since <dur>] [--limit <n>]
Turning a pasted Actions URL into a run/job/attempt idslingsling resolve <id|URL> [--target run|job|attempt] — a run id covering several jobs is ambiguous: exit 2, {"candidates": […]} on stdout. Pass one of the returned candidate ids (att_<jobid>.<n>) or --target run; --target job/attempt re-state the kind and return the same ambiguity
The biggest time or cost hotspotsslingsling top [--by workflow|job|label|repo|branch] [--metric ...]
Runner-minutes and cost attributed per repo/workflow/label/dayslingsling usage [--group-by <axis>] [--window <n>d]
What is owed this period, or past invoicesslingsling bill, sling bill history
Which runner labels/sizes exist and what they costslingsling labels list
Identity, org, credential, environment healthslingsling whoami, sling doctor, sling org switch — and sling login, which the user runs, not you
Re-run a run or its failed jobsghgh run rerun <run-id> [--failed]
Cancel an in-progress runghgh run cancel <run-id>
Trigger a workflow (workflow_dispatch)ghgh workflow run <workflow> [-f key=value]
Enable or disable a workflowghgh workflow enable|disable <workflow>
Download an artifactghgh run download <run-id>
Delete a runghgh run delete <run-id>
Approve or reject a pending deploymentghgh api — see references/gh-fallback.md
The checks on a specific PRghgh pr checks <pr> — then take the failing run/job id back into sling why / sling time
Secrets or repo/environment variablesghgh secret, gh variable
The contents of a workflow fileneitherRead the .yml directly — this is a file question, not a CLI action
A repo-wide grade, speed sweep, or security scanneitherHand off — see Handoff

Ambiguous asks. With no action verb (re-run / cancel / trigger / enable / disable / download) and a specific run, job, or spend in view, default to sling: it is the read path and costs nothing to try. If the ask is read-only but sling has no matching subcommand — "what does this workflow's on: trigger include" is YAML content, not run data — read the file rather than forcing it through either CLI.

Compound asks — "tell me why this run failed, then re-run it" — are two steps, in order: do the sling half first (sling why), report it, then do the gh half (gh run rerun) as an explicit, separately announced action — and run the gh gate (below) before promising that second half: a working sling says nothing about whether gh is signed in. Never chain into a state change without telling the user what changed.

Command reference

Full per-command flags and the verified JSON shape of every response: references/command-reference.md. The machine-readable list of every command that exists, which is what keeps this skill from inventing one: references/command-surface.json.

The short version, grouped the way sling --help groups them:

  • Auth & setup — login, logout, whoami, doctor, org switch.
  • Inspect CI — runs list, runs show, jobs list, jobs show, logs, resolve.
  • Diagnose — why (classification, evidence, suggested actions, and a ready-to-use prompt field), time (wall-clock split into queue_wait, provision, image_pull, cache_restore, checkout+patch, steps, cache_save, teardown).
  • Cost & capacity — usage, top, bill, bill history, labels list.

Two habits worth keeping:

  • sling why on a RUN (id or URL) can answer for ONE selected job at exit 0 — verified on a cancelled three-job run, where it diagnosed the single failed job and never mentioned the other two or the cancellation. Before reporting that diagnosis as the cause of a run, confirm the run's job set (jobs list --run <id>) whenever the run has several jobs or did not conclude cleanly.
  • Start from why for a failure, not from logs. why is classified server-side with no LLM in the loop, and its suggested_actions[] carry the exact follow-up command (usually a sling logs --grep) instead of making you guess a pattern. Its prompt field is written for an agent to act on directly.
  • sling logs is a filter, not a dump. Reach for --grep and --limit before pulling a whole transcript; has_more plus --cursor pages the rest.

Exit codes

Branch on $?, read immediately after the command. The inference fails in both directions: a successful result can be empty, and a failed command can still print a full JSON body — logs exits 3 with {"lines": []}, resolve exits 2 with {"candidates": […]} — and so do logs, why and time on a bare multi-job run id, with why/time putting nothing on stderr at all. The invocation was valid: read the candidates off stdout and pass one id (or --target run) rather than re-reading --help for a usage error that is not there. Neither an empty stdout nor a parseable one tells you what happened; only $? does.

CodeMeaningWhat to do
0Success—
1Unexpected internal error (a crash) — or a subcommand that does not existRead stderr first. unknown command "<name>" for "sling" is a routing mistake, not a crash: the binary lists its real commands, so correct the name against that list rather than filing a bug — this is where the doctor fix_command gotcha below lands. stderr naming an environment variable (SLING_HOST must be a valid https URL …) is an environment fix, not a bug. Anything else: do not retry blindly, and surface the stderr text as a bug report
2Usage — bad flags, a prompt refused under --agent, org ambiguity, or no orgs at allRead the stderr first. You don't belong to any orgs yet. → step 5, the app is not installed; never a flag problem. Org-ambiguous → pass --org or sling org switch. Otherwise fix the invocation against sling <cmd> --help
3Not found — no such run/job/attempt in any org you can access, or a real job that stores no logsA pasted URL from a third-party org lands here, not on exit 4 — the resolver searches your orgs and reports not-found (No run/job/attempt matches that id in an org you can access). For an org the user does not belong to, do not suggest installing the app on it: fall back to the gh read path (public repos answer) and say the richer sling diagnosis is unavailable. Otherwise try sling resolve, confirm the org, then ask the user to confirm the id
4Auth — or no StarSling installation on that org, or a third party's org named via a flag. Read the stderr text before actingYou don't have access to org "<name>" → the app is not installed there (or the user is not a member); point them at https://github.com/apps/starslingdev, do NOT retry login. Anything else → ask the user to run sling login themselves (a browser approval, never --agent), then retry once. If the retry exits 4 again, STOP and report what was verified — never ask for a second login
5Control-plane or API error (5xx or transport)Retry once after a short backoff (~2s); on a second failure fall back to the gh read equivalent and say sling was unreachable
6Partial — telemetry incomplete, result still emitted (time, why)Not an error. Use the result, and tell the user it is partial
7Rate limited (HTTP 429)Back off and retry once. On a second 429, stop: fall back to the gh read equivalent and say sling was rate limited
10Remote outcome failed — doctor unhealthy, or runs show --wait on a run that did not succeedNot a CLI error. This is the answer: report the unhealthy check, or the run's failure

sling exit-codes on v0.1.8 prints only 0–5; codes 6, 7, and 10 are real and documented (and doctor --help names 10 itself), so treat that help text as abridged. Any non-zero code not in this table: surface stderr to the user rather than guessing a recovery.

Gotchas

These are the places where sling behaves differently from what its own output, its --help, or its documentation implies. Each was found by running the binary; none of them announce themselves at runtime. Everything version-pinned here was verified against sling v0.1.8 and gh 2.93.0 — re-verify on upgrade.

  • doctor's fix_command is advice, not a verified command. On 0.1.2 its version check recommended a command that did not exist — it emitted "fix_command": "sling update", and sling update does not exist in any release (0.1.8 still rejects it as unknown; the check now emits the installer one-liner instead). Other checks emit templates with unfilled placeholders: git_remote suggests git remote add origin <github-url> verbatim. Never run a fix_command unchecked. The general lesson outlives the original bug: a command name printed by a tool is not proof the tool has it.
  • Exit 4 does not always mean the credential is stale, and its message misdirects when it does not. An org StarSling was never installed on fails with You don't have access to org "<name>". Run \sling login`` — the same shape as an expired session, ending in advice that cannot work. Read the message before acting on the code: a named org means the app is missing there, not that the login is.
  • An empty listing is a coverage hole, never a finding. sling runs list --repo <name> returns {"runs": []} and exit 0 both when the repo truly had no runs in the window and when StarSling is not watching that repo at all. The payload cannot tell them apart, so an empty result means this check did NOT run — say so with the reason you cannot rule out, rather than reporting "you have no CI runs" as a fact about their repo. A repo that does not exist at all returns the same empty shape at exit 0 (verified live), so when the answer matters, a cheap gh read — gh repo view, gh run list — settles which of the three it is. The same three-way-ambiguous empty comes back from jobs list --repo ({"jobs": []}), usage --repo ({"rows": []}) and time --repo ({"phases": []} — at exit 6, which time --repo returns even on full data, so "partial" there carries no signal; the empty phase list is the coverage hole).
  • There is no client-side timeout. A black-holed control plane (packets dropped, not refused) hangs sling indefinitely — verified past 45s — with no exit code and nothing on either stream. Wrap long calls in a timeout, and when one fires report the timeout itself: a killed command produced no result, and "no result" is never "no findings". A refused connection returns exit 5 cleanly.
  • Unknown flags are ignored, not rejected. sling runs list --bogus exits 0 and returns unfiltered rows. Exit 0 is therefore not evidence that a filter applied — check the rows you got back before reporting a filtered answer.
  • --help lists an abridged flag set. runs list --help omits --trigger, --workflow-path, --label and the window flags, all of which work. Absence from --help is not absence from the CLI; the fuller list is in references/command-reference.md.
  • sling logs returns JSON under --agent — the same structured envelope as every other data command. (An earlier revision claimed the published docs disagreed; they do not — the docs document exactly this. The real doc discrepancy is smaller: they call the envelope one-object-per-line, and it is pretty-printed, indented JSON.)
  • A zero phase in sling time can mean "not measured". In v1, image_pull and cold_start are bundled into provision and reported as 0 with a reason in meta.truncated. Read that array before telling a user a phase took no time — a measurement gap reported as a finding is a false finding.
  • Exit 10 is an answer, not a failure. doctor unhealthy and runs show --wait on a failed run both exit 10. Report what it says. Exit 6 likewise carries a real result, flagged partial.
  • --agent silently includes --yes. Harmless while sling is read-only, but do not treat a confirmation prompt as a safety net.
  • sling runs show gives no job_id — its jobs[] carry job_name and attempts[] only. Use jobs list --run <id> or resolve when you need job ids.
  • sling top can report a repo as (multiple) when one key spans repos. Do not print that as a repo name without saying what it means.
  • sling bill has two totals. amount_due_usd is what is owed; amount_usd is before credits. status: "open" means the period is still accruing, so it is not a final number.

Handoff to the audit skills

sling reads live run data and has no ability to read workflow configuration at all, so it structurally cannot audit, grade, or scan a repo. When a conversation turns into "audit my whole CI setup", "grade my CI", "why is CI slow generally", or "is this secure", stop and name the right skill rather than looping sling over every run:

The askThe skill
A configuration best-practices grade ("grade my CI", "CI score")ci-score
A measured speed / runner-minute audit across many runs ("why is CI slow")ci-speedup
A security scan of the workflow files ("is my CI secure")ci-secure

Each reads a local checkout and runs its own catalog. Name the skill and let the user run it; do not approximate one of these from run data.

Suggest, do not auto-chain. After sling usage or sling top shows a clear cost outlier, or sling time shows one phase dominating repeatedly, end the answer by suggesting ci-speedup for the across-many-runs root cause and fix — sling shows that this run is slow or expensive; ci-speedup shows why, with a fix. Never invoke another skill without the user asking.

gh fallback

The mutating commands this skill routes to, with their real syntax: references/gh-fallback.md.

gh gate, before the first gh call. If gh isn't installed or gh auth status fails, gh cannot do any of it — and gh authenticates separately from sling, so a working sling says nothing about whether gh is signed in. Sandboxed agent shells (Codex) can't reach keyring credentials: retry with host access before trusting a failure, and never report auth "expired" off a sandboxed probe. When host access is not available to retry with, report gh's availability as UNVERIFIED rather than expired or absent. Then STOP and tell the user plainly which half of their request is unavailable — the reads still work through sling, the state change does not. Give the path (https://cli.github.com; then gh auth login), and never report an action as done that never ran.

コメント