kkārya
docs / start

Getting started

Install Karya, point it at a model, and run a first task inside a repository. Karya is pre-1.0; commands and variables may change before 1.0.

Install

Karya is a single Go binary. Install it with the Go toolchain:

$ go install github.com/prateek041/karya/cmd/karya@latest

A Homebrew tap and prebuilt release binaries are on the roadmap.

Configure

Karya reads its configuration from environment variables. Only HARNESS_MODEL is required. The two limits are worth setting before your first session.

environment
HARNESS_MODELrequired
The model to run. The loop talks to it through one internal provider interface, so changing this value changes the model and nothing else.
HARNESS_BASE_URLoptional
Overrides the provider API endpoint.
HARNESS_MAX_STEPSsafety limit · conservative default
Maximum loop steps per session. When reached, the loop stops, reports the limit, and the session stays resumable.
HARNESS_MAX_COSTsession cost ceiling
Estimated cost ceiling for the session. When reached, the loop stops, reports the limit, and the session stays resumable.

For example, in your shell profile:

export HARNESS_MODEL=claude-sonnet-5
export HARNESS_MAX_STEPS=40
export HARNESS_MAX_COST=1.00

First task

Run karya inside a repository. That directory becomes the project root for the session and cannot change while the session runs. Use --root <path> to choose a different directory.

$ cd ~/src/tasks
$ karya

Type a bounded task in plain language and press enter. Karya streams the model's response, runs tool calls through the loop, and ends with a final answer and a usage and cost summary.

Karya~/src/tasks
›add a --json flag to the list command and make the tests pass
I'll read the list command, add a --json flag that encodes the tasks with encoding/json, then run the test suite.
· read cmd/list.go lines 1–86
RunE builds the table. Adding the flag and a JSON branch there.
editcmd/list.go
awaiting approval
@@ -14,7 +14,12 @@ func newListCmd() *cobra.Command
cmd := &cobra.Command{Use: "list"}
+ var asJSON bool
+ cmd.Flags().BoolVar(&asJSON, "json", false, "print as JSON")
cmd.RunE = func(c *cobra.Command, _ []string) error {
tasks := store.List()
+ if asJSON {
+ return json.NewEncoder(c.OutOrStdout()).Encode(tasks)
+ }
return printTable(c.OutOrStdout(), tasks)
[a]pprove[d]eny
waiting on you · [a]pprove [d]eny
›
arise, resolved to fight

Karya read cmd/list.go without asking. The edit is waiting: press a to approve or d to deny.

Approvals

Each tool has a fixed approval policy. Before anything that changes files or runs a command, Karya shows exactly what will happen and waits.

toolpolicyshown before running
readautoone-line trace
writeaskunified diff
editaskunified diff
bashaskexact command and timeout

Why every shell command asks

Karya does not try to sort shell commands into safe and unsafe. A command that looks read-only can start subprocesses, run a script, or redirect output into a file, and none of that is reliably visible from the command string. So bash always asks, and it always runs inside the sandbox.

Denying a call

A denial is sent back to the model as a structured tool result. The model can propose a different approach or stop and explain.

bashproject root
✕ denied
$ go test ./... -run TestList -count=1
timeout 120s · sandboxed · network off

Resume a session

Every session is an append-only JSONL log stored outside the project. Logs are keyed to the repository's git remote URL rather than its local path, and contain no absolute paths or hostnames, so you can resume on any machine with a clone of the same repository.

$ karya --resume <session-id>

On resume, Karya compares what it recorded with the live repository and gives the model a drift note. The note covers:

HEADrecorded SHA against the current SHA
working treerecorded dirty flag against the current state
platformoperating system, if it changed
drift note
HEAD moved from a1b2c3 to d4e5f6, working tree dirty, platform changed from darwin to linux.

A session that stopped at HARNESS_MAX_STEPS or HARNESS_MAX_COST is resumable the same way.