Useimmat käyttävät Claude Codea terminaalissa keskustellen. Sama työkalu toimii myös ilman keskustelua: annat tehtävän yhdellä komennolla, Claude tekee sen ja tulostaa tuloksen. Silloin sen voi laittaa npm-skriptiin, cron-ajoon tai CI-putkeen siinä missä minkä tahansa muun komentorivityökalun.
Tässä oppaassa käydään läpi, miten headless-ajo toimii, miten tulos saadaan koneluettavaan muotoon, miten oikeudet annetaan ilman ihmistä ja miten GitHub Actions -integraatio asennetaan. Lopuksi katsotaan lyhyesti Agent SDK:ta.
Mikä on Claude Coden headless-tila?
Headless tarkoittaa ajoa ilman interaktiivista käyttöliittymää. Claude Codessa se tehdään lipulla -p (pitkänä --print):
claude -p "Mitä auth-moduuli tekee?"
Komento käynnistyy, Claude lukee tarvitsemansa tiedostot, vastaa ja ajo päättyy. Kesken ajon ei voi kirjoittaa mitään, eikä kukaan vastaa kyselyihin.
Exit-koodi kertoo skriptille, miten kävi. Onnistunut ajo päättyy koodiin 0 ja epäonnistunut muuhun koodiin. Virheellinen lippu tulostuu stderriin ennen kuin ajo alkaa. Jos virhe tapahtuu ajon sisällä, esimerkiksi kirjautuminen puuttuu, se tulostuu tuloksena stdoutiin.
Dokumentaatio kutsuu tätä Agent SDK:n komentoriviliittymäksi. Sama agenttisilmukka, samat työkalut ja sama kontekstinhallinta ovat käytössä kuin interaktiivisessa Claude Codessa.
Milloin headless kannattaa ja milloin ei
Headless sopii tehtäviin, joissa lopputulos on selvä ja sen voi tarkistaa jälkikäteen: lokin selittäminen, diffin katselmointi, muutosten tiivistäminen, testien ajaminen ja yksinkertaisten virheiden korjaus. Näissä kukaan ei kaipaa keskustelua kesken työn.
Huono valinta se on silloin, kun tehtävä vaatii tarkennuksia. Interaktiivisessa sessiossa Claude voi kysyä, kumpaa kahdesta vaihtoehdosta tarkoitit. Headless-ajossa se joko arvaa tai pysähtyy. Isompi uusi ominaisuus kannattaa siis suunnitella keskustellen, esimerkiksi plan modessa, ja automatisoida vasta toistuvat rutiinit.
Toinen huomio: headless-ajon tulos tarkistetaan samalla tavalla kuin kollegan pull request. Se, ettei kukaan katsonut ajoa, ei tee tuloksesta luotettavampaa.
Putkita dataa sisään
claude -p lukee stdinin, joten siihen voi syöttää lokeja, diffejä tai mitä tahansa tekstiä:
cat build-error.txt | claude -p "Selitä lyhyesti, mikä aiheuttaa tämän build-virheen" > selitys.txt
Putkitetun syötteen yläraja on 10 MB. Isommat syötteet kirjoitetaan tiedostoon, ja promptissa kerrotaan tiedoston polku.
Esimerkki: Claude npm-skriptinä
Dokumentaation oma esimerkki on kirjoitusvirheiden tarkistin. Diff putkitetaan Claudelle, joten se ei tarvitse Bash-lupaa diffin lukemiseen:
{
"scripts": {
"lint:claude": "git diff main | claude -p \"Olet kirjoitusvirheiden tarkistaja. Kerro jokaisesta tämän diffin kirjoitusvirheestä tiedosto:rivi yhdellä rivillä ja virhe seuraavalla. Älä palauta muuta.\""
}
}
Ajo tapahtuu komennolla npm run lint:claude. Escapetut lainausmerkit pitävät skriptin toimivana myös Windowsissa.
Tulostemuodot: text, json ja stream-json
Lippu --output-format päättää, missä muodossa tulos tulee:
texton oletus: pelkkä vastaustekstijsonpalauttaa yhden JSON-olion, jossa on tulos, session ID ja metatietojastream-jsonpalauttaa rivi kerrallaan JSON-tapahtumia sitä mukaa kuin ajo etenee
JSON-muodossa vastausteksti on kentässä result, joten sen saa ulos jq:lla:
claude -p "Tiivistä tämä projekti" --output-format json | jq -r '.result'
Samassa JSON-vastauksessa on kenttä total_cost_usd ja mallikohtainen kustannuserittely. Skripti voi siis seurata kulutusta itse. Dokumentaatio muistuttaa, että luvut ovat asiakaspään arvioita ja voivat poiketa laskusta.
Tarkka rakenne --json-schemalla
Kun tulosta käsittelee koodi eikä ihminen, vapaamuotoinen teksti on hankalaa. Lippu --json-schema pakottaa tuloksen annettuun JSON Schemaan:
claude -p "Listaa auth.py:n päätason funktioiden nimet" \
--output-format json \
--json-schema '{"type":"object","properties":{"functions":{"type":"array","items":{"type":"string"}}},"required":["functions"]}' \
| jq '.structured_output'
Rakenteinen tulos on kentässä structured_output. Jos ajo päättyy ilman kelvollista tulosta, esimerkiksi koska Claude kieltäytyi, kenttää ei ole lainkaan. Skriptin kannattaa siis tarkistaa kentän olemassaolo ennen käyttöä.
Striimaus
Reaaliaikaista tulosta varten stream-json yhdistetään lippuihin --verbose ja --include-partial-messages:
claude -p "Selitä rekursio" --output-format stream-json --verbose --include-partial-messages
Jokainen rivi on yksi tapahtuma. Viimeinen rivi on result-viesti, jossa on lopullinen vastaus, kustannus ja session tiedot.
Oikeudet headless-ajossa
Tämä on kohta, jossa useimmat CI-kokeilut kaatuvat ensimmäisellä kerralla. Interaktiivisessa sessiossa Claude kysyy luvan, ja sinä vastaat. Headless-ajossa kukaan ei vastaa.
Uusissa versioissa (v2.1.302 alkaen) claude -p käynnistyy Manual-tilassa, jos tilaa ei ole asetettu. Silloin jokainen kutsu, joka vaatisi luvan, estetään. Claude ei siis saa ajaa testejä, ellei sitä ole erikseen sallittu.
Luvat annetaan etukäteen lipulla --allowedTools. Se käyttää samaa sääntösyntaksia kuin settings.json-tiedoston allow-lista, josta kerrotaan tarkemmin oikeuksien ja asetusten oppaassa:
claude -p "Aja testit ja korjaa epäonnistuneet" \
--allowedTools "Bash(npm test *),Read,Edit"
Tarkempi rajaus on yleensä parempi kuin pelkkä Bash. Tässä Claude saa tehdä commitin mutta ei pushata:
claude -p "Katso stagetut muutokset ja tee niistä commit kuvaavalla viestillä" \
--allowedTools "Bash(git diff *),Bash(git log *),Bash(git status *),Bash(git commit *)"
Välilyönti ennen tähteä on tärkeä. Bash(git diff *) osuu git diff -alkuisiin komentoihin, mutta ilman välilyöntiä Bash(git diff*) osuisi myös komentoon git diff-index.
Oikeustila koko ajolle
Yksittäisten työkalujen sijaan koko ajolle voi antaa pohjan lipulla --permission-mode:
dontAsk: kaikki, mikä kysyisi, estetään. Sallitut työkalut ja lukeminen työhakemistossa toimivat. Tämä on lukitun CI-ajon tila.acceptEdits: tiedostomuokkaukset ja yleiset tiedostokomennot menevät läpi, muut komennot tarvitsevat edelleen allow-säännön.auto: erillinen luokittelijamalli tarkistaa toimenpiteet ihmisen sijaan.
Dokumentaation CI-esimerkki yhdistää kaksi ensimmäistä ajatusta:
claude -p "Aja testisarja" --permission-mode dontAsk --allowedTools "Bash(npm test)" "Read"
Ajastetuissa töissä hyödyllinen on myös --permission-prompts none. Se kertoo Claudelle, ettei kukaan voi hyväksyä pyyntöjä, joten Claude ei yritä samaa estettyä toimintoa uudelleen. Lippu vaatii version v2.1.259 tai uudemman.
--dangerously-skip-permissions vain kontissa
Lippu --dangerously-skip-permissions ohittaa kyselyt kokonaan. Dokumentaatio sallii sen täysin valvomattomaan ajoon vain kontissa, virtuaalikoneessa tai sandbox-ympäristössä, ja Linuxilla ja macOS:llä ei-root-käyttäjänä. Tavalliseen CI-ajoon riittää yleensä dontAsk ja tarkka allow-lista.
--bare: sama tulos joka koneella
Ilman lisälippuja claude -p lataa kaiken samoin kuin interaktiivinen sessio: hookit, skillit, omat komennot, subagentit, pluginit, MCP-palvelimet, automaattisen muistin ja CLAUDE.md-tiedoston. Työhakemiston ja ~/.claude-kansion sisältö vaikuttaa siis ajoon.
Lippu --bare ohittaa tämän automaattisen latauksen. Ajo käynnistyy nopeammin ja tuottaa saman tuloksen koneesta riippumatta, koska kollegan ~/.claude-kansiossa oleva hook tai projektin .mcp.json-palvelin ei tule mukaan.
claude --bare -p "Tiivistä README.md" --allowedTools "Read"
Pari asiaa kannattaa tietää ennen käyttöä:
- Bare-tila ei käytä tilauksesi kirjautumista. Anthropic API:a varten asetetaan ympäristömuuttuja
ANTHROPIC_API_KEY. - Tarvittava konteksti annetaan lipuilla:
--append-system-prompt,--settings,--mcp-configja--agents. - Hookit eivät aja bare-tilassa, vaikka ne annettaisiin
--settings-lipulla.
Dokumentaation mukaan --bare on suositeltu tila skripteille ja SDK-kutsuille, ja siitä tulee tulevassa versiossa -p:n oletus.
Vieraan repositorion kanssa varovasti
Tämä liittyy edelliseen ja on helppo unohtaa. Ilman --bare-lippua -p-ajo ajaa projektin .claude/settings.json-tiedoston hookit ja yhdistää .mcp.json-palvelimiin, vaikka et olisi koskaan hyväksynyt kansiota. Headless-ajo ei näytä workspace trust -ikkunaa.
Jos ajat claude -p:tä repositoriossa, jota et ole itse kirjoittanut, dokumentaatio antaa kolme keinoa:
--setting-sources user, jolloin projektin asetuksia ja.mcp.json-tiedostoa ei lueta--bare, jolloin projektin hookit, skillit, subagentit, pluginit ja MCP-palvelimet jäävät pois--settings '{"disableAllHooks": true}', joka sammuttaa hookit tältä ajolta
Keskustelun jatkaminen ja ajon rajat
Headless-ajon ei tarvitse olla yksittäinen. --continue jatkaa viimeisintä keskustelua:
claude -p "Käy koodipohja läpi suorituskykyongelmien varalta"
claude -p "Keskity nyt tietokantakyselyihin" --continue
claude -p "Tee yhteenveto kaikista löydöistä" --continue
Jos ajoja on useita rinnakkain, session ID otetaan talteen ja annetaan --resume-lipulle:
session_id=$(claude -p "Aloita katselmointi" --output-format json | jq -r '.session_id')
claude -p "Jatka katselmointia" --resume "$session_id"
Valvomattomalle ajolle kannattaa asettaa katto. --max-turns rajaa agenttisilmukan kierrosten määrän, ja --max-budget-usd pysäyttää ajon, kun arvioitu kulutus ylittää annetun summan. Kumpikin toimii vain print-tilassa.
Kun keskustelua jatketaan --continue- tai --resume-lipulla, JSON-tuloksen kustannus kattaa koko keskustelun, myös aiempien ajojen kulutuksen. Tämä kannattaa muistaa, jos skripti laskee kuluja yhteen.
Taustatyöt ja ajon pysäyttäminen
claude -p ei välttämättä pääty heti, kun Claude on vastannut. Jos Claude käynnisti taustakomennon tai taustalla toimivan subagentin, ajo jää odottamaan sitä. Oletuksena Claude Code pysäyttää jäljellä olevat taustatyöt, kun odotusta on kestänyt 10 minuuttia ilman tapahtumia, paitsi jos pääkeskustelun käynnistämä taustakomento on yhä käynnissä. Rajaa voi muuttaa ympäristömuuttujalla CLAUDE_CODE_PRINT_BG_WAIT_CEILING_MS.
Jos ajo pysäytetään SIGTERM-signaalilla, esimerkiksi CI:n aikakatkaisussa, Claude Code päättyy koodiin 143. Kesken ollut vuoro jää silloin kesken eikä tulosta tallenneta. Tämä on hyvä tietää, kun luet CI-lokista outoa exit-koodia.
Esimerkki: yöllinen testiajo
Edellä käsitellyistä lipuista saa koottua skriptin, joka ajaa testit, korjaa yksinkertaiset virheet ja tallentaa raportin. Kaikki luvat on annettu etukäteen, ajolla on katto, ja tulos on koneluettavaa:
#!/usr/bin/env bash
set -euo pipefail
claude --bare -p "Aja testit komennolla npm test. Jos jokin testi epäonnistuu selvän virheen takia, korjaa se. Älä muuta testejä. Kerro lopuksi, mitä muutit ja mitkä testit ovat yhä punaisella." \
--permission-mode dontAsk \
--allowedTools "Bash(npm test *),Read,Edit" \
--max-turns 20 \
--output-format json > tulos.json
jq -r '.result' tulos.json > raportti.md
jq -r '.total_cost_usd' tulos.json
--bare vaatii tässä ANTHROPIC_API_KEY-muuttujan, ja set -e pysäyttää skriptin, jos Claude Code päättyy virheeseen. Muutokset jäävät työhakemistoon, joten ne voi katsoa git diff -komennolla ennen kuin mitään viedään eteenpäin.
Oman ohjeen voi lisätä Claude Coden oletusohjeiden perään lipulla --append-system-prompt. Tämä skripti hakee pull requestin diffin ja pyytää tietoturvakatselmoinnin:
gh pr diff "$1" | claude -p \
--append-system-prompt "Olet tietoturva-asiantuntija. Katselmoi haavoittuvuuksien varalta." \
--output-format json
-p-tilassa toimivat myös omat skillit ja komennot: kirjoita /skillin-nimi promptiin, ja Claude Code avaa sen ennen ajoa. Pelkästään terminaalissa toimivat komennot kuten /login eivät ole käytössä. Skillien tekemisestä kerrotaan skills-oppaassa.
Claude Code GitHub Actions
GitHub Actions -integraatio on oma GitHub Action, anthropics/claude-code-action, joka ajaa Claude Codea repositorion workflow'ssa. Se on rakennettu Agent SDK:n päälle.
Asennus
Nopein tapa on ajaa Claude Codessa repositorion kansiossa:
/install-github-app
Komento asentaa Claude GitHub Appin, tallentaa avaimen repositorion secretiksi ja puskee haaran workflow-tiedostoineen. Selain avautuu valmiin pull requestin kohdalle, ja kun se on mergetty, @claude toimii repositoriossa. Asennus vaatii admin-oikeudet repositorioon, asennetun ja kirjautuneen GitHub CLI:n (gh auth login), ja se toimii vain github.comin repositorioille.
Käsin asennus tehdään kolmessa vaiheessa:
- Asenna Claude GitHub App repositorioon.
- Lisää secret:
ANTHROPIC_API_KEYClaude Consolen API-avaimelle taiCLAUDE_CODE_OAUTH_TOKENtilauksen tokenille, jonka saa komennollaclaude setup-token. - Kopioi
examples/claude.ymlaction-repositoriosta kansioon.github/workflows/.
Kaksi tapaa toimia
Action päättelee toimintatavan workflow'n asetuksista:
- Interaktiivinen tila: jos
prompt-syötettä ei ole, Claude odottaa mainintaa@claudeissuen tai pull requestin kommentissa ja vastaa siihen kommentilla. - Automaatiotila: jos
prompton annettu, Claude ajaa sen heti ilman mainintaa. Tulokset menevät oletuksena workflow-ajon lokiin.
Tämä workflow vastaa @claude-mainintoihin:
name: Claude Code
on:
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]
jobs:
claude:
if: contains(github.event.comment.body, '@claude')
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
issues: write
id-token: write
actions: read
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 1
- uses: anthropics/claude-code-action@v1
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
Rivi if estää runnerin käynnistymisen kommenteista, joissa ei mainita Claudea. actions: read antaa Clauden lukea pull requestin CI-tulokset.
Kommentti voi olla esimerkiksi:
@claude korjaa TypeErrorin käyttäjän dashboard-komponentissa
Kuka voi käynnistää ajon
Action tarkistaa käynnistäjän ennen kuin Claude aloittaa. Issue- ja pull request -tapahtumissa käynnistäjällä pitää olla repositorioon kirjoitusoikeus. Botit hylätään kaikissa tapahtumissa, ellei niitä ole listattu allowed_bots-syötteeseen. Näin botit eivät voi käynnistää Claudea silmukassa toistensa kommenteista.
Skillin ajaminen promptina
prompt-syöte hyväksyy tavallisen tekstin lisäksi skillin kutsun. Jos skill on repositorion kansiossa .claude/skills/, workflow'ssa ajetaan ensin actions/checkout, jotta skillin tiedostot ovat runnerilla, ja promptiksi annetaan /skillin-nimi. Pluginiin paketoidun skillin voi asentaa syötteillä plugin_marketplaces ja plugins.
Julkisissa repositorioissa GitHub ei anna secretejä forkeista tulleiden pull requestien ajoille. Katselmointi-workflow toimii siis vain saman repositorion haaroista tehdyille pull requesteille.
Ajastettu ajo
Automaatiotilassa Action toimii millä tahansa GitHub-tapahtumalla, myös cron-ajastuksella. Pelkällä tekstipromptilla Claudella ei ole shell- tai GitHub API -pääsyä, ennen kuin työkalut sallitaan claude_args-syötteessä:
name: Päivän raportti
on:
schedule:
- cron: "0 9 * * *"
jobs:
report:
runs-on: ubuntu-latest
permissions:
contents: read
issues: read
id-token: write
steps:
- uses: anthropics/claude-code-action@v1
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
prompt: "Tee yhteenveto eilisistä commiteista ja avoimista issueista"
claude_args: |
--model sonnet
--allowedTools "mcp__github__list_commits,mcp__github__list_issues"
claude_args ottaa vastaan mitä tahansa Claude Coden CLI-lippuja, joten kaikki edellä käsitellyt rajat toimivat myös täällä.
GitHub ajaa ajastetut workflow't vain oletushaarasta. Julkisissa repositorioissa GitHub myös sammuttaa ajastuksen, jos repositoriossa ei ole tapahtunut mitään 60 päivään.
Kustannukset ja sudenkuopat
Jokainen ajo kuluttaa kahta asiaa: GitHub Actions -minuutteja ja API-tokeneita. OAuth-tokenilla ajot käyttävät tilaustasi API-laskutuksen sijaan. Dokumentaation vinkit kulujen hillitsemiseen:
- Kirjoita
@claude-pyynnöt tarkasti, jolloin kierroksia tarvitaan vähemmän. - Pidä CLAUDE.md lyhyenä, koska Claude lukee sen joka ajossa. CLAUDE.md-oppaassa on ohjeet hyvään tiedostoon.
- Aseta
--max-turnsclaude_args-syötteeseen. - Käytä workflow-tason aikakatkaisuja ja GitHubin concurrency-asetuksia.
Kaksi sudenkuoppaa kannattaa tietää etukäteen. Ensinnäkin GitHub ei käynnistä workflow'ta oletus-GITHUB_TOKENilla tehdyistä commiteista, joten jos annat Actionille github_token-syötteeksi repositorion oman GITHUB_TOKEN-secretin, Clauden commitit eivät aja CI:tä. Ilman tätä syötettä Action tunnistautuu Claude GitHub Appina. Toiseksi maininnan pitää olla kokonainen sana @claude, ei /claude tai @claude-bot, ja kommentoijalla pitää olla repositorioon kirjoitusoikeus.
API-avaimia ei koskaan kirjoiteta suoraan repositorioon, vaan ne tallennetaan GitHub Secretsiin. GitLabille on oma integraationsa, jota tämä opas ei käsittele.
Agent SDK lyhyesti
Kun komentorivi ei riitä, Agent SDK antaa saman agentin kirjastona Pythoniin ja TypeScriptiin. Sillä Claude Coden agentti upotetaan omaan sovellukseen: työkalut, oikeudet, sessiot, hookit, subagentit ja MCP ovat käytössä.
Kolme tässä oppaassa käsiteltyä tapaa eroavat lähinnä siinä, missä agentti pyörii ja kuka sitä ohjaa:
| Tapa | Missä pyörii | Sopii |
|---|---|---|
claude -p | Omalla koneella tai CI-runnerilla komentona | Skriptit, npm-skriptit, CI-askeleet |
| GitHub Action | GitHubin runnerilla workflow'n osana | @claude-kommentit, katselmoinnit, ajastetut raportit |
| Agent SDK | Omassa Python- tai TypeScript-sovelluksessa | Omat työkalut, joissa hyväksynnät ja viestit käsitellään koodissa |
SDK:ssa työkalujen hyväksynnän voi hoitaa omassa koodissa canUseTool-callbackilla. Komentorivillä sama päätös tehdään etukäteen sääntöinä.
Asennus:
npm install @anthropic-ai/claude-agent-sdk
# tai Pythonille
pip install claude-agent-sdk
Pienin TypeScript-esimerkki, joka etsii ja korjaa bugeja tiedostosta:
import { query } from "@anthropic-ai/claude-agent-sdk";
for await (const message of query({
prompt: "Käy utils.py läpi kaatumisia aiheuttavien bugien varalta ja korjaa ne.",
options: {
allowedTools: ["Read", "Edit", "Glob"],
permissionMode: "acceptEdits"
}
})) {
if (message.type === "result") {
console.log(`Valmis: ${message.subtype}`);
}
}
query palauttaa asynkronisen iteraattorin, joka antaa viestejä sitä mukaa kuin Claude ajattelee, kutsuu työkaluja ja tekee päätöksiä. Optiot ovat samat kuin komentorivillä, vain eri muodossa: allowedTools vastaa lippua --allowedTools ja permissionMode lippua --permission-mode.
Pari käytännön huomiota. SDK:n kanssa käytetään API-avainta, eikä kolmannen osapuolen tuotteissa saa tarjota claude.ai-kirjautumista ilman Anthropicin lupaa. Jos ohjelmointikieli on jokin muu kuin Python tai TypeScript, dokumentaatio neuvoo ajamaan claude -p --output-format json -komentoa aliprosessina.
Mistä aloittaa?
Headless-käytön voi aloittaa pienesti ja laajentaa vasta, kun perusasiat toimivat:
- Kokeile paikallisesti. Putkita jokin loki tai diff komentoon
claude -pja katso, mitä tulee ulos. - Tee yksi npm-skripti. Kirjoitusvirheiden tarkistin tai muutosten tiivistäjä on hyvä ensimmäinen.
- Lisää JSON-tuloste. Kun skripti lukee tuloksen, ota käyttöön
--output-format jsonja tarvittaessa--json-schema. - Rajaa oikeudet. CI-ajoon
--permission-mode dontAsk, tarkka--allowedTools-lista,--bareja--max-turns. - Asenna GitHub Actions.
/install-github-appja ensimmäinen@claude-kommentti testiksi.
Kun haluat ajaa useaa Claude-sessiota samanaikaisesti omalla koneellasi, katso git worktree -opas. Hookeilla voi automatisoida asioita myös headless-ajon sisällä, ja niistä kerrotaan hooks-oppaassa.
Automaatioon ja rinnakkaisiin sessioihin liittyvät artikkelit on koottu Claude Code -oppaiden sivulle.