Sessions

A session is one running copy of your stack in the cloud: the template's services, a shell, a browser and your code. This page follows a session through its life: starting it, checking on it, stopping and starting it again, starting it on a schedule, the automatic stops, ending it, resetting its data, switching branches, leaving a cloud session and sharing it with a teammate.

Error codes on this page link to their entry in troubleshooting.md.

Start a session

Terminal
ciresk dev up                      # the template for the directory you are in
ciresk dev up app                  # a named template
ciresk dev up app --preset light --param api-workers=4
ciresk dev up app --remote         # a cloud session with no local worktree behind it

Each worktree gets its own session. ciresk dev up creates it, or returns the one that is already running for this worktree on this machine, so running it twice gives you the same session back. templates.md says which template a bare ciresk dev up picks.

up waits until every service is ready and prints the session:

  • the label and state, with the primary URL (http://<label>.localhost:<port>)
  • one URL per http port, and 127.0.0.1:<local> -> <port> for each tcp port
  • the session id, the generation (the number of the last sync of your worktree) and whether it is in sync
  • the parameter values and preset, when the template declares parameters
  • each service and its state

While it waits, up prints a progress line on stderr every 10 seconds. When no worker is free, the session is pending and the line says what it waits for (a worker starting, for example). --timeout counts from the last time a starting service moved, so a long install is waited through. A service that fails or stalls ends the wait with service_not_ready (exit 1) and names the service; ciresk dev logs <service> shows why.

FlagDefaultWhat it does
<template>picked from the directoryThe template in .ciresk/dev.yaml to start.
--recreateoffEnds the running session and starts a new one in its place, with the same label.
--remoteoffA cloud session: it starts from the repository's trunk, not from your worktree, and holds its own edits. See Cloud sessions.
--lazyoffFetches file content on first read instead of before the start. Takes effect only when the template's workspace.materialise is lazy.
--idle <duration>the template's or your organization'sThis session's idle stop, such as 30m or 2h, within your organization's bounds. See Idle stop.
--param <name>=<value>the parameter's defaultA template parameter's value. Repeatable.
--preset <name>noneOne of the template's presets. Its values apply before --param.
--timeout <duration>120sHow long to wait with nothing moving before up gives up with not_ready (exit 7). The session keeps starting.
--no-waitoffReturns once the session is created.

Durations are a whole number with ms, s, m or h; a bare number is seconds. Every command also takes --json for one JSON answer on stdout and --quiet for no progress lines.

Parameters and presets

A template may declare typed parameters and named presets (templates.md). A session's value of each parameter is its default, then the preset's value, then the value you pass with --param. A value the template does not allow is refused with parameter_invalid (exit 2), and each finding says what the parameter takes. The session records the values it runs with; ciresk dev status shows them as parameters: seed=none, api-workers=4 (preset light).

With a session running, ciresk dev up compares only the parameters you name, directly or through --preset:

You runResult
ciresk dev up with no --param or --presetThe running session, as it is.
A different value of a parameter marked mutableup ends the session and starts a new one with the new values, and says so.
A different value of an immutable parameterRefused with parameter_immutable (exit 4), naming the parameters. Run the same command with --recreate.

An agent that calls the dev_session_up MCP tool gets parameters_changed or parameter_immutable instead, and passes recreate: true to apply the change; nothing restarts a session behind your back.

When the template changes

A running session keeps the template it started with. When you edit .ciresk/dev.yaml, ciresk dev status says the file changed, and the next ciresk dev up starts the session again on the new file. Asking a running session for another template (ciresk dev up other) is refused with template_mismatch (exit 4); add --recreate to replace it.

Refusals at up

CodeExitMeaning
no_template2No .ciresk/dev.yaml, no template of that name, or no way to pick one.
template_invalid2The template fails validation; the answer lists every finding (templates.md).
parameter_invalid2--param or --preset names something the template does not declare, or a value its type refuses.
parameter_immutable, template_mismatch4See above.
person_session_limit, org_session_limit4You, or your organization, already hold the most live sessions allowed (10 per person and 100 per organization unless an admin changed them). ciresk dev status --all lists yours; end one you are done with.
idle_out_of_bounds4--idle is outside your organization's range; the answer names both bounds.
session_too_large4The template reserves more memory or CPUs than your organization allows one session.
egress_denied4A required egress row is not allowed (egress.md).
template_not_published4Your organization runs only published template versions, and this file is not the promoted one.
policy_local_sync_denied4Your organization does not allow syncing a local worktree. Use ciresk dev up --remote.
budget_exceeded5Your budget or your organization's is spent (budgets.md).
cell_session_limit8The region is full. Try again later.

Check on a session

Terminal
ciresk dev status            # this worktree's session
ciresk dev status --wait     # wait up to 55 s until it is ready
ciresk dev status --all      # every live session you own or that is shared with you
ciresk dev open              # the primary URL in your browser (--print only prints it)

status shows the same lines as up, plus what needs you first (questions and approvals from your agents, and a lifetime warning), the session's health and its next step. It also shows your role on a session shared with you, the organization policy the session runs under and, when you have dotfiles, whether they were applied.

status --all is the list of your sessions: one line each with the session id, label, state and primary URL. It shows live sessions (everything but stopped and failed, so paused and lost sessions are included), yours and those shared with you. The API lists ended ones too, GET /v1/dev/sessions?state=stopped, and started_by=agent or started_by=person keeps only the sessions an agent or a person opened. A person or service key with dev:audit.read lists every session of the organization with scope=org (see /api/dev).

Session states

StateWhat it means
pendingWaiting for a worker. state_reason says why, such as no_capacity, worker_starting or no_worker.
startingA worker holds it: it receives your first sync, runs the prepare steps and starts the services.
readyEvery service is ready.
degradedRunning, but a service is not well; status names it and its next step.
disconnectedThe worker stopped reporting. Nothing is stopped; it comes back when the worker does. After 15 minutes it becomes lost.
lostThe worker is gone. The next ciresk dev up in the worktree places the session again on another worker.
stoppingA stop was asked for and the worker is stopping it.
pausedA cloud session stopped and kept with its checkpoint, using no compute. ciresk dev start brings it back.
stoppedEnded. state_reason says why: requested, idle, max_lifetime, budget, kill, access_changed, recreated, checkpoint_expired and others.
failedEnded by a failure; state_reason holds its code, such as start_failed or disk_full.

While a session starts, phase narrows its state down for a client: placing, syncing, starting or ready.

Idle stop

A session is active while your worktree syncs to it, a stream to it (a URL, a port, SSH) is open, or a command names it. After its idle time without activity it stops. A session that gets no first sync within 60 seconds of starting stops too.

The idle time is the template's idle (60 minutes unless the template says otherwise), or your organization's default when it sets one, moved into your organization's range (5 minutes to 8 hours unless an admin narrowed it). ciresk dev up --idle 2h chooses your own for one session; outside the range it is refused with idle_out_of_bounds.

What an idle stop does depends on where the session's code lives:

  • A session on your worktree ends: its containers and volumes are deleted, and your code is safe in your worktree. The next ciresk dev up starts a fresh one.
  • A cloud session is paused with its checkpoint (see Stop and start a cloud session), unless your organization set automatic stops to end sessions. In that case a cloud session started without --idle gets your organization's maximum idle time instead, since it holds the only copy of its edits.

Maximum lifetime

Your organization can cap how long any session runs, whatever its activity (between 1 hour and 7 days; no cap by default). Before the end, by default one hour before, the session raises a need of kind expiring to you, which ciresk dev status, ciresk dev watch and ciresk dev needs show. At the end the session stops like an idle stop: a session on your worktree ends, and a cloud session is paused. ciresk dev up --recreate starts a fresh one with a new lifetime. A budget's hard stop works the same way (budgets.md).

Stop and start a cloud session

Terminal
ciresk dev stop     # checkpoint the workspace, release the compute, keep the session
ciresk dev start    # place it again from that checkpoint

stop and start are for cloud sessions (--remote, or a session started from the console). A session on your worktree has nothing to keep, since its code is on your machine: stop refuses it with not_cloud_writer (exit 1), and ciresk dev down ends it instead.

ciresk dev stop freezes the session, stores a checkpoint of its workspace, and answers once the session is paused, with the time of its checkpoint and the data volumes it did not keep. It waits up to 90 seconds; after that it answers stopping and the session is paused in the background. If the final checkpoint fails, the session pauses on the previous one, at most about a minute older. Stopping a session that already ended answers session_ended.

A paused session keeps:

  • its id, so links to it keep working
  • its workspace files, as of the checkpoint
  • its members and their roles, its device grants, open needs and journal
  • its parameter values
  • its branch: nothing else writes the session's branch while it is paused

It does not keep running processes, memory, or the data in service volumes such as a database: the checkpoint holds the workspace only, so the template's data volumes start empty and their seed jobs run again. ciresk dev stop names those volumes, and the session's journal records them. Web preview links lapse, and the session's SSH host key changes; ciresk dev ssh and your editor pick up the new key by themselves.

A paused session runs nothing, reserves nothing from your budget and does not count toward the live-session limits. It lasts until 30 days after the session was created, when its checkpoint expires. Before that, by default one hour before, you get an expiring need, and at that time the session ends with state_reason: checkpoint_expired.

Terminal
ciresk dev start [<template>] [--timeout 120s] [--no-wait]

ciresk dev start is ciresk dev up --remote for the worktree's paused session: it is admitted like a new session (your session limits and budget), takes your organization's current policy and a fresh maximum lifetime, and is placed again from its checkpoint, on whichever worker takes it. It keeps the parameters it was created with. ciresk dev up --remote in the same worktree starts it the same way, and ciresk dev up --remote --recreate ends it and starts a new session from the trunk. A session that is already running answers as it is. One that is stopping, has ended, or was paused by the kill switch answers not_paused (exit 1): a killed session never starts again. A plain ciresk dev up, without --remote, does not start a paused cloud session: it starts a session on your worktree.

Retrying stop and start safely

The API's stop, pause and start calls (POST /v1/dev/sessions/{id}/stop, /pause and /start) take an Idempotency-Key header. A retry with the same key, method, path and body within 24 hours gets the first answer again instead of acting twice; the same key with another body is refused with idempotency_key_reused (422), and a key that is empty or over 255 characters with invalid_idempotency_key (400). Without the header the calls still act once per state change. ciresk dev stop and ciresk dev down send a fresh key on every run, and --idempotency-key <key> lets you choose it, so a retried command never stops twice. ciresk dev start and ciresk dev up send their own key.

Start on a schedule

Terminal
ciresk dev schedule set 08:30 --tz Europe/Copenhagen               # this worktree's cloud session, weekdays
ciresk dev schedule set 08:30 --days mon,wed,fri --tz Europe/Berlin
ciresk dev schedule set 09:00 --template app --tz America/New_York # every paused session of yours of this template
ciresk dev schedule show                                           # this worktree's session's schedule
ciresk dev schedule show --all                                     # every schedule of yours
ciresk dev schedule clear [--template app]

A schedule has a paused cloud session ready by a local time on the days you choose, so a session you stopped in the evening is waiting for you in the morning. It starts the session 5 minutes before the time, from its checkpoint, through the same admission as ciresk dev start: your session limits and budget apply, and a refusal is recorded instead of a start. A session that is not paused at that time (still running, for example) is left as it is. A start more than 15 minutes late (when your organization was suspended at the time, for example) is skipped and recorded as missed.

Argument or flagDefaultWhat it does
<HH:MM>requiredThe local time the session is ready by, 00:00 to 23:59.
--daysweekdaysmon,tue,wed,thu,fri,sat,sun in any combination, weekdays or every-day.
--tzthe TZ environment variableAn IANA time zone, such as Europe/Copenhagen. Without --tz or TZ the command refuses, since it cannot know your zone.
--template <name>this worktree's sessionSchedules every paused session of yours with this template name instead.

Without --template, the schedule belongs to this worktree's session, which must be a cloud session (a session on your worktree is never paused, so set refuses it with not_cloud_writer) and must not have ended (session_ended). Setting a schedule again replaces it, so running the same set twice is harmless; clear removes one and leaves the sessions as they are, and clearing twice is harmless too. A session's schedule is removed at its next start time once the session has ended.

schedule show prints when each schedule is ready, its next start (in UTC) and what its last run did: the sessions it started, the ones it could not start with the reason, or that it was missed. An agent manages schedules through the same capability with the MCP tools; the person who owns the session is the one it starts for.

End a session

Terminal
ciresk dev down

down ends this worktree's session and releases everything it held. Only the session's owner can end it. A paused session ends too. Afterwards ciresk dev up starts a new one. A cloud session stores a last checkpoint as it stops, so ciresk dev up --remote can still continue it (below). --idempotency-key <key> makes a retried down act once.

Reset data to its seed

Terminal
ciresk dev reset                    # every data volume
ciresk dev reset --volume postgres  # only some; repeatable
ciresk dev reset --rebuild          # empty the volumes and run the seed jobs again

A template that declares data (templates.md) gets a snapshot of its data volumes once its seed jobs have completed. reset stops the services that use those volumes, puts the volumes back to the snapshot, typically in about a second, and starts the services again. Running commands get 30 seconds to finish before they are interrupted, and new ones wait until the reset is done. reset waits up to 10 minutes and prints which volumes it restored and which services it restarted.

When a file under the template's data.inputs changes (a new migration, often after a branch switch), the snapshot is stale: ciresk dev status says so and names ciresk dev reset --rebuild, and a reset rebuilds instead of restoring. Nothing resets your data by itself. The session's owner and use members can reset.

Switch branches

Switch branches in your worktree as you always do. The session follows:

  • While git holds .git/index.lock (a checkout, a rebase or a commit in progress), nothing is synced, so the session never sees half a switch.
  • When the branch changed, the switch is synced as one change once git is done and your worktree has been quiet for 200 milliseconds. The session moves to the new branch first.
  • A prepare step whose inputs changed (a lockfile, for example) runs again, and the services that wait for it restart. Other services take the change through their own watchers. ciresk dev wait --gen <n> waits for all of it.
  • A change under data.inputs marks the seed stale (above).

If another session already works on the new branch, the switch is refused with writer_conflict: the session gets nothing of the new branch, sync pauses, and it is tried again every 10 seconds. A detached HEAD leaves the session on its last branch.

In a cloud session, switch branches with git inside the session.

Cloud sessions

ciresk dev up --remote starts a session from the repository's trunk with no local worktree behind it: the session holds its own edits, which you make with ciresk dev exec, ciresk dev ssh or your editor (editors.md). Use it when you want work to go on without your machine, or when your organization does not allow syncing a local worktree.

Its edits leave the session in these ways:

CommandWhat it does
ciresk dev checkpointStores the workspace as a checkpoint now. The session also takes them on its own as you work.
ciresk dev push [--base <branch>] [--pr] [--title <text>]Pushes the checkpoint as one commit to the session's own branch, and with --pr opens a pull request into --base. See git.md.
ciresk dev stopKeeps the whole session, paused, until ciresk dev start.
ciresk dev up --remote after the session endedContinues the newest ended cloud session of this worktree from its last checkpoint, as a new session on the same branch. A session ended by the kill switch is not continued. Add --recreate to start from the trunk instead.

Share a session

You can give a member of your organization access to one of your sessions, to follow along or to work in it with you:

Terminal
ciresk dev share [email protected] --role view
ciresk dev share [email protected] --role use
ciresk dev share --list
ciresk dev share --revoke devm_0192...
RoleWhat the member can do
viewStatus, logs, the journal (ciresk dev watch), code search, the session's http ports, and the read-only shell (ciresk dev ssh --read-only). No exec, no browser, no data operations, no editor.
useEverything but sharing, stopping and syncing: exec, restart, reset, test logins (ciresk dev login <identity> --cookies or --revoke), the browser, the read-write shell and editor, and every declared port.

Only you, the owner, can share, and only as a person: an agent cannot share a session. The member is named by e-mail address or user id. A share is refused when the role is above your organization's sharing ceiling (sharing_ceiling, exit 4; view unless an admin changed it), when the person is not another member of your organization (not_a_member), when the member may not read every path the session holds (member_view_narrower), or with use on a session whose agents act for you in other products (delegated_session). A session that has ended cannot be shared (session_not_running). admin.md covers the ceiling.

--revoke takes the member id that --list prints. It ends the member's access at once: their open connections close.

Join a session shared with you

The member runs, on their own machine:

Terminal
ciresk dev attach devs_0192...        # the session id the owner gives you
ciresk dev status --all               # the session, with your role
ciresk dev ssh <label>                # use: the read-write shell
ciresk dev ssh <label> --read-only    # view or use: the read-only shell
ciresk dev watch --session devs_0192... --follow

attach grants your device access and has your daemon serve the session, so its URLs work on your machine too. An attached device never syncs files into the session; only the owner's worktree does. ciresk dev watch follows what happens in the session, one line per event: syncs with the paths they changed, commands and their exit codes, restarts, resets and logins. ciresk dev attach <session_id> --revoke <grant_id> takes your device off again.