Kodelet / Documentation
Automation
Resume and steer saved work, use persistent goals, connect workspace runners, and integrate Kodelet into scripts and applications.
On this page
Build automation around saved conversations and explicit execution context. The daemon owns the work; clients can connect, provide guidance, and disconnect without becoming its lifetime manager.
Find and continue a conversation
All user-facing runs are saved in the daemon’s conversation store, including --result-only runs. Find the conversation you need:
kodelet conversation list
kodelet conversation list --search "migration"
kodelet conversation show CONVERSATION_ID --format markdown
Replace CONVERSATION_ID with an ID from the listing. Search matches conversation IDs, working directories, first messages, and summaries.
Continue it with a new instruction:
kodelet run --resume CONVERSATION_ID "Continue the migration and run the focused tests."
Or follow the newest conversation in a known directory:
kodelet run --cwd "$PWD" --follow "Review the remaining work."
--follow requires --cwd or --runner. Resume retains the saved runner, directory, and model settings; it does not retarget the conversation to your current shell.
Rename a conversation without invoking the model:
kodelet run --resume CONVERSATION_ID "/rename Parser migration"
Move or branch a conversation
To try another approach while keeping the original transcript:
kodelet conversation fork CONVERSATION_ID
Forking is experimental. It copies history and execution context, resets cumulative usage, and does not inherit the active goal. It does not copy or isolate the working tree. Keep your Git work organized so two conversations do not unintentionally edit the same files.
To assign legacy history to a runner or move an existing conversation:
kodelet runner list
kodelet conversation move CONVERSATION_ID RUNNER_ID:/path/to/project
Use a registered runner ID and a directory on its host. Omit :/path/to/project to keep the stored directory. The command asks for confirmation; finish or stop active work first.
A move preserves history and settings but copies no files and does not check destination readiness. Offline registered runners can be selected. Ensure the destination contains the expected project before resuming.
Give longer work a goal
Set a persistent objective with a clear definition of done:
kodelet run "/goal Migrate the parser to the new format, update its documentation, and verify the parser tests pass."
The goal stays with the conversation through resume and context compaction. While active, it focuses subsequent work and supports automatic continuation. The agent marks it complete when finished or blocked when it cannot make meaningful progress without outside input or a change in conditions.
Ask the agent to pause automatic continuation, resume a paused goal, or clear the objective when your plans change. Setting a goal is not evidence that the work succeeded: review the changes and verification results before accepting completion.
Steer active work
Provide additional guidance without starting a second competing run:
kodelet steer --conversation-id CONVERSATION_ID "Keep the public API unchanged and add a regression test."
Or target active work in the current directory:
kodelet steer --cwd "$PWD" --follow "Prioritize the failing parser test before cleanup."
A steering message can be queued; acceptance is not proof the model has acted on it yet. In terminal chat, entering a message while a turn is running also queues steering. To change direction entirely, explicitly stop the active turn before starting replacement work.
Recover an interrupted request
Losing a connection does not cancel daemon-owned execution. If a run request is interrupted, its error gives the conversation and turn IDs needed to inspect the saved receipt:
kodelet conversation turn CONVERSATION_ID TURN_ID
This returns the submitted turn’s saved status and result as JSON. Inspect it before retrying: a disconnected client may have missed a result even though the task ran. If cancellation could not be confirmed, treat the work as potentially still active. See interface-specific stop controls.
Runners
The built-in runner handles local work. Add a standalone runner when the repository or tools live on another machine. Use a stable, authenticated server endpoint and keep client, daemon, and runner releases compatible.
For a server already configured for browser-approved runner enrollment, run the following from the project directory on the runner machine:
kodelet runner enroll --server https://kodelet.example --name project-runner
kodelet runner start --server https://kodelet.example
Replace the URL and display name with your deployment. Complete browser approval after enrollment; runner start then uses the saved workspace credential and remains running in the foreground. Supervise it separately if it must stay available after logout.
In token mode instead, supply the server’s separate runner credential through KODELET_RUNNER_AUTH_TOKEN before starting the runner. Do not supply a shared runner token in enrollment mode, and do not reuse a web/API token for runner authentication.
On the client, authenticate separately and select the registered runner:
kodelet auth login --server https://kodelet.example
kodelet runner list --server https://kodelet.example
kodelet run --server https://kodelet.example --runner project-runner "Inspect this repository and explain its test workflow."
The sign-in command above is for an OIDC-enabled server; token-authenticated deployments use a client API token instead. Runner commands do not automatically start a server.
A runner’s startup directory is its default workspace. --cwd can select another accessible directory on that runner’s host, not the client’s machine. A workspace selection is not a filesystem sandbox. Recipes, skills, extensions, Git operations, and shell commands execute using the selected runner’s resources and applicable policy.
Programmatic integration
Shell pipelines and saved JSON
For final text in a pipeline, use --result-only and check the command’s exit status:
git diff --cached | kodelet run --no-tools --no-extensions --result-only "Summarize the supplied staged diff for a reviewer."
This disables model tools and extension loading for the request. For unattended tasks that do need tools, configure a deliberately limited runner profile and ensure any enabled extensions do not require interactive input. Do not use a prompt alone as an access-control policy.
For structured saved data:
kodelet conversation list --json
kodelet conversation show CONVERSATION_ID --format json
These are snapshots, not live event streams. The old run --headless, --stream-deltas, and conversation stream interfaces are not supported. --no-save is also removed, with no transient replacement mode. Use ACP or the SDK for live structured events.
TypeScript sessions
Use Node.js 20 or newer, a compatible kodelet executable on PATH, and the SDK package. In your application project:
npm install kodelet
npm install --save-dev tsx
Save this as review.mts (the .mts extension selects an ES module):
import { Client } from "kodelet";
const client = new Client();
try {
const session = await client.createSession({ streaming: true });
session.on("assistant.message_delta", (event) => {
process.stdout.write(event.data.deltaContent);
});
session.on("tool.result", (event) => {
console.error("Tool finished:", event.data.toolName);
});
await session.runAndWait({
message: "Review this repository's test coverage. Do not edit files.",
});
} finally {
await client.close();
}
Run it from the project you want to inspect:
npx tsx review.mts
Client launches the thin kodelet acp client. The daemon still owns provider credentials and model execution. Select a named daemon profile with createSession({ profile: "your-profile" }); set server and runner on Client for a remote deployment, using normal client authentication. Session cwd values are interpreted on the runner.
Use session.runAndWait()’s returned content when you need only the final response. Streaming listeners expose assistant deltas and tool calls, updates, and results. A tool.update is a partial snapshot; tool.result is authoritative.
Always await client.close() to clean up the ACP subprocess, including on errors. Closing a client or session detaches; use session.cancel() when you intend to stop an active turn. Inline extensions, typed execution options, and compatibility requirements are covered in the customization guide and upstream SDK reference.